Skip to content

Commit

Permalink
feat: add fastapi docker (#2740)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kludex authored Mar 3, 2021
1 parent ce44ff2 commit 02e9ddf
Show file tree
Hide file tree
Showing 14 changed files with 74 additions and 3 deletions.
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,11 @@
"description": "%vscode-docker.debug.python.django%",
"default": false
},
"fastapi": {
"type": "boolean",
"description": "%vscode-docker.debug.python.fastapi%",
"default": false
},
"jinja": {
"type": "boolean",
"description": "%vscode-docker.debug.python.jinja%",
Expand All @@ -815,6 +820,7 @@
"description": "%vscode-docker.debug.python.projectType%",
"enum": [
"django",
"fastapi",
"flask",
"general"
]
Expand Down
1 change: 1 addition & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"vscode-docker.debug.python.pathMappings.remoteRoot": "The container path.",
"vscode-docker.debug.python.justMyCode": "Debug only user-written code.",
"vscode-docker.debug.python.django": "Django debugging.",
"vscode-docker.debug.python.fastapi": "FastAPI debugging.",
"vscode-docker.debug.python.jinja": "Jinja template debugging (e.g. Flask).",
"vscode-docker.debug.python.projectType": "Type of the Python app.",
"vscode-docker.debug.python.args": "Arguments passed to the Python app.",
Expand Down
4 changes: 4 additions & 0 deletions resources/templates/python/requirements.txt.template
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
{{#if (eq platform 'Python: Django')}}
django==3.1.1
{{/if}}
{{#if (eq platform 'Python: FastAPI')}}
fastapi[all]==0.63.0
uvicorn[standard]==0.13.4
{{/if}}
{{#if (eq platform 'Python: Flask')}}
flask==1.1.2
{{/if}}
Expand Down
2 changes: 1 addition & 1 deletion src/commands/containers/browseContainer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const commonWebPorts = [
3001, // (Node.js) Sails.js
5001, // (.NET Core) ASP.NET SSL
5000, // (.NET Core) ASP.NET HTTP and (Python) Flask
8000, // (Python) Django
8000, // (Python) Django and FastAPI
8080, // (Node.js)
8081 // (Node.js)
];
Expand Down
4 changes: 4 additions & 0 deletions src/debugging/python/PythonDebugHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface PythonDebugOptions {
justMyCode?: boolean;
projectType?: PythonProjectType;
django?: boolean;
fastapi?: boolean;
jinja?: boolean;
args?: string[];
}
Expand Down Expand Up @@ -88,6 +89,7 @@ export class PythonDebugHelper implements DebugHelper {
pathMappings: debugConfiguration.python.pathMappings,
justMyCode: debugConfiguration.python.justMyCode ?? true,
django: debugConfiguration.python.django || projectType === 'django',
fastapi: debugConfiguration.python.fastapi || projectType === 'fastapi',
jinja: debugConfiguration.python.jinja || projectType === 'flask',
dockerOptions: {
containerName: containerName,
Expand Down Expand Up @@ -126,6 +128,8 @@ export class PythonDebugHelper implements DebugHelper {
switch (projectType) {
case 'django':
return 'Starting development server at (https?://\\S+|[0-9]+)';
case 'fastapi':
return 'Uvicorn running on (https?://\\S+|[0-9]+)';
case 'flask':
return 'Running on (https?://\\S+|[0-9]+)';
default:
Expand Down
2 changes: 1 addition & 1 deletion src/scaffolding/scaffoldDebugConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export async function scaffoldDebugConfig(wizardContext: Partial<ScaffoldingWiza

const promptSteps: AzureWizardPromptStep<ScaffoldingWizardContext>[] = [
new ChooseWorkspaceFolderStep(),
new ChoosePlatformStep(['Node.js', '.NET: ASP.NET Core', '.NET: Core Console', 'Python: Django', 'Python: Flask', 'Python: General']),
new ChoosePlatformStep(['Node.js', '.NET: ASP.NET Core', '.NET: Core Console', 'Python: Django', 'Python: FastAPI', 'Python: Flask', 'Python: General']),
];

const wizard = new AzureWizard<ScaffoldingWizardContext>(wizardContext as ScaffoldingWizardContext, {
Expand Down
1 change: 1 addition & 0 deletions src/scaffolding/wizard/ChoosePlatformStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export class ChoosePlatformStep extends TelemetryPromptStep<ScaffoldingWizardCon
case '.NET: Core Console':
return getNetCoreSubWizardOptions(wizardContext);
case 'Python: Django':
case 'Python: FastAPI':
case 'Python: Flask':
case 'Python: General':
return getPythonSubWizardOptions(wizardContext);
Expand Down
2 changes: 2 additions & 0 deletions src/scaffolding/wizard/ScaffoldDebuggingStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export class ScaffoldDebuggingStep extends AzureWizardExecuteStep<ScaffoldingWiz
break;

case 'Python: Django':
case 'Python: FastAPI':
case 'Python: Flask':
case 'Python: General':
scaffoldContext.platform = 'python';
Expand All @@ -68,6 +69,7 @@ export class ScaffoldDebuggingStep extends AzureWizardExecuteStep<ScaffoldingWiz
case '.NET: ASP.NET Core':
case '.NET: Core Console':
case 'Python: Django':
case 'Python: FastAPI':
case 'Python: Flask':
case 'Python: General':
return wizardContext.scaffoldType === 'all' || wizardContext.scaffoldType === 'debugging';
Expand Down
1 change: 1 addition & 0 deletions src/scaffolding/wizard/ScaffoldFileStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export class ScaffoldFileStep<TWizardContext extends ScaffoldingWizardContext> e
subPath = path.join('netCore', `${this.fileType}.template`);
break;
case 'Python: Django':
case 'Python: FastAPI':
case 'Python: Flask':
case 'Python: General':
subPath = path.join('python', `${this.fileType}.template`);
Expand Down
36 changes: 36 additions & 0 deletions src/scaffolding/wizard/python/PythonGatherInformationStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ export class PythonGatherInformationStep extends GatherInformationStep<PythonSca
wizardContext.pythonProjectType = 'django';
await this.getDjangoCmdParts(wizardContext);
break;
case 'Python: FastAPI':
wizardContext.pythonProjectType = 'fastapi';
await this.getFastAPICmdParts(wizardContext);
break;
case 'Python: Flask':
wizardContext.pythonProjectType = 'flask';
await this.getFlaskCmdParts(wizardContext);
Expand Down Expand Up @@ -69,6 +73,38 @@ export class PythonGatherInformationStep extends GatherInformationStep<PythonSca
wizardContext.debugPorts = [PythonDefaultDebugPort];
}

private async getFastAPICmdParts(wizardContext: PythonScaffoldingWizardContext): Promise<void> {
const { args, bindPort } = this.getCommonProps(wizardContext);

let asgiModule: string;

if ('module' in wizardContext.pythonArtifact) {
asgiModule = wizardContext.pythonArtifact.module;
} else if ('file' in wizardContext.pythonArtifact) {
asgiModule = wizardContext.pythonArtifact.file.replace(/\.[^/.]+$/, '');
}

// Replace forward-slashes with dots.
asgiModule = asgiModule.replace(/\//g, '.');

wizardContext.pythonCmdParts = [
'gunicorn',
'--bind',
`0.0.0.0:${bindPort}`,
'-k',
'uvicorn.workers.UvicornWorker',
`${asgiModule}:app`,
];

wizardContext.pythonDebugCmdParts = [
'sh',
'-c',
`${debugCmdPart} -m uvicorn ${asgiModule}:app ${args.join(' ')}`,
];

wizardContext.debugPorts = [PythonDefaultDebugPort];
}

private async getFlaskCmdParts(wizardContext: PythonScaffoldingWizardContext): Promise<void> {
const { args, bindPort } = this.getCommonProps(wizardContext);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ export function getPythonSubWizardOptions(wizardContext: ScaffoldingWizardContex

if (wizardContext.platform === 'Python: Django' && (wizardContext.scaffoldType === 'all' || wizardContext.scaffoldType === 'compose')) {
promptSteps.push(new ChoosePortsStep([PythonDefaultPorts.get('django')]));
} else if (wizardContext.platform === 'Python: FastAPI' && (wizardContext.scaffoldType === 'all' || wizardContext.scaffoldType === 'compose')) {
promptSteps.push(new ChoosePortsStep([PythonDefaultPorts.get('fastapi')]));
} else if (wizardContext.platform === 'Python: Flask' && (wizardContext.scaffoldType === 'all' || wizardContext.scaffoldType === 'compose')) {
promptSteps.push(new ChoosePortsStep([PythonDefaultPorts.get('flask')]));
}
Expand Down
5 changes: 5 additions & 0 deletions src/tasks/python/PythonTaskHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* Licensed under the MIT License. See LICENSE.md in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as path from 'path';
import { PythonScaffoldingOptions } from '../../debugging/DockerDebugScaffoldingProvider';
import { inferPythonArgs } from '../../utils/pythonUtils';
import { unresolveWorkspaceFolder } from "../../utils/resolveVariables";
Expand Down Expand Up @@ -66,6 +67,10 @@ export class PythonTaskHelper implements TaskHelper {
}
runOptions.module = 'flask';
runOptions.file = undefined;
} else if (options.projectType === 'fastapi') {
runOptions.args.unshift(`${path.basename(runOptions.file, '.py')}:app`);
runOptions.module = 'uvicorn';
runOptions.file = undefined;
}

return [{
Expand Down
1 change: 1 addition & 0 deletions src/utils/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const AllPlatforms = [
'.NET: ASP.NET Core',
'.NET: Core Console',
'Python: Django',
'Python: FastAPI',
'Python: Flask',
'Python: General',
'Java',
Expand Down
10 changes: 9 additions & 1 deletion src/utils/pythonUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ import * as fse from 'fs-extra';
import * as os from 'os';
import { Platform } from './platform';

export type PythonProjectType = 'django' | 'flask' | 'general';
export type PythonProjectType = 'django' | 'fastapi' | 'flask' | 'general';

export const PythonFileExtension = ".py";
export const PythonDefaultDebugPort: number = 5678;
export const PythonDefaultPorts = new Map<PythonProjectType, number | undefined>([
['django', 8000],
['fastapi', 8000],
['flask', 5000],
['general', undefined],
]);
Expand All @@ -35,6 +36,11 @@ export function inferPythonArgs(projectType: PythonProjectType, ports: number[])
'--nothreading',
'--noreload'
];
case 'fastapi':
return [
'--host', '0.0.0.0',
'--port', `${ports !== undefined ? ports[0] : PythonDefaultPorts.get(projectType)}`,
]
case 'flask':
return [
'run',
Expand All @@ -52,6 +58,8 @@ export function getPythonProjectType(platform: Platform): PythonProjectType | un
switch (platform) {
case 'Python: Django':
return 'django';
case 'Python: FastAPI':
return 'fastapi';
case 'Python: Flask':
return 'flask';
case 'Python: General':
Expand Down

0 comments on commit 02e9ddf

Please sign in to comment.