Skip to content

Commit e91d01d

Browse files
committed
Merge remote-tracking branch 'origin/main' into feature/console-hide-session-list
2 parents 3e7ba97 + 1856215 commit e91d01d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1369
-623
lines changed

.github/workflows/positron-python-ci.yml

+2
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ on:
55
push:
66
branches:
77
- main
8+
- 'prerelease/**'
89
paths:
910
- '.github/workflows/positron-python-ci.yml'
1011
- 'extensions/positron-python/**'
1112
pull_request:
1213
branches:
1314
- main
15+
- 'prerelease/**'
1416
paths:
1517
- '.github/workflows/positron-python-ci.yml'
1618
- 'extensions/positron-python/**'

build/gulpfile.vscode.js

+20-1
Original file line numberDiff line numberDiff line change
@@ -527,10 +527,29 @@ function patchWin32DependenciesTask(cwd) {
527527
const packageJson = JSON.parse(await fs.promises.readFile(path.join(cwd, 'resources', 'app', 'package.json'), 'utf8'));
528528
const product = JSON.parse(await fs.promises.readFile(path.join(cwd, 'resources', 'app', 'product.json'), 'utf8'));
529529
const baseVersion = packageJson.version.replace(/-.*$/, '');
530+
// --- Start Positron ---
531+
const year = new Date().getFullYear();
532+
const executablePath = `${product.nameShort}.exe`;
533+
534+
fancyLog('rcedit: ' + executablePath);
535+
536+
await rcedit(path.join(cwd, executablePath), {
537+
'file-version': product.positronVersion,
538+
'version-string': {
539+
'CompanyName': 'Posit Software, PBC',
540+
'FileDescription': product.nameLong,
541+
'FileVersion': product.positronVersion,
542+
'InternalName': executablePath,
543+
'LegalCopyright': `Copyright (C) 2022-${year} Posit Software, PBC. All rights reserved.`,
544+
'OriginalFilename': executablePath,
545+
'ProductName': product.nameLong,
546+
'ProductVersion': product.positronVersion,
547+
}
548+
});
530549

531550
await Promise.all(deps.map(async dep => {
532551
const basename = path.basename(dep);
533-
// --- Start Positron ---
552+
fancyLog('rcedit: ' + dep);
534553
try {
535554
await rcedit(path.join(cwd, dep), {
536555
'file-version': baseVersion,

build/lib/bootstrapExtensions.js

-7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build/lib/bootstrapExtensions.ts

-8
Original file line numberDiff line numberDiff line change
@@ -141,14 +141,6 @@ export function getBootstrapExtensions(): Promise<void> {
141141
const controlState = control[extension.name] || 'marketplace';
142142
control[extension.name] = controlState;
143143

144-
// Discard extensions intended for the web. The 'type' field isn't a
145-
// formal part of the extension definition but a custom field we use to
146-
// filter out web-only extensions (i.e. Posit Workbench)
147-
// @ts-ignore
148-
if (extension.type === 'reh-web') {
149-
continue;
150-
}
151-
152144
streams.push(syncExtension(extension, controlState));
153145
}
154146

extensions/positron-python/python_files/posit/pinned-test-requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ hvplot==0.11.2 ; python_version >= '3.9'
99
hvplot==0.8.0 ; python_version < '3.9'
1010
ibis-framework[duckdb]==10.0.0; python_version >= '3.10'
1111
ipykernel==6.29.5
12+
ipython<=8.31.0
1213
ipywidgets==8.1.5
1314
lightning==2.3.2
1415
matplotlib==3.7.4; python_version < '3.9'

extensions/positron-python/src/test/positron/testElectron.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*---------------------------------------------------------------------------------------------
2-
* Copyright (C) 2025 Posit Software, PBC. All rights reserved.
2+
* Copyright (C) 2024-2025 Posit Software, PBC. All rights reserved.
33
* Licensed under the Elastic License 2.0. See LICENSE.txt for license information.
44
*--------------------------------------------------------------------------------------------*/
55

extensions/positron-reticulate/src/extension.ts

+16-8
Original file line numberDiff line numberDiff line change
@@ -775,7 +775,7 @@ export class ReticulateProvider {
775775
this.context.subscriptions.push(positron.runtime.registerLanguageRuntimeManager('python', this.manager));
776776
}
777777

778-
async registerClient(client: positron.RuntimeClientInstance) {
778+
async registerClient(client: positron.RuntimeClientInstance, input?: string) {
779779
if (this._client) {
780780
this._client.dispose();
781781
}
@@ -786,15 +786,23 @@ export class ReticulateProvider {
786786
await this.manager.maybeRegisterReticulateRuntime();
787787
await positron.runtime.selectLanguageRuntime('reticulate');
788788

789+
if (input) {
790+
await positron.runtime.executeCode('python', input, true, true);
791+
}
792+
789793
this.manager._session?.onDidEndSession(() => {
790794
this._client?.dispose();
791795
this._client = undefined;
792796
});
793797

794-
this._client.onDidSendEvent((e) => {
798+
this._client.onDidSendEvent(async (e) => {
795799
const event = e.data as any;
796800
if (event.method === 'focus') {
797-
this.focusReticulateConsole();
801+
let input;
802+
if (event.params && event.params.input) {
803+
input = event.params.input;
804+
}
805+
await this.focusReticulateConsole(input);
798806
}
799807
});
800808

@@ -807,12 +815,12 @@ export class ReticulateProvider {
807815
);
808816
}
809817

810-
focusReticulateConsole() {
818+
async focusReticulateConsole(input?: string) {
811819
// if this session is already active, this is a no-op that just
812820
// brings focus.
813-
positron.runtime.selectLanguageRuntime('reticulate');
814-
// Execute an empty code block to focus the console
815-
positron.runtime.executeCode('python', '', true, true);
821+
await positron.runtime.selectLanguageRuntime('reticulate');
822+
// Execute an empty code block if input is null to focus the console.
823+
await positron.runtime.executeCode('python', input ?? '', true, true);
816824
}
817825

818826
dispose() {
@@ -837,7 +845,7 @@ export function activate(context: vscode.ExtensionContext) {
837845
positron.runtime.registerClientHandler({
838846
clientType: 'positron.reticulate',
839847
callback: (client, params: any) => {
840-
reticulateProvider.registerClient(client);
848+
reticulateProvider.registerClient(client, params.input);
841849
return true;
842850
}
843851
}));

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@
7676
"extensions-ci": "node ./node_modules/gulp/bin/gulp.js extensions-ci",
7777
"extensions-ci-pr": "node ./node_modules/gulp/bin/gulp.js extensions-ci-pr",
7878
"perf": "node scripts/code-perf.js",
79-
"update-build-ts-version": "npm install typescript@next && tsc -p ./build/tsconfig.build.json"
79+
"update-build-ts-version": "npm install typescript@next && tsc -p ./build/tsconfig.build.json",
80+
"rebuild:": "nvm use && ./rebuild.sh"
8081
},
8182
"dependencies": {
8283
"@microsoft/1ds-core-js": "^3.2.13",

product.json

+4-16
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@
116116
"bootstrapExtensions": [
117117
{
118118
"name": "ms-python.black-formatter",
119-
"version": "2024.2.0",
119+
"version": "2024.6.0",
120120
"repo": "https://github.com/microsoft/vscode-black-formatter",
121121
"metadata": {
122122
"id": "859e640c-c157-47da-8699-9080b81c8371",
@@ -177,7 +177,7 @@
177177

178178
{
179179
"name": "ms-toolsai.jupyter",
180-
"version": "2024.8.1",
180+
"version": "2024.11.0",
181181
"repo": "https://github.com/Microsoft/vscode-jupyter",
182182
"metadata": {
183183
"id": "6c2f1801-1e7f-45b2-9b5c-7782f1e076e8",
@@ -192,7 +192,7 @@
192192
},
193193
{
194194
"name": "ms-pyright.pyright",
195-
"version": "1.1.379",
195+
"version": "1.1.395",
196196
"repo": "https://github.com/Microsoft/pyright",
197197
"metadata": {
198198
"id": "593fe6a5-513e-4cb3-abfb-5b9f5fe39802",
@@ -207,7 +207,7 @@
207207
},
208208
{
209209
"name": "ms-python.debugpy",
210-
"version": "2024.8.0",
210+
"version": "2025.0.1",
211211
"repo": "https://github.com/microsoft/vscode-python-debugger",
212212
"metadata": {
213213
"id": "4bd5d2c9-9d65-401a-b0b2-7498d9f17615",
@@ -233,18 +233,6 @@
233233
},
234234
"publisherDisplayName": "Posit Software, PBC"
235235
},
236-
{
237-
"name": "posit.shiny",
238-
"version": "1.1.2",
239-
"repo": "http://github.com/posit-dev/shiny-vscode",
240-
"type": "reh-web",
241-
"metadata": {
242-
"id": "f1b3b3b4-3b3b-4b3b-8b3b-3b3b3b3b3b3b",
243-
"publisherId": "090804ff-7eb2-4fbd-bb61-583e34f2b070",
244-
"displayName": "Shiny",
245-
"multiPlatformServiceUrl": "https://open-vsx.org/api"
246-
}
247-
},
248236
{
249237
"name": "quarto.quarto",
250238
"version": "1.118.0",

src/vs/platform/extensionManagement/node/positronBootstrapExtensionsInitializer.ts

+4-5
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import { existsSync, readFileSync, writeFileSync } from 'fs';
1515
import { Disposable } from '../../../base/common/lifecycle.js';
1616

1717
export class PositronBootstrapExtensionsInitializer extends Disposable {
18-
private readonly storageFilePath: string;
1918

2019
constructor(
2120
@INativeEnvironmentService private readonly environmentService: INativeEnvironmentService,
@@ -26,19 +25,19 @@ export class PositronBootstrapExtensionsInitializer extends Disposable {
2625
) {
2726
super();
2827

29-
this.storageFilePath = join(this.getVSIXPath().fsPath, '.version');
28+
const storageFilePath = join(this.environmentService.extensionsPath, '.version');
3029
const currentVersion = this.productService.positronVersion;
3130

32-
const lastKnownVersion = existsSync(this.storageFilePath) ? readFileSync(this.storageFilePath, 'utf8').trim() : '';
31+
const lastKnownVersion = existsSync(storageFilePath) ? readFileSync(storageFilePath, 'utf8').trim() : '';
3332

3433
if (lastKnownVersion !== currentVersion) {
3534
this.logService.info('First launch after first install, upgrade, or downgrade. Installing bootstrapped extensions');
3635
this.installVSIXOnStartup()
3736
.then(() => {
3837
try {
39-
writeFileSync(this.storageFilePath, currentVersion);
38+
writeFileSync(storageFilePath, currentVersion);
4039
} catch (error) {
41-
this.logService.error('Error writing bootstrapped extension storage file', this.storageFilePath, getErrorMessage(error));
40+
this.logService.error('Error writing bootstrapped extension storage file', storageFilePath, getErrorMessage(error));
4241
}
4342
})
4443
.catch(error => {

src/vs/workbench/api/browser/positron/mainThreadConsole.ts

+4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ export class MainThreadConsole {
1111
) {
1212
}
1313

14+
getLanguageId(): string {
15+
return this._console.session.runtimeMetadata.languageId;
16+
}
17+
1418
pasteText(text: string): void {
1519
this._console.pasteText(text);
1620
}

src/vs/workbench/api/browser/positron/mainThreadConsoleService.ts

+20-14
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,22 @@ export class MainThreadConsoleService implements MainThreadConsoleServiceShape {
1414

1515
private readonly _disposables = new DisposableStore();
1616

17-
// Map of language `id` to console.
18-
// Assumes each language `id` maps to at most 1 console,
19-
// which may need to be relaxed in the future.
20-
// Kept in sync with consoles in `ExtHostConsoleService`.
21-
private readonly _mainThreadConsolesByLanguageId = new Map<string, MainThreadConsole>();
17+
/**
18+
* A Map of session ids to the respective console.
19+
* Each session id maps to a single console.
20+
* Multiple sessions could map to the same console, this happens
21+
* when a user power-cycles the session for a console instance
22+
* (i.e. shutdown session for console instance, then start a session for console instance)
23+
*
24+
* Kept in sync with consoles in `ExtHostConsoleService`
25+
*/
26+
private readonly _mainThreadConsolesBySessionId = new Map<string, MainThreadConsole>();
2227

2328
private readonly _proxy: ExtHostConsoleServiceShape;
2429

2530
constructor(
2631
extHostContext: IExtHostContext,
27-
@IPositronConsoleService private readonly _positronConsoleService: IPositronConsoleService,
32+
@IPositronConsoleService private readonly _positronConsoleService: IPositronConsoleService
2833
) {
2934
// Create the proxy for the extension host.
3035
this._proxy = extHostContext.getProxy(ExtHostPositronContext.ExtHostConsoleService);
@@ -37,17 +42,17 @@ export class MainThreadConsoleService implements MainThreadConsoleServiceShape {
3742
this._proxy.$onDidChangeConsoleWidth(newWidth);
3843
}));
3944

40-
// Forward new positron console language id to the extension host, and then register it
45+
// Forward new positron console session id to the extension host, and then register it
4146
// in the main thread too
4247
this._disposables.add(
4348
this._positronConsoleService.onDidStartPositronConsoleInstance((console) => {
44-
const id = console.session.runtimeMetadata.languageId;
49+
const sessionId = console.session.sessionId;
4550

4651
// First update ext host
47-
this._proxy.$addConsole(id);
52+
this._proxy.$addConsole(sessionId);
4853

4954
// Then update main thread
50-
this.addConsole(id, console);
55+
this.addConsole(sessionId, console);
5156
})
5257
);
5358

@@ -60,7 +65,7 @@ export class MainThreadConsoleService implements MainThreadConsoleServiceShape {
6065
//
6166
// this._disposables.add(
6267
// this._positronConsoleService.onDidRemovePositronConsoleInstance((console) => {
63-
// const id = console.runtime.metadata.languageId;
68+
// const id = console.session.sessionId;
6469
//
6570
// // First update ext host
6671
// this._proxy.$removeConsole(id);
@@ -76,12 +81,13 @@ export class MainThreadConsoleService implements MainThreadConsoleServiceShape {
7681
}
7782

7883
private getConsoleForLanguage(id: string): MainThreadConsole | undefined {
79-
return this._mainThreadConsolesByLanguageId.get(id);
84+
return Array.from(this._mainThreadConsolesBySessionId.values())
85+
.find(console => console.getLanguageId() === id);
8086
}
8187

82-
private addConsole(id: string, console: IPositronConsoleInstance) {
88+
private addConsole(sessionId: string, console: IPositronConsoleInstance) {
8389
const mainThreadConsole = new MainThreadConsole(console);
84-
this._mainThreadConsolesByLanguageId.set(id, mainThreadConsole);
90+
this._mainThreadConsolesBySessionId.set(sessionId, mainThreadConsole);
8591
}
8692

8793
// TODO:

src/vs/workbench/api/common/positron/extHostConsole.ts

+4
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,9 @@ export class ExtHostConsole {
4141
getConsole(): positron.Console {
4242
return this._value;
4343
}
44+
45+
getLanguageId(): string {
46+
return this.getLanguageId();
47+
}
4448
}
4549

src/vs/workbench/api/common/positron/extHostConsoleService.ts

+16-10
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,16 @@ import { dispose } from '../../../../base/common/lifecycle.js';
1212

1313
export class ExtHostConsoleService implements extHostProtocol.ExtHostConsoleServiceShape {
1414

15-
// Map of language `id` to console.
16-
// Assumes each language `id` maps to at most 1 console,
17-
// which may need to be relaxed in the future.
18-
// Kept in sync with consoles in `MainThreadConsoleService`.
19-
private readonly _extHostConsolesByLanguageId = new Map<string, ExtHostConsole>;
15+
/**
16+
* A Map of session ids to the respective console.
17+
* Each session id maps to a single console.
18+
* Multiple sessions could map to the same console, this happens
19+
* when a user power-cycles the session for a console instance
20+
* (i.e. shutdown session for console instance, then start a session for console instance)
21+
*
22+
* Kept in sync with consoles in `MainThreadConsoleService`
23+
*/
24+
private readonly _extHostConsolesBySessionId = new Map<string, ExtHostConsole>();
2025

2126
private readonly _onDidChangeConsoleWidth = new Emitter<number>();
2227

@@ -41,7 +46,9 @@ export class ExtHostConsoleService implements extHostProtocol.ExtHostConsoleServ
4146
}
4247

4348
getConsoleForLanguage(id: string): positron.Console | undefined {
44-
const extHostConsole = this._extHostConsolesByLanguageId.get(id);
49+
// find a console for this langauge id
50+
const extHostConsole = Array.from(this._extHostConsolesBySessionId.values())
51+
.find(extHostConsole => extHostConsole.getLanguageId() === id);
4552

4653
if (!extHostConsole) {
4754
// Console for this language `id` doesn't exist yet
@@ -62,14 +69,13 @@ export class ExtHostConsoleService implements extHostProtocol.ExtHostConsoleServ
6269
// Called when a new console instance is started
6370
$addConsole(id: string): void {
6471
const extHostConsole = new ExtHostConsole(id, this._proxy, this._logService);
65-
this._extHostConsolesByLanguageId.set(id, extHostConsole);
72+
this._extHostConsolesBySessionId.set(id, extHostConsole);
6673
}
6774

6875
// Called when a console instance is removed
6976
$removeConsole(id: string): void {
70-
const extHostConsole = this._extHostConsolesByLanguageId.get(id);
71-
this._extHostConsolesByLanguageId.delete(id);
72-
77+
const extHostConsole = this._extHostConsolesBySessionId.get(id);
78+
this._extHostConsolesBySessionId.delete(id);
7379
// "Dispose" of an `ExtHostConsole`, ensuring that future API calls warn / error
7480
dispose(extHostConsole);
7581
}

0 commit comments

Comments
 (0)