@@ -334,3 +334,115 @@ async def test_multiple_files_multiple():
334
334
335
335
m = await fastui_form (FormMultipleFiles ).dependency (request )
336
336
assert m .model_dump () == {'files' : [file1 , file2 ]}
337
+
338
+
339
+ class FixedTuple (BaseModel ):
340
+ foo : Tuple [str , int , int ]
341
+
342
+
343
+ def test_fixed_tuple ():
344
+ m = components .ModelForm (model = FixedTuple , submit_url = '/foo/' )
345
+ # insert_assert(m.model_dump(by_alias=True, exclude_none=True))
346
+ assert m .model_dump (by_alias = True , exclude_none = True ) == {
347
+ 'submitUrl' : '/foo/' ,
348
+ 'method' : 'POST' ,
349
+ 'type' : 'ModelForm' ,
350
+ 'formFields' : [
351
+ {
352
+ 'name' : 'foo.0' ,
353
+ 'title' : ['Foo' , '0' ],
354
+ 'required' : True ,
355
+ 'locked' : False ,
356
+ 'htmlType' : 'text' ,
357
+ 'type' : 'FormFieldInput' ,
358
+ },
359
+ {
360
+ 'name' : 'foo.1' ,
361
+ 'title' : ['Foo' , '1' ],
362
+ 'required' : True ,
363
+ 'locked' : False ,
364
+ 'htmlType' : 'number' ,
365
+ 'type' : 'FormFieldInput' ,
366
+ },
367
+ {
368
+ 'name' : 'foo.2' ,
369
+ 'title' : ['Foo' , '2' ],
370
+ 'required' : True ,
371
+ 'locked' : False ,
372
+ 'htmlType' : 'number' ,
373
+ 'type' : 'FormFieldInput' ,
374
+ },
375
+ ],
376
+ }
377
+
378
+
379
+ async def test_fixed_tuple_submit ():
380
+ request = FakeRequest ([('foo.0' , 'bar' ), ('foo.1' , '123' ), ('foo.2' , '456' )])
381
+
382
+ m = await fastui_form (FixedTuple ).dependency (request )
383
+ assert m .model_dump () == {'foo' : ('bar' , 123 , 456 )}
384
+
385
+
386
+ class NestedTuple (BaseModel ):
387
+ bar : FixedTuple
388
+
389
+
390
+ def test_fixed_tuple_nested ():
391
+ m = components .ModelForm (model = NestedTuple , submit_url = '/foobar/' )
392
+ # insert_assert(m.model_dump(by_alias=True, exclude_none=True))
393
+ assert m .model_dump (by_alias = True , exclude_none = True ) == {
394
+ 'submitUrl' : '/foobar/' ,
395
+ 'method' : 'POST' ,
396
+ 'type' : 'ModelForm' ,
397
+ 'formFields' : [
398
+ {
399
+ 'name' : 'bar.foo.0' ,
400
+ 'title' : ['FixedTuple' , 'Foo' , '0' ],
401
+ 'required' : True ,
402
+ 'locked' : False ,
403
+ 'htmlType' : 'text' ,
404
+ 'type' : 'FormFieldInput' ,
405
+ },
406
+ {
407
+ 'name' : 'bar.foo.1' ,
408
+ 'title' : ['FixedTuple' , 'Foo' , '1' ],
409
+ 'required' : True ,
410
+ 'locked' : False ,
411
+ 'htmlType' : 'number' ,
412
+ 'type' : 'FormFieldInput' ,
413
+ },
414
+ {
415
+ 'name' : 'bar.foo.2' ,
416
+ 'title' : ['FixedTuple' , 'Foo' , '2' ],
417
+ 'required' : True ,
418
+ 'locked' : False ,
419
+ 'htmlType' : 'number' ,
420
+ 'type' : 'FormFieldInput' ,
421
+ },
422
+ ],
423
+ }
424
+
425
+
426
+ async def test_fixed_tuple_nested_submit ():
427
+ request = FakeRequest ([('bar.foo.0' , 'bar' ), ('bar.foo.1' , '123' ), ('bar.foo.2' , '456' )])
428
+
429
+ m = await fastui_form (NestedTuple ).dependency (request )
430
+ assert m .model_dump () == {'bar' : {'foo' : ('bar' , 123 , 456 )}}
431
+
432
+
433
+ def test_variable_tuple ():
434
+ class VarTuple (BaseModel ):
435
+ foo : Tuple [str , ...]
436
+
437
+ m = components .ModelForm (model = VarTuple , submit_url = '/foo/' )
438
+ with pytest .raises (NotImplementedError , match = 'Array fields are not fully supported' ):
439
+ m .model_dump (by_alias = True , exclude_none = True )
440
+
441
+
442
+ def test_tuple_optional ():
443
+ class TupleOptional (BaseModel ):
444
+ foo : Tuple [str , Union [str , None ]]
445
+
446
+ m = components .ModelForm (model = TupleOptional , submit_url = '/foo/' )
447
+ with pytest .raises (NotImplementedError , match = 'Tuples with optional fields are not yet supported' ):
448
+ m .model_dump (by_alias = True , exclude_none = True )
0 commit comments