Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/actions/build-vsix/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ runs:
VSIX_NAME: ${{ inputs.vsix_name }}

- name: Upload VSIX
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: ${{ inputs.artifact_name }}
path: ${{ inputs.vsix_name }}
Expand Down
14 changes: 0 additions & 14 deletions .github/workflows/pr-file-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,3 @@ jobs:
.github/test_plan.md
skip-label: 'skip tests'
failure-message: 'TypeScript code was edited without also editing a ${file-pattern} file; see the Testing page in our wiki on testing guidelines (the ${skip-label} label can be used to pass this check)'

- name: 'Ensure PR has an associated issue'
uses: actions/github-script@v8
with:
script: |
const labels = context.payload.pull_request.labels.map(label => label.name);
if (!labels.includes('skip-issue-check')) {
const prBody = context.payload.pull_request.body || '';
const issueLink = prBody.match(/https:\/\/github\.com\/\S+\/issues\/\d+/);
const issueReference = prBody.match(/#\d+/);
if (!issueLink && !issueReference) {
core.setFailed('No associated issue found in the PR description.');
}
}
31 changes: 31 additions & 0 deletions .github/workflows/pr-issue-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: PR issue check

on:
pull_request:
types:
- 'opened'
- 'reopened'
- 'synchronize'
- 'labeled'
- 'unlabeled'

permissions: {}

jobs:
check-for-attached-issue:
name: 'Check for attached issue'
runs-on: ubuntu-latest
steps:
- name: 'Ensure PR has an associated issue'
uses: actions/github-script@v8
with:
script: |
const labels = context.payload.pull_request.labels.map(label => label.name);
if (!labels.includes('skip-issue-check')) {
const prBody = context.payload.pull_request.body || '';
const issueLink = prBody.match(/https:\/\/github\.com\/\S+\/issues\/\d+/);
const issueReference = prBody.match(/#\d+/);
if (!issueLink && !issueReference) {
core.setFailed('No associated issue found in the PR description.');
}
}
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,13 @@ To see all available Python commands, open the Command Palette and type `Python`

Learn more about the rich features of the Python extension:

- [IntelliSense](https://code.visualstudio.com/docs/python/editing#_autocomplete-and-intellisense): Edit your code with auto-completion, code navigation, syntax checking and more
- [Linting](https://code.visualstudio.com/docs/python/linting): Get additional code analysis with Pylint, Flake8 and more
- [Code formatting](https://code.visualstudio.com/docs/python/formatting): Format your code with black, autopep or yapf
- [Debugging](https://code.visualstudio.com/docs/python/debugging): Debug your Python scripts, web apps, remote or multi-threaded processes
- [IntelliSense](https://code.visualstudio.com/docs/python/editing#_autocomplete-and-intellisense): Edit your code with auto-completion, code navigation, syntax checking and more.
- [Linting](https://code.visualstudio.com/docs/python/linting): Get additional code analysis with Pylint, Flake8 and more.
- [Code formatting](https://code.visualstudio.com/docs/python/formatting): Format your code with black, autopep or yapf.
- [Debugging](https://code.visualstudio.com/docs/python/debugging): Debug your Python scripts, web apps, remote or multi-threaded processes.
- [Testing](https://code.visualstudio.com/docs/python/unit-testing): Run and debug tests through the Test Explorer with unittest or pytest.
- [Jupyter Notebooks](https://code.visualstudio.com/docs/python/jupyter-support): Create and edit Jupyter Notebooks, add and run code cells, render plots, visualize variables through the variable explorer, visualize dataframes with the data viewer, and more
- [Environments](https://code.visualstudio.com/docs/python/environments): Automatically activate and switch between virtualenv, venv, pipenv, conda and pyenv environments
- [Jupyter Notebooks](https://code.visualstudio.com/docs/python/jupyter-support): Create and edit Jupyter Notebooks, add and run code cells, render plots, visualize variables through the variable explorer, visualize dataframes with the data viewer, and more.
- [Environments](https://code.visualstudio.com/docs/python/environments): Automatically activate and switch between virtualenv, venv, pipenv, conda and pyenv environments.
- [Refactoring](https://code.visualstudio.com/docs/python/editing#_refactoring): Restructure your Python code with variable extraction and method extraction. Additionally, there is componentized support to enable additional refactoring, such as import sorting, through extensions including [isort](https://marketplace.visualstudio.com/items?itemName=ms-python.isort) and [Ruff](https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff).


Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "python",
"displayName": "Python",
"description": "Python language support with extension access points for IntelliSense (Pylance), Debugging (Python Debugger), linting, formatting, refactoring, unit tests, and more.",
"version": "2025.17.0-dev",
"version": "2025.18.0",
"featureFlags": {
"usingNewInterpreterStorage": true
},
Expand Down
14 changes: 8 additions & 6 deletions python_files/vscode_pytest/run_pytest_script.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,22 @@ def run_pytest(args):

run_test_ids_pipe = os.environ.get("RUN_TEST_IDS_PIPE")
if run_test_ids_pipe:
ids_path = pathlib.Path(run_test_ids_pipe)
try:
# Read the test ids from the file, delete file, and run pytest.
ids_path = pathlib.Path(run_test_ids_pipe)
# Read the test ids from the file and run pytest.
ids = ids_path.read_text(encoding="utf-8").splitlines()
try:
ids_path.unlink()
except Exception as e:
print("Error[vscode-pytest]: unable to delete temp file" + str(e))
arg_array = ["-p", "vscode_pytest", *args, *ids]
print("Running pytest with args: " + str(arg_array))
pytest.main(arg_array)
except Exception as e:
print("Error[vscode-pytest]: unable to read testIds from temp file" + str(e))
run_pytest(args)
finally:
# Delete the test ids temp file.
try:
ids_path.unlink()
except Exception as e:
print("Error[vscode-pytest]: unable to delete temp file" + str(e))
else:
print("Error[vscode-pytest]: RUN_TEST_IDS_PIPE env var is not set.")
run_pytest(args)
12 changes: 4 additions & 8 deletions src/client/testing/testController/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,26 +155,22 @@ export interface ITestResultResolver {
_resolveCoverage(payload: CoveragePayload, runInstance: TestRun): void;
}
export interface ITestDiscoveryAdapter {
// ** first line old method signature, second line new method signature
discoverTests(uri: Uri): Promise<void>;
discoverTests(
uri: Uri,
executionFactory?: IPythonExecutionFactory,
executionFactory: IPythonExecutionFactory,
token?: CancellationToken,
interpreter?: PythonEnvironment,
): Promise<void>;
}

// interface for execution/runner adapter
export interface ITestExecutionAdapter {
// ** first line old method signature, second line new method signature
runTests(uri: Uri, testIds: string[], profileKind?: boolean | TestRunProfileKind): Promise<void>;
runTests(
uri: Uri,
testIds: string[],
profileKind?: boolean | TestRunProfileKind,
runInstance?: TestRun,
executionFactory?: IPythonExecutionFactory,
profileKind: boolean | TestRunProfileKind | undefined,
runInstance: TestRun,
executionFactory: IPythonExecutionFactory,
debugLauncher?: ITestDebugLauncher,
interpreter?: PythonEnvironment,
): Promise<void>;
Expand Down
8 changes: 4 additions & 4 deletions src/client/testing/testController/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,8 @@ export class PythonTestController implements ITestController, IExtensionSingleAc
}
await testAdapter.discoverTests(
this.testController,
this.refreshCancellation.token,
this.pythonExecFactory,
this.refreshCancellation.token,
await this.interpreterService.getActiveInterpreter(workspace.uri),
);
} else {
Expand All @@ -302,8 +302,8 @@ export class PythonTestController implements ITestController, IExtensionSingleAc
}
await testAdapter.discoverTests(
this.testController,
this.refreshCancellation.token,
this.pythonExecFactory,
this.refreshCancellation.token,
await this.interpreterService.getActiveInterpreter(workspace.uri),
);
} else {
Expand Down Expand Up @@ -453,9 +453,9 @@ export class PythonTestController implements ITestController, IExtensionSingleAc
this.testController,
runInstance,
testItems,
this.pythonExecFactory,
token,
request.profile?.kind,
this.pythonExecFactory,
this.debugLauncher,
await this.interpreterService.getActiveInterpreter(workspace.uri),
);
Expand All @@ -470,9 +470,9 @@ export class PythonTestController implements ITestController, IExtensionSingleAc
this.testController,
runInstance,
testItems,
this.pythonExecFactory,
token,
request.profile?.kind,
this.pythonExecFactory,
this.debugLauncher,
await this.interpreterService.getActiveInterpreter(workspace.uri),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class PytestTestDiscoveryAdapter implements ITestDiscoveryAdapter {

async discoverTests(
uri: Uri,
executionFactory?: IPythonExecutionFactory,
executionFactory: IPythonExecutionFactory,
token?: CancellationToken,
interpreter?: PythonEnvironment,
): Promise<void> {
Expand Down Expand Up @@ -69,7 +69,7 @@ export class PytestTestDiscoveryAdapter implements ITestDiscoveryAdapter {
uri: Uri,
discoveryPipeName: string,
cSource: CancellationTokenSource,
executionFactory?: IPythonExecutionFactory,
executionFactory: IPythonExecutionFactory,
interpreter?: PythonEnvironment,
token?: CancellationToken,
): Promise<void> {
Expand Down Expand Up @@ -170,7 +170,7 @@ export class PytestTestDiscoveryAdapter implements ITestDiscoveryAdapter {
resource: uri,
interpreter,
};
const execService = await executionFactory?.createActivatedEnvironment(creationOptions);
const execService = await executionFactory.createActivatedEnvironment(creationOptions);

const execInfo = await execService?.getExecutablePath();
traceVerbose(`Executable path for pytest discovery: ${execInfo}.`);
Expand Down
34 changes: 17 additions & 17 deletions src/client/testing/testController/pytest/pytestExecutionAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ export class PytestTestExecutionAdapter implements ITestExecutionAdapter {
async runTests(
uri: Uri,
testIds: string[],
profileKind?: TestRunProfileKind,
runInstance?: TestRun,
executionFactory?: IPythonExecutionFactory,
profileKind: boolean | TestRunProfileKind | undefined,
runInstance: TestRun,
executionFactory: IPythonExecutionFactory,
debugLauncher?: ITestDebugLauncher,
interpreter?: PythonEnvironment,
): Promise<void> {
Expand All @@ -49,14 +49,14 @@ export class PytestTestExecutionAdapter implements ITestExecutionAdapter {
}
};
const cSource = new CancellationTokenSource();
runInstance?.token.onCancellationRequested(() => cSource.cancel());
runInstance.token.onCancellationRequested(() => cSource.cancel());

const name = await utils.startRunResultNamedPipe(
dataReceivedCallback, // callback to handle data received
deferredTillServerClose, // deferred to resolve when server closes
cSource.token, // token to cancel
);
runInstance?.token.onCancellationRequested(() => {
runInstance.token.onCancellationRequested(() => {
traceInfo(`Test run cancelled, resolving 'TillServerClose' deferred for ${uri.fsPath}.`);
});

Expand All @@ -82,9 +82,9 @@ export class PytestTestExecutionAdapter implements ITestExecutionAdapter {
testIds: string[],
resultNamedPipeName: string,
serverCancel: CancellationTokenSource,
runInstance?: TestRun,
profileKind?: TestRunProfileKind,
executionFactory?: IPythonExecutionFactory,
runInstance: TestRun,
profileKind: boolean | TestRunProfileKind | undefined,
executionFactory: IPythonExecutionFactory,
debugLauncher?: ITestDebugLauncher,
interpreter?: PythonEnvironment,
): Promise<ExecutionTestPayload> {
Expand Down Expand Up @@ -114,7 +114,7 @@ export class PytestTestExecutionAdapter implements ITestExecutionAdapter {
interpreter,
};
// need to check what will happen in the exec service is NOT defined and is null
const execService = await executionFactory?.createActivatedEnvironment(creationOptions);
const execService = await executionFactory.createActivatedEnvironment(creationOptions);

const execInfo = await execService?.getExecutablePath();
traceVerbose(`Executable path for pytest execution: ${execInfo}.`);
Expand Down Expand Up @@ -144,14 +144,14 @@ export class PytestTestExecutionAdapter implements ITestExecutionAdapter {
cwd,
throwOnStdErr: true,
env: mutableEnv,
token: runInstance?.token,
token: runInstance.token,
};

if (debugBool) {
const launchOptions: LaunchOptions = {
cwd,
args: testArgs,
token: runInstance?.token,
token: runInstance.token,
testProvider: PYTEST_PROVIDER,
runTestIdsPort: testIdsFileName,
pytestPort: resultNamedPipeName,
Expand Down Expand Up @@ -181,19 +181,19 @@ export class PytestTestExecutionAdapter implements ITestExecutionAdapter {
args: runArgs,
env: (mutableEnv as unknown) as { [key: string]: string },
});
runInstance?.token.onCancellationRequested(() => {
runInstance.token.onCancellationRequested(() => {
traceInfo(`Test run cancelled, killing pytest subprocess for workspace ${uri.fsPath}`);
proc.kill();
deferredTillExecClose.resolve();
serverCancel.cancel();
});
proc.stdout.on('data', (data) => {
const out = utils.fixLogLinesNoTrailing(data.toString());
runInstance?.appendOutput(out);
runInstance.appendOutput(out);
});
proc.stderr.on('data', (data) => {
const out = utils.fixLogLinesNoTrailing(data.toString());
runInstance?.appendOutput(out);
runInstance.appendOutput(out);
});
proc.onExit((code, signal) => {
if (code !== 0) {
Expand All @@ -218,7 +218,7 @@ export class PytestTestExecutionAdapter implements ITestExecutionAdapter {

let resultProc: ChildProcess | undefined;

runInstance?.token.onCancellationRequested(() => {
runInstance.token.onCancellationRequested(() => {
traceInfo(`Test run cancelled, killing pytest subprocess for workspace ${uri.fsPath}`);
// if the resultProc exists just call kill on it which will handle resolving the ExecClose deferred, otherwise resolve the deferred here.
if (resultProc) {
Expand All @@ -235,11 +235,11 @@ export class PytestTestExecutionAdapter implements ITestExecutionAdapter {
// Displays output to user and ensure the subprocess doesn't run into buffer overflow.
result?.proc?.stdout?.on('data', (data) => {
const out = utils.fixLogLinesNoTrailing(data.toString());
runInstance?.appendOutput(out);
runInstance.appendOutput(out);
});
result?.proc?.stderr?.on('data', (data) => {
const out = utils.fixLogLinesNoTrailing(data.toString());
runInstance?.appendOutput(out);
runInstance.appendOutput(out);
});
result?.proc?.on('exit', (code, signal) => {
if (code !== 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class UnittestTestDiscoveryAdapter implements ITestDiscoveryAdapter {

public async discoverTests(
uri: Uri,
executionFactory?: IPythonExecutionFactory,
executionFactory: IPythonExecutionFactory,
token?: CancellationToken,
): Promise<void> {
const settings = this.configSettings.getSettings(uri);
Expand Down Expand Up @@ -89,7 +89,7 @@ export class UnittestTestDiscoveryAdapter implements ITestDiscoveryAdapter {
testRunPipeName: string,
cwd: string,
cSource: CancellationTokenSource,
executionFactory?: IPythonExecutionFactory,
executionFactory: IPythonExecutionFactory,
): Promise<void> {
// get and edit env vars
const mutableEnv = {
Expand Down Expand Up @@ -157,7 +157,7 @@ export class UnittestTestDiscoveryAdapter implements ITestDiscoveryAdapter {
allowEnvironmentFetchExceptions: false,
resource: options.workspaceFolder,
};
const execService = await executionFactory?.createActivatedEnvironment(creationOptions);
const execService = await executionFactory.createActivatedEnvironment(creationOptions);
const execInfo = await execService?.getExecutablePath();
traceVerbose(`Executable path for unittest discovery: ${execInfo}.`);

Expand Down
Loading
Loading