diff --git a/network-poc/frontend/src/pages/index.astro b/network-poc/frontend/src/pages/index.astro index 14f59cf..d38660c 100644 --- a/network-poc/frontend/src/pages/index.astro +++ b/network-poc/frontend/src/pages/index.astro @@ -193,6 +193,19 @@ import Settings from "../components/Settings.astro"; if (fname === 'schemas.py') { if (/:\s*date\b/.test(code) && !/from datetime import/.test(code)) issues.push('ISSUE: schemas.py: käyttää date-tyyppiä mutta "from datetime import date" puuttuu'); + if (/:\s*datetime\b/.test(code) && !/from datetime import/.test(code)) + issues.push('ISSUE: schemas.py: käyttää datetime-tyyppiä mutta "from datetime import datetime" puuttuu'); + } + + // 4b. Python-syntaksi: JS-booleanit (false/true ilman isoa alkukirjainta) + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + if (/^\s*#/.test(line) || /^\s*$/.test(line)) continue; + // Etsi false/true joita ei ole merkkijonon sisällä ja jotka eivät ole osa isompaa sanaa + if (/(? { + let pyVal; + if (v === true) pyVal = 'True'; + else if (v === false) pyVal = 'False'; + else if (v === null) pyVal = 'None'; + else if (typeof v === 'string') pyVal = `"${v}"`; + else pyVal = String(v); + return `"${k}":${pyVal}`; + }); + return '{' + parts.join(',') + '}'; + } + const SPEC_SYSTEM = `You are a software architect who designs database schemas for Python web applications. THINK STEP BY STEP before outputting JSON: @@ -1179,7 +1215,7 @@ Blog → Author: name,email,bio(Text|None) / Post: title, content(Text), author_ for (const f of e.fields) { let parts = [`Column(${f.sa_type}`]; if (!f.nullable) parts.push('nullable=False'); - if (f.default !== null && f.default !== undefined) parts.push(typeof f.default === 'string' ? `default="${f.default}"` : `default=${f.default}`); + if (f.default !== null && f.default !== undefined) parts.push(`default=${pyLiteral(f.default)}`); code += ` ${f.name} = ${parts.join(', ')})\n`; } code += '\n'; @@ -1189,13 +1225,27 @@ Blog → Author: name,email,bio(Text|None) / Post: title, content(Text), author_ } function tmplSchemas(spec) { + // Tunnista tarvittavat datetime-importit kenttätyypeistä + const dtTypes = new Set(); + for (const e of spec.entities) for (const f of e.fields) { + if (/\bdate\b/i.test(f.py_type) && !/datetime/.test(f.py_type)) dtTypes.add('date'); + if (/\bdatetime\b/i.test(f.py_type)) dtTypes.add('datetime'); + } + let code = 'from pydantic import BaseModel\n'; - for (const imp of (spec.extra_imports || [])) code += imp + '\n'; + if (dtTypes.size > 0) code += `from datetime import ${[...dtTypes].sort().join(', ')}\n`; + + // extra_imports: suodata pois pelkät nimet kuten "datetime" (jo käsitelty yllä) + for (const imp of (spec.extra_imports || [])) { + if (/^(date|datetime)$/.test(imp.trim())) continue; // käsitelty jo + if (/^from\s/.test(imp) || /^import\s/.test(imp)) code += imp + '\n'; + } code += '\n'; + for (const e of spec.entities) { code += `class ${e.name}Create(BaseModel):\n`; for (const f of e.fields) { - if (f.default !== null && f.default !== undefined) code += ` ${f.name}: ${f.py_type} = ${typeof f.default === 'string' ? '"'+f.default+'"' : f.default}\n`; + if (f.default !== null && f.default !== undefined) code += ` ${f.name}: ${f.py_type} = ${pyLiteral(f.default)}\n`; else if (f.nullable && f.py_type.includes('None')) code += ` ${f.name}: ${f.py_type} = None\n`; else code += ` ${f.name}: ${f.py_type}\n`; } @@ -1253,11 +1303,11 @@ Blog → Author: name,email,bio(Text|None) / Post: title, content(Text), author_ else if (f.py_type.includes('bool')) testData[f.name] = true; else if (f.py_type.includes('date')) testData[f.name] = '2024-01-15'; } - const td = JSON.stringify(testData); + const td = pyJsonLiteral(testData); const firstStr = e.fields.find(f => f.py_type.includes('str') && f.name !== 'status'); const updateData = {...testData}; if (firstStr) updateData[firstStr.name] = `Updated ${firstStr.name}`; - const ud = JSON.stringify(updateData); + const ud = pyJsonLiteral(updateData); code += `def test_create_${lo}():\n response = client.post('/${tb}/', json=${td})\n assert response.status_code == 201\n assert 'id' in response.json()\n\n`; code += `def test_list_${lo}s():\n client.post('/${tb}/', json=${td})\n response = client.get('/${tb}/')\n assert response.status_code == 200\n assert len(response.json()) >= 1\n\n`; diff --git a/projektit/luodut/rest-api-kyttjhallinnalle (1).zip b/projektit/luodut/rest-api-kyttjhallinnalle (1).zip new file mode 100644 index 0000000..00e8e4e Binary files /dev/null and b/projektit/luodut/rest-api-kyttjhallinnalle (1).zip differ diff --git a/projektit/luodut/rest-api-kyttjhallinnalle.zip b/projektit/luodut/rest-api-kyttjhallinnalle.zip new file mode 100644 index 0000000..bc4c418 Binary files /dev/null and b/projektit/luodut/rest-api-kyttjhallinnalle.zip differ