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

Support for new Python language model #3235

Merged
merged 52 commits into from
Aug 19, 2022
Merged
Show file tree
Hide file tree
Changes from 50 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
f292a6e
Sketch preview project type.
philliphoff May 24, 2022
bd581ea
Switch to language model rather than separate (sub) languages.
philliphoff May 25, 2022
170361f
Exclude Python v2+ from creating functions on project create.
philliphoff May 25, 2022
ee2b112
Store project language model in workspace settings.
philliphoff May 26, 2022
50f8425
Add project-level function source.
philliphoff May 26, 2022
18fa4b2
Use "isolated mode" detection of functions for Python v2+.
philliphoff May 26, 2022
a5e5b40
Merge branch 'main' into philliphoff-new-python-model
philliphoff Jun 1, 2022
a1e2427
Open function .py file on project creation.
philliphoff Jun 1, 2022
c23d8d6
Detect Python language model.
philliphoff Jun 1, 2022
0e965f4
Add Python preview to VS Code init list.
philliphoff Jun 1, 2022
e3b5efe
Extract python preview model into constant.
philliphoff Jun 1, 2022
2fde907
Merge branch 'main' into philliphoff-new-python-model
philliphoff Jul 1, 2022
d11297c
Sketch prompt for Python function location.
philliphoff Jul 1, 2022
5c14fb6
Sketch selecting a script.
philliphoff Jul 1, 2022
2d6e945
Sketch opening template.
philliphoff Jul 5, 2022
ddbdec4
Append new function to file.
philliphoff Jul 5, 2022
33bccc0
Enforce storage configuration for Python V2+.
philliphoff Jul 6, 2022
5493c6a
Exclude extension bundles from Python V2+ projects.
philliphoff Jul 6, 2022
6dc3230
Check for valid Functions version.
philliphoff Jul 6, 2022
8daf287
Merge branch 'main' into philliphoff-new-python-model
philliphoff Jul 6, 2022
4f15b00
Complete merge from `main`.
philliphoff Jul 6, 2022
e9e4cab
Resolve linter warnings.
philliphoff Jul 7, 2022
351ea86
Updates per PM feedback.
philliphoff Jul 7, 2022
bb5b5cb
Updates per PR feedback.
philliphoff Jul 8, 2022
ec0bc15
Merge branch 'main' into philliphoff-new-python-model
philliphoff Jul 27, 2022
f971019
Shift subwizard to separate class.
philliphoff Jul 27, 2022
e3d0102
Move Python location script up front.
philliphoff Jul 28, 2022
c17d114
Move Python script name prompt up front.
philliphoff Jul 28, 2022
834d0f7
Switch to local content provider.
philliphoff Jul 28, 2022
21c5a19
Fake Markdown for trigger template.
philliphoff Jul 28, 2022
6d8fd18
Tweak text.
philliphoff Jul 28, 2022
c795a81
Move content to query string.
philliphoff Jul 29, 2022
644a926
Sketch embedding PyStein templates in extension.
philliphoff Aug 10, 2022
28a5249
Add Python Preview templates to verified list.
philliphoff Aug 11, 2022
92e5193
Exclude OpenAPI function from PyStein projects.
philliphoff Aug 11, 2022
aa2a45f
Merge branch 'main' into philliphoff-new-python-model
philliphoff Aug 11, 2022
65ce583
Account for lack of new files in function creation.
philliphoff Aug 17, 2022
8762121
Use template for project.
philliphoff Aug 17, 2022
a71e522
Fix finding MD content in template.
philliphoff Aug 17, 2022
0b50d12
Disable name prompt for V2.
philliphoff Aug 17, 2022
e9ff169
Update required Function host version, add whitespace during append.
philliphoff Aug 17, 2022
40b2bdd
Update version number.
philliphoff Aug 17, 2022
d5e70ab
Replace direct use of fs-extra.
philliphoff Aug 17, 2022
65b9180
Add notes for preview Python model numbering.
philliphoff Aug 17, 2022
4512d63
More notes.
philliphoff Aug 17, 2022
532af72
Show getting started MD on creation.
philliphoff Aug 18, 2022
9f89955
Do not expose properties commands from PyStein functions in tree.
philliphoff Aug 18, 2022
11068e5
Exclude PyStein from re-adding bundle property on function create.
philliphoff Aug 19, 2022
4137ea2
Updates to documentation per feedback in PR.
philliphoff Aug 19, 2022
1056c34
Update supported PyStein version number and comments.
philliphoff Aug 19, 2022
5718cf9
Allow opening MD to the side.
philliphoff Aug 19, 2022
70e4d64
Use opt-out list instead of opt-in.
philliphoff Aug 19, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 8 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "vscode-azurefunctions",
"displayName": "Azure Functions",
"description": "%azureFunctions.description%",
"version": "1.7.5-alpha.0",
"version": "1.8.0-alpha.0",
"publisher": "ms-azuretools",
"icon": "resources/azure-functions.png",
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
Expand Down Expand Up @@ -77,6 +77,7 @@
"onCommand:azureFunctions.viewDeploymentLogs",
"onCommand:azureFunctions.viewProperties",
"onDebugInitialConfigurations",
"onFileSystem:vscode-azurefunctions-static-content",
"onUri",
"onView:azureWorkspace",
"workspaceContains:**/host.json"
Expand Down Expand Up @@ -833,6 +834,12 @@
""
]
},
"azureFunctions.projectLanguageModel": {
"scope": "resource",
"type": "number",
philliphoff marked this conversation as resolved.
Show resolved Hide resolved
"description": "%azureFunctions.projectLanguageModel%",
"minimum": 1
},
"azureFunctions.projectTemplateKey": {
"scope": "resource",
"type": "string",
Expand Down
1 change: 1 addition & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"azureFunctions.problemMatchers.funcPythonWatch": "Azure Functions Python problems (watch mode)",
"azureFunctions.problemMatchers.funcWatch": "Azure Functions problems (watch mode)",
"azureFunctions.projectLanguage": "The default language to use when performing operations like \"Create New Function\".",
"azureFunctions.projectLanguageModel": "The default language model to use when performing operations like \"Create New Function\".",
"azureFunctions.projectLanguage.preview": "(Preview)",
"azureFunctions.projectOpenBehavior": "The behavior to use after creating a new project. The options are \"AddToWorkspace\", \"OpenInNewWindow\", or \"OpenInCurrentWindow\".",
"azureFunctions.projectRuntime": "The default version of the Azure Functions runtime to use when performing operations like \"Create New Function\".",
Expand Down
4,968 changes: 4,968 additions & 0 deletions resources/backupTemplates/pystein/templates/templates.json

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions src/LocalResourceProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as path from 'path';
import { Disposable, workspace, WorkspaceFolder } from "vscode";
import { tryGetFunctionProjectRoot } from "./commands/createNewProject/verifyIsProject";
import { getFunctionAppName, getJavaDebugSubpath } from "./commands/initProjectForVSCode/InitVSCodeStep/JavaInitVSCodeStep";
import { funcVersionSetting, JavaBuildTool, javaBuildTool, ProjectLanguage, projectLanguageSetting } from "./constants";
import { funcVersionSetting, JavaBuildTool, javaBuildTool, ProjectLanguage, projectLanguageModelSetting, projectLanguageSetting } from "./constants";
import { FuncVersion, tryParseFuncVersion } from "./FuncVersion";
import { localize } from "./localize";
import { InitLocalProjectTreeItem } from "./tree/localProject/InitLocalProjectTreeItem";
Expand All @@ -35,6 +35,7 @@ export class FunctionsLocalResourceProvider implements WorkspaceResourceProvider
if (projectPath) {
try {
const language: ProjectLanguage | undefined = getWorkspaceSetting(projectLanguageSetting, projectPath);
const languageModel: number | undefined = getWorkspaceSetting(projectLanguageModelSetting, projectPath);
const version: FuncVersion | undefined = tryParseFuncVersion(getWorkspaceSetting(funcVersionSetting, projectPath));
if (language === undefined || version === undefined) {
children.push(new InitLocalProjectTreeItem(parent, projectPath, folder));
Expand All @@ -52,7 +53,7 @@ export class FunctionsLocalResourceProvider implements WorkspaceResourceProvider
}


const treeItem: LocalProjectTreeItem = new LocalProjectTreeItem(parent, { effectiveProjectPath, folder, language, version, preCompiledProjectPath, isIsolated });
const treeItem: LocalProjectTreeItem = new LocalProjectTreeItem(parent, { effectiveProjectPath, folder, language, languageModel, version, preCompiledProjectPath, isIsolated });
this._projectDisposables.push(treeItem);
children.push(treeItem);
}
Expand Down
2 changes: 1 addition & 1 deletion src/commands/addBinding/BindingListStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export class BindingListStep extends AzureWizardPromptStep<IBindingWizardContext
const language: ProjectLanguage = nonNullProp(context, 'language');
const version: FuncVersion = nonNullProp(context, 'version');
const templateProvider = ext.templateProvider.get(context);
const templates: IBindingTemplate[] = await templateProvider.getBindingTemplates(context, context.projectPath, language, version);
const templates: IBindingTemplate[] = await templateProvider.getBindingTemplates(context, context.projectPath, language, undefined, version);
return templates
.filter(b => b.direction.toLowerCase() === direction.toLowerCase())
.sort((a, b) => a.displayName.localeCompare(b.displayName))
Expand Down
6 changes: 4 additions & 2 deletions src/commands/addBinding/addBinding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ export async function addBinding(context: IActionContext, data: Uri | LocalFunct
workspaceFolder = nonNullValue(getContainingWorkspace(functionJsonPath), 'workspaceFolder');
workspacePath = workspaceFolder.uri.fsPath;
projectPath = await tryGetFunctionProjectRoot(context, workspaceFolder, 'modalPrompt') || workspacePath;
[language, version] = await verifyInitForVSCode(context, projectPath);
const verifiedInit = await verifyInitForVSCode(context, projectPath);
language = verifiedInit.language;
version = verifiedInit.version;
} else {
if (!data) {
const noItemFoundErrorMessage: string = localize('noLocalProject', 'No matching functions found. C# and Java projects do not support this operation.');
Expand All @@ -48,7 +50,7 @@ export async function addBinding(context: IActionContext, data: Uri | LocalFunct
workspaceFolder = projectTi.workspaceFolder;
workspacePath = projectTi.workspacePath;
projectPath = projectTi.effectiveProjectPath;
language = projectTi.langauge;
language = projectTi.language;
version = projectTi.version;
}

Expand Down
3 changes: 2 additions & 1 deletion src/commands/createFunction/FunctionCreateStepBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ function runPostFunctionCreateSteps(func: ICachedFunction): void {
void callWithTelemetryAndErrorHandling('postFunctionCreate', async (context: IActionContext) => {
context.telemetry.suppressIfSuccessful = true;

if (getContainingWorkspace(func.projectPath)) {
// If function creation created a new file, open it in an editor...
if (func.newFilePath && getContainingWorkspace(func.projectPath)) {
if (await AzExtFsExtra.pathExists(func.newFilePath)) {
await window.showTextDocument(await workspace.openTextDocument(Uri.file(func.newFilePath)));
}
Expand Down
104 changes: 16 additions & 88 deletions src/commands/createFunction/FunctionListStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,19 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { AzureWizardExecuteStep, AzureWizardPromptStep, IActionContext, IAzureQuickPickItem, IAzureQuickPickOptions, IWizardOptions } from '@microsoft/vscode-azext-utils';
import { AzureWizardPromptStep, IActionContext, IAzureQuickPickItem, IAzureQuickPickOptions, IWizardOptions } from '@microsoft/vscode-azext-utils';
import * as escape from 'escape-string-regexp';
import { JavaBuildTool, ProjectLanguage, TemplateFilter, templateFilterSetting } from '../../constants';
import { canValidateAzureWebJobStorageOnDebug } from '../../debug/validatePreDebug';
import { ext } from '../../extensionVariables';
import { getAzureWebJobsStorage } from '../../funcConfig/local.settings';
import { FuncVersion } from '../../FuncVersion';
import { localize } from '../../localize';
import { IFunctionTemplate } from '../../templates/IFunctionTemplate';
import { nonNullProp } from '../../utils/nonNull';
import { isPythonV2Plus } from '../../utils/pythonUtils';
import { getWorkspaceSetting, updateWorkspaceSetting } from '../../vsCodeConfig/settings';
import { addBindingSettingSteps } from '../addBinding/settingSteps/addBindingSettingSteps';
import { AzureWebJobsStorageExecuteStep } from '../appSettings/AzureWebJobsStorageExecuteStep';
import { AzureWebJobsStoragePromptStep } from '../appSettings/AzureWebJobsStoragePromptStep';
import { JavaPackageNameStep } from '../createNewProject/javaSteps/JavaPackageNameStep';
import { DotnetFunctionCreateStep } from './dotnetSteps/DotnetFunctionCreateStep';
import { DotnetFunctionNameStep } from './dotnetSteps/DotnetFunctionNameStep';
import { DotnetNamespaceStep } from './dotnetSteps/DotnetNamespaceStep';
import { FunctionSubWizard } from './FunctionSubWizard';
import { IFunctionWizardContext } from './IFunctionWizardContext';
import { JavaFunctionCreateStep } from './javaSteps/JavaFunctionCreateStep';
import { JavaFunctionNameStep } from './javaSteps/JavaFunctionNameStep';
import { OpenAPICreateStep } from './openAPISteps/OpenAPICreateStep';
import { OpenAPIGetSpecificationFileStep } from './openAPISteps/OpenAPIGetSpecificationFileStep';
import { ScriptFunctionCreateStep } from './scriptSteps/ScriptFunctionCreateStep';
import { ScriptFunctionNameStep } from './scriptSteps/ScriptFunctionNameStep';
import { TypeScriptFunctionCreateStep } from './scriptSteps/TypeScriptFunctionCreateStep';
import { PythonLocationStep } from './scriptSteps/PythonLocationStep';

export class FunctionListStep extends AzureWizardPromptStep<IFunctionWizardContext> {
public hideStepCount: boolean = true;
Expand All @@ -47,7 +34,7 @@ export class FunctionListStep extends AzureWizardPromptStep<IFunctionWizardConte
const language: ProjectLanguage = nonNullProp(context, 'language');
const version: FuncVersion = nonNullProp(context, 'version');
const templateProvider = ext.templateProvider.get(context);
const templates: IFunctionTemplate[] = await templateProvider.getFunctionTemplates(context, context.projectPath, language, version, TemplateFilter.All, context.projectTemplateKey);
const templates: IFunctionTemplate[] = await templateProvider.getFunctionTemplates(context, context.projectPath, language, context.languageModel, version, TemplateFilter.All, context.projectTemplateKey);
const foundTemplate: IFunctionTemplate | undefined = templates.find((t: IFunctionTemplate) => {
if (options.templateId) {
const actualId: string = t.id.toLowerCase();
Expand All @@ -69,75 +56,15 @@ export class FunctionListStep extends AzureWizardPromptStep<IFunctionWizardConte
}

public async getSubWizard(context: IFunctionWizardContext): Promise<IWizardOptions<IFunctionWizardContext> | undefined> {
const template: IFunctionTemplate | undefined = context.functionTemplate;
if (template) {
const promptSteps: AzureWizardPromptStep<IFunctionWizardContext>[] = [];
switch (context.language) {
case ProjectLanguage.Java:
promptSteps.push(new JavaPackageNameStep(), new JavaFunctionNameStep());
break;
case ProjectLanguage.CSharp:
case ProjectLanguage.FSharp:
promptSteps.push(new DotnetFunctionNameStep(), new DotnetNamespaceStep());
break;
default:
promptSteps.push(new ScriptFunctionNameStep());
break;
}

// Add settings to context that were programmatically passed in
for (const key of Object.keys(this._functionSettings)) {
context[key.toLowerCase()] = this._functionSettings[key];
}

addBindingSettingSteps(template.userPromptedSettings, promptSteps);

const executeSteps: AzureWizardExecuteStep<IFunctionWizardContext>[] = [];
switch (context.language) {
case ProjectLanguage.Java:
executeSteps.push(new JavaFunctionCreateStep());
break;
case ProjectLanguage.CSharp:
case ProjectLanguage.FSharp:
executeSteps.push(await DotnetFunctionCreateStep.createStep(context));
break;
case ProjectLanguage.TypeScript:
executeSteps.push(new TypeScriptFunctionCreateStep());
break;
default:
executeSteps.push(new ScriptFunctionCreateStep());
break;
}

if ((!template.isHttpTrigger && !template.isSqlBindingTemplate) && !canValidateAzureWebJobStorageOnDebug(context.language) && !await getAzureWebJobsStorage(context, context.projectPath)) {
promptSteps.push(new AzureWebJobsStoragePromptStep());
executeSteps.push(new AzureWebJobsStorageExecuteStep());
}

const title: string = localize('createFunction', 'Create new {0}', template.name);
return { promptSteps, executeSteps, title };
} else if (context.generateFromOpenAPI) {
const promptSteps: AzureWizardPromptStep<IFunctionWizardContext>[] = [];
const executeSteps: AzureWizardExecuteStep<IFunctionWizardContext>[] = [];

switch (context.language) {
case ProjectLanguage.Java:
promptSteps.push(new JavaPackageNameStep());
break;
case ProjectLanguage.CSharp:
promptSteps.push(new DotnetNamespaceStep());
break;
default:
break;
}

promptSteps.push(new OpenAPIGetSpecificationFileStep());
executeSteps.push(await OpenAPICreateStep.createStep(context));
const isV2PythonModel = isPythonV2Plus(context.language, context.languageModel);

const title: string = localize('createFunction', 'Create new {0}', 'HTTP Triggers from OpenAPI (v2/v3) Specification File');
return { promptSteps, executeSteps, title };
if (isV2PythonModel) {
return {
// TODO: Title?
promptSteps: [ new PythonLocationStep(this._functionSettings) ]
};
} else {
return undefined;
return await FunctionSubWizard.createSubWizard(context, this._functionSettings);
}
}

Expand Down Expand Up @@ -169,7 +96,7 @@ export class FunctionListStep extends AzureWizardPromptStep<IFunctionWizardConte
context.generateFromOpenAPI = true;
break;
} else if (result === 'reloadTemplates') {
await templateProvider.clearTemplateCache(context, context.projectPath, nonNullProp(context, 'language'), nonNullProp(context, 'version'));
await templateProvider.clearTemplateCache(context, context.projectPath, nonNullProp(context, 'language'), context.languageModel, nonNullProp(context, 'version'));
context.telemetry.properties.reloaded = 'true';
} else {
context.functionTemplate = result;
Expand All @@ -185,9 +112,10 @@ export class FunctionListStep extends AzureWizardPromptStep<IFunctionWizardConte

private async getPicks(context: IFunctionWizardContext, templateFilter: TemplateFilter): Promise<IAzureQuickPickItem<IFunctionTemplate | TemplatePromptResult>[]> {
const language: ProjectLanguage = nonNullProp(context, 'language');
const languageModel = context.languageModel;
const version: FuncVersion = nonNullProp(context, 'version');
const templateProvider = ext.templateProvider.get(context);
const templates: IFunctionTemplate[] = await templateProvider.getFunctionTemplates(context, context.projectPath, language, version, templateFilter, context.projectTemplateKey);
const templates: IFunctionTemplate[] = await templateProvider.getFunctionTemplates(context, context.projectPath, language, context.languageModel, version, templateFilter, context.projectTemplateKey);
context.telemetry.measurements.templateCount = templates.length;
const picks: IAzureQuickPickItem<IFunctionTemplate | TemplatePromptResult>[] = templates
.sort((a, b) => sortTemplates(a, b, templateFilter))
Expand All @@ -208,7 +136,7 @@ export class FunctionListStep extends AzureWizardPromptStep<IFunctionWizardConte
data: <IFunctionTemplate | TemplatePromptResult><unknown>undefined,
onPicked: () => { /* do nothing */ }
})
} else if (language === ProjectLanguage.CSharp || language === ProjectLanguage.Java || language === ProjectLanguage.Python || language === ProjectLanguage.TypeScript) {
} else if (language === ProjectLanguage.CSharp || language === ProjectLanguage.Java || (language === ProjectLanguage.Python && !isPythonV2Plus(language, languageModel)) || language === ProjectLanguage.TypeScript) {
// NOTE: Only show this if we actually found other templates
picks.push({
label: localize('openAPI', 'HTTP trigger(s) from OpenAPI V2/V3 Specification (Preview)'),
Expand Down