Skip to content
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

WIP - Unit tests for Flask template debugging #1282

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 .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"coverage": true
},
"typescript.tsdk": "./node_modules/typescript/lib", // we want to use the TS server from our node_modules folder to control its version
"tslint.enable": true,
"tslint.enable": true, // We will run our own linting in gulp (& git commit hooks), else tslint extension just complains about unmodified files
"python.linting.enabled": false,
"python.unitTest.promptToConfigure": false,
"python.workspaceSymbols.enabled": false,
Expand Down
2 changes: 2 additions & 0 deletions news/1 Enhancements/1229.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Add prelimnary support for remote debugging using the experimental debugger.
Attach to a Python program started using the command `python -m ptvsd --server --port 9091 --file pythonFile.py`
71 changes: 71 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,19 @@
"Pyramid"
]
}
},
{
"label": "Python Experimental: Attach",
"description": "%python.snippet.launch.attach.description%",
"body": {
"name": "Attach (Remote Debug)",
"type": "pythonExperimental",
"request": "attach",
"localRoot": "^\"\\${workspaceFolder}\"",
"remoteRoot": "^\"\\${workspaceFolder}\"",
"port": 3000,
"host": "localhost"
}
}
],
"configurationAttributes": {
Expand Down Expand Up @@ -963,6 +976,53 @@
"default": false
}
}
},
"attach": {
"required": [
"port",
"remoteRoot"
],
"properties": {
"localRoot": {
"type": "string",
"description": "Local source root that corrresponds to the 'remoteRoot'.",
"default": "${workspaceFolder}"
},
"remoteRoot": {
"type": "string",
"description": "The source root of the remote host.",
"default": ""
},
"port": {
"type": "number",
"description": "Debug port to attach",
"default": 0
},
"host": {
"type": "string",
"description": "IP Address of the of remote server (default is localhost or use 127.0.0.1).",
"default": "localhost"
},
"debugOptions": {
"type": "array",
"description": "Advanced options, view read me for further details.",
"items": {
"type": "string",
"enum": [
"RedirectOutput",
"DebugStdLib",
"Django",
"Jinja"
]
},
"default": []
},
"logToFile": {
"type": "boolean",
"description": "Enable logging of debugger events to a log file.",
"default": false
}
}
}
},
"initialConfigurations": [
Expand All @@ -973,6 +1033,15 @@
"program": "${file}",
"console": "integratedTerminal"
},
{
"name": "Python Experimental: Attach",
"type": "pythonExperimental",
"request": "pythonExperimental",
"localRoot": "${workspaceFolder}",
"remoteRoot": "${workspaceFolder}",
"port": 3000,
"host": "localhost"
},
{
"name": "Python Experimental: Django",
"type": "pythonExperimental",
Expand Down Expand Up @@ -1790,6 +1859,7 @@
"@types/md5": "^2.1.32",
"@types/mocha": "^2.2.48",
"@types/node": "^9.4.7",
"@types/request": "^2.47.0",
"@types/semver": "^5.5.0",
"@types/shortid": "^0.0.29",
"@types/sinon": "^4.3.0",
Expand Down Expand Up @@ -1821,6 +1891,7 @@
"mocha": "^5.0.4",
"relative": "^3.0.2",
"remap-istanbul": "^0.10.1",
"request": "^2.85.0",
"retyped-diff-match-patch-tsd-ambient": "^1.0.0-0",
"shortid": "^2.2.8",
"sinon": "^4.4.5",
Expand Down
1 change: 1 addition & 0 deletions src/client/debugger/Common/Contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export interface LaunchRequestArguments extends DebugProtocol.LaunchRequestArgum
}

