From 79cd1f02a5bb6ec2682733e022d833745fdd3820 Mon Sep 17 00:00:00 2001 From: HugoCasa Date: Thu, 13 Jul 2023 15:19:59 +0200 Subject: [PATCH] feat(frontend): use typed dict for resource types in python (#1869) * feat(frontend): python typed dict resource types + filter pickers according to lang * feat: use typed dict for AI gen --- frontend/src/lib/components/EditorBar.svelte | 173 +++++++++++++------ frontend/src/lib/components/codeGen/lib.ts | 14 +- frontend/src/lib/components/codeGen/utils.ts | 65 +++++-- frontend/src/lib/utils.ts | 6 + 4 files changed, 183 insertions(+), 75 deletions(-) diff --git a/frontend/src/lib/components/EditorBar.svelte b/frontend/src/lib/components/EditorBar.svelte index f02cabf887..e0534e7ffb 100644 --- a/frontend/src/lib/components/EditorBar.svelte +++ b/frontend/src/lib/components/EditorBar.svelte @@ -31,10 +31,10 @@ import { SCRIPT_EDITOR_SHOW_EXPLORE_OTHER_SCRIPTS } from '$lib/consts' import { createEventDispatcher } from 'svelte' import { sendUserToast } from '$lib/toast' - import { getScriptByPath } from '$lib/scripts' + import { getScriptByPath, scriptLangToEditorLang } from '$lib/scripts' import Toggle from './Toggle.svelte' import { Link, Users } from 'lucide-svelte' - import { capitalize } from '$lib/utils' + import { capitalize, toCamel } from '$lib/utils' import type { Schema, SchemaProperty, SupportedLanguage } from '$lib/common' import ScriptVersionHistory from './ScriptVersionHistory.svelte' import { ScriptGen } from './codeGen' @@ -65,6 +65,15 @@ let resourceTypePicker: ItemPicker let variableEditor: VariableEditor let resourceEditor: ResourceEditor + let showContextVarPicker = false + let showVarPicker = false + let showResourcePicker = false + let showResourceTypePicker = false + + $: showContextVarPicker = ['python3', 'bash', 'go', 'deno', 'bun'].includes(lang) + $: showVarPicker = ['python3', 'bash', 'go', 'deno', 'bun'].includes(lang) + $: showResourcePicker = ['python3', 'bash', 'go', 'deno', 'bun'].includes(lang) + $: showResourceTypePicker = scriptLangToEditorLang(lang) === 'typescript' || lang === 'python3' let codeViewer: Drawer let codeObj: { language: SupportedLanguage; content: string } | undefined = undefined @@ -137,6 +146,35 @@ return rec(schema.properties, true) } + function pythonCompile(schema: Schema) { + let res = '' + const entries = Object.entries(schema.properties) + if (entries.length === 0) { + return 'dict' + } + let i = 0 + for (let [name, prop] of entries) { + let typ = 'dict' + if (prop.type === 'array') { + typ = 'list' + } else if (prop.type === 'string') { + typ = 'str' + } else if (prop.type === 'number') { + typ = 'float' + } else if (prop.type === 'integer') { + typ = 'int' + } else if (prop.type === 'boolean') { + typ = 'bool' + } + res += `${name}: ${typ}` + i++ + if (i < entries.length) { + res += '\n' + } + } + return res + } + let historyBrowserDrawerOpen = false @@ -171,13 +209,14 @@ {/if} - { if (!editor) return if (lang == 'deno') { editor.insertAtCursor(`Deno.env.get('${name}')`) + } else if (lang === 'bun') { + editor.insertAtCursor(`Bun.env["${name}"]`) } else if (lang == 'python3') { if (!editor.getCode().includes('import os')) { editor.insertAtBeginning('import os\n') @@ -212,6 +251,18 @@ ) } editor.insertAtCursor(`(await wmill.getVariable('${path}'))`) + } else if (lang === 'bun') { + const code = editor.getCode() + if (!code.includes('import { setClient, getVariable } from "windmill-client@0.3.15')) { + editor.insertAtBeginning( + `import { setClient, getVariable } from "windmill-client@0.3.15"\n` + ) + } + if (!code.includes('setClient()')) { + editor.insertAtCursor(`setClient()\n(await getVariable('${path}'))`) + } else { + editor.insertAtCursor(`(await getVariable('${path}'))`) + } } else if (lang == 'python3') { if (!editor.getCode().includes('import wmill')) { editor.insertAtBeginning('import wmill\n') @@ -262,6 +313,18 @@ ) } editor.insertAtCursor(`(await wmill.getResource('${path}'))`) + } else if (lang === 'bun') { + const code = editor.getCode() + if (!code.includes('import { setClient, getResource } from "windmill-client@0.3.15')) { + editor.insertAtBeginning( + `import { setClient, getResource } from "windmill-client@0.3.15"\n` + ) + } + if (!code.includes('setClient()')) { + editor.insertAtCursor(`setClient()\n(await getResource('${path}'))`) + } else { + editor.insertAtCursor(`(await getResource('${path}'))`) + } } else if (lang == 'python3') { if (!editor.getCode().includes('import wmill')) { editor.insertAtBeginning('import wmill\n') @@ -301,24 +364,29 @@ -{#if lang == 'deno'} +{#if showResourceTypePicker} { if (!editor) return - const toCamel = (s) => { - return s.replace(/([-_][a-z])/gi, ($1) => { - return $1.toUpperCase().replace('-', '').replace('_', '') - }) - } const resourceType = await ResourceService.getResourceType({ workspace: $workspaceStore ?? 'NO_W', path: name }) - const tsSchema = compile(resourceType.schema) - console.log(tsSchema) - editor.insertAtCursor(`type ${toCamel(capitalize(name))} = ${tsSchema}\n`) + if (lang == 'python3') { + const pySchema = pythonCompile(resourceType.schema) + + editor.insertAtCursor(`class ${name}(TypedDict):\n${pySchema}\n`) + const code = editor.getCode() + if (!code.includes('from typing import TypedDict')) { + editor.insertAtBeginning('from typing import TypedDict\n') + } + } else { + const tsSchema = compile(resourceType.schema) + console.log(tsSchema) + editor.insertAtCursor(`type ${toCamel(capitalize(name))} = ${tsSchema}\n`) + } sendUserToast(`${name} inserted at cursor`) }} tooltip="Resources Types are the schemas associated with a Resource. They define the structure of the data that is returned from a Resource." @@ -339,46 +407,51 @@ class="rounded-full w-2 h-2 mx-2 {validCode ? 'bg-green-300' : 'bg-red-300'}" />
- + {#if showContextVarPicker} + + {/if} + {#if showVarPicker} + + {/if} - + {#if showResourcePicker} + + {/if} - - - {#if lang == 'deno'} + {#if showResourceTypePicker}