export interface AttachRequestArguments extends DebugProtocol.AttachRequestArguments {
type?: DebuggerType;
/** An absolute path to local directory with source. */
localRoot: string;
remoteRoot: string;
Expand Down
14 changes: 10 additions & 4 deletions src/client/debugger/DebugClients/RemoteDebugClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,25 @@ import { DebugSession } from 'vscode-debugadapter';
import { AttachRequestArguments, IPythonProcess } from '../Common/Contracts';
import { BaseDebugServer } from '../DebugServers/BaseDebugServer';
import { RemoteDebugServer } from '../DebugServers/RemoteDebugServer';
import { RemoteDebugServerV2 } from '../DebugServers/RemoteDebugServerv2';
import { DebugClient, DebugType } from './DebugClient';

export class RemoteDebugClient extends DebugClient<AttachRequestArguments> {
private pythonProcess: IPythonProcess;
private pythonProcess?: IPythonProcess;
private debugServer?: BaseDebugServer;
// tslint:disable-next-line:no-any
constructor(args: any, debugSession: DebugSession) {
constructor(args: AttachRequestArguments, debugSession: DebugSession) {
super(args, debugSession);
}

public CreateDebugServer(pythonProcess?: IPythonProcess): BaseDebugServer {
this.pythonProcess = pythonProcess!;
this.debugServer = new RemoteDebugServer(this.debugSession, this.pythonProcess!, this.args);
if (this.args.type === 'pythonExperimental') {
// tslint:disable-next-line:no-any
this.debugServer = new RemoteDebugServerV2(this.debugSession, undefined as any, this.args);
} else {
this.pythonProcess = pythonProcess!;
this.debugServer = new RemoteDebugServer(this.debugSession, this.pythonProcess!, this.args);
}
return this.debugServer!;
}
public get DebugType(): DebugType {
Expand Down
52 changes: 52 additions & 0 deletions src/client/debugger/DebugServers/RemoteDebugServerv2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

'use strict';

// tslint:disable:quotemark ordered-imports no-any no-empty curly member-ordering one-line max-func-body-length no-var-self prefer-const cyclomatic-complexity prefer-template

import { DebugSession } from "vscode-debugadapter";
import { IPythonProcess, IDebugServer, AttachRequestArguments } from "../Common/Contracts";
import { connect, Socket } from "net";
import { BaseDebugServer } from "./BaseDebugServer";

export class RemoteDebugServerV2 extends BaseDebugServer {
private args: AttachRequestArguments;
private socket?: Socket;
constructor(debugSession: DebugSession, pythonProcess: IPythonProcess, args: AttachRequestArguments) {
super(debugSession, pythonProcess);
this.args = args;
}

public Stop() {
if (this.socket) {
this.socket.destroy();
}
}
public Start(): Promise<IDebugServer> {
return new Promise<IDebugServer>((resolve, reject) => {
let portNumber = this.args.port;
let options = { port: portNumber! };
if (typeof this.args.host === "string" && this.args.host.length > 0) {
(<any>options).host = this.args.host;
}
try {
let connected = false;
const socket = connect(options, () => {
connected = true;
this.socket = socket;
this.clientSocket.resolve(socket);
resolve(options);
});
socket.on('error', ex => {
if (connected) {
return;
}
reject(ex);
});
} catch (ex) {
reject(ex);
}
});
}
}
37 changes: 29 additions & 8 deletions src/client/debugger/configProviders/baseProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,18 @@ import { PythonLanguage } from '../../common/constants';
import { IFileSystem, IPlatformService } from '../../common/platform/types';
import { IConfigurationService } from '../../common/types';
import { IServiceContainer } from '../../ioc/types';
import { DebuggerType, DebugOptions, LaunchRequestArguments } from '../Common/Contracts';
import { AttachRequestArguments, DebuggerType, DebugOptions, LaunchRequestArguments } from '../Common/Contracts';

// tslint:disable:no-invalid-template-strings

export type PythonDebugConfiguration = DebugConfiguration & LaunchRequestArguments;
export type PythonLaunchDebugConfiguration = DebugConfiguration & LaunchRequestArguments;
export type PythonAttachDebugConfiguration = DebugConfiguration & AttachRequestArguments;

@injectable()
export abstract class BaseConfigurationProvider implements DebugConfigurationProvider {
constructor(@unmanaged() public debugType: DebuggerType, protected serviceContainer: IServiceContainer) { }
public resolveDebugConfiguration(folder: WorkspaceFolder | undefined, debugConfiguration: DebugConfiguration, token?: CancellationToken): ProviderResult<DebugConfiguration> {
const config = debugConfiguration as PythonDebugConfiguration;
const config = debugConfiguration as PythonLaunchDebugConfiguration;
const numberOfSettings = Object.keys(config);
const workspaceFolder = this.getWorkspaceFolder(folder, config);

Expand All @@ -35,10 +36,30 @@ export abstract class BaseConfigurationProvider implements DebugConfigurationPro
config.env = {};
}

this.provideDefaults(workspaceFolder, config);
if (config.request === 'attach') {
// tslint:disable-next-line:no-any
this.provideAttachDefaults(workspaceFolder, config as any as PythonAttachDebugConfiguration);
} else {
this.provideLaunchDefaults(workspaceFolder, config);
}
return config;
}
protected provideDefaults(workspaceFolder: Uri | undefined, debugConfiguration: PythonDebugConfiguration): void {
protected provideAttachDefaults(workspaceFolder: Uri | undefined, debugConfiguration: PythonAttachDebugConfiguration): void {
if (!Array.isArray(debugConfiguration.debugOptions)) {
debugConfiguration.debugOptions = [];
}
// Always redirect output.
if (debugConfiguration.debugOptions.indexOf(DebugOptions.RedirectOutput) === -1) {
debugConfiguration.debugOptions.push(DebugOptions.RedirectOutput);
}
if (!debugConfiguration.host) {
debugConfiguration.host = 'localhost';
}
if (!debugConfiguration.localRoot && workspaceFolder) {
debugConfiguration.localRoot = workspaceFolder.fsPath;
}
}
protected provideLaunchDefaults(workspaceFolder: Uri | undefined, debugConfiguration: PythonLaunchDebugConfiguration): void {
this.resolveAndUpdatePythonPath(workspaceFolder, debugConfiguration);
if (typeof debugConfiguration.cwd !== 'string' && workspaceFolder) {
debugConfiguration.cwd = workspaceFolder.fsPath;
Expand Down Expand Up @@ -75,7 +96,7 @@ export abstract class BaseConfigurationProvider implements DebugConfigurationPro
}
}
}
private getWorkspaceFolder(folder: WorkspaceFolder | undefined, config: PythonDebugConfiguration): Uri | undefined {
private getWorkspaceFolder(folder: WorkspaceFolder | undefined, config: PythonLaunchDebugConfiguration): Uri | undefined {
if (folder) {
return folder.uri;
}
Expand All @@ -94,14 +115,14 @@ export abstract class BaseConfigurationProvider implements DebugConfigurationPro
}
}
}
private getProgram(config: PythonDebugConfiguration): string | undefined {
private getProgram(config: PythonLaunchDebugConfiguration): string | undefined {
const documentManager = this.serviceContainer.get<IDocumentManager>(IDocumentManager);
const editor = documentManager.activeTextEditor;
if (editor && editor.document.languageId === PythonLanguage.language) {
return editor.document.fileName;
}
}
private resolveAndUpdatePythonPath(workspaceFolder: Uri | undefined, debugConfiguration: PythonDebugConfiguration): void {
private resolveAndUpdatePythonPath(workspaceFolder: Uri | undefined, debugConfiguration: PythonLaunchDebugConfiguration): void {
if (!debugConfiguration) {
return;
}
Expand Down
16 changes: 13 additions & 3 deletions src/client/debugger/configProviders/pythonV2Provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import { Uri } from 'vscode';
import { IPlatformService } from '../../common/platform/types';
import { IServiceContainer } from '../../ioc/types';
import { DebugOptions } from '../Common/Contracts';
import { BaseConfigurationProvider, PythonDebugConfiguration } from './baseProvider';
import { BaseConfigurationProvider, PythonAttachDebugConfiguration, PythonLaunchDebugConfiguration } from './baseProvider';

@injectable()
export class PythonV2DebugConfigurationProvider extends BaseConfigurationProvider {
constructor(@inject(IServiceContainer) serviceContainer: IServiceContainer) {
super('pythonExperimental', serviceContainer);
}
protected provideDefaults(workspaceFolder: Uri, debugConfiguration: PythonDebugConfiguration): void {
super.provideDefaults(workspaceFolder, debugConfiguration);
protected provideLaunchDefaults(workspaceFolder: Uri, debugConfiguration: PythonLaunchDebugConfiguration): void {
super.provideLaunchDefaults(workspaceFolder, debugConfiguration);

debugConfiguration.stopOnEntry = false;
debugConfiguration.debugOptions = Array.isArray(debugConfiguration.debugOptions) ? debugConfiguration.debugOptions : [];
Expand All @@ -30,4 +30,14 @@ export class PythonV2DebugConfigurationProvider extends BaseConfigurationProvide
debugConfiguration.debugOptions.push(DebugOptions.Jinja);
}
}
protected provideAttachDefaults(workspaceFolder: Uri, debugConfiguration: PythonAttachDebugConfiguration): void {
super.provideAttachDefaults(workspaceFolder, debugConfiguration);

debugConfiguration.debugOptions = Array.isArray(debugConfiguration.debugOptions) ? debugConfiguration.debugOptions : [];

// Add PTVSD specific flags.
if (this.serviceContainer.get<IPlatformService>(IPlatformService).isWindows) {
debugConfiguration.debugOptions.push(DebugOptions.FixFilePathCase);
}
}
}
Loading