from ipyautoui import AutoUi
import pathlib
import json
from pydantic import BaseModel, Field, model_validator, ConfigDict
from enum import Enum
from ipyautoui.constants import DIR_MODULE
from ipyautoui._utils import display_pydantic_json
import ipywidgets as w
import typing as ty
AutoUi
With ipyautoui we can create ipywidgets from either a json-schema or a pydantic model. This makes it quick and easy to whip up a user interface when required.
# create a pydantic model (or a json-schema) defining the fields of interest
class Sub(BaseModel):
str = "a"
a: int = 1
b:
class My(Enum):
"asdfal;ksdfj"
= "a"
a = "b"
b
class Example(BaseModel):
str = Field(default="Test", description="This description is very important")
text: int = 1
inty:
sub: Substr] = None
nu: ty.Optional[
my: My
= {"text": "this is a value"}
data = AutoUi(
ui =Example,
schema=pathlib.Path("test.ui.json"),
path=True,
show_savebuttonbar
) display(ui)
update the value
of the form as you would any other ipywidget
= {'text': 'Test upates', 'inty': 1, 'sub': {'a': 'asdf', 'b': 3}, 'nu': "not None", 'my': 'b'} ui.value
Updating the model / schema
Minor changes to the model can be made. The keys and resulting widgets must remain the same, but the attributes that define them can change (i.e. descriptions, the options of Dropdown, limits of an integer etc.). You can also add validation logic in this way. This is to support the edge case where the parameters of a form must remain the same but the allowed values and other customisations can change.
class New(Enum):
"asdfal;ksdfj"
= 1
c = 2
d
class Example2(BaseModel):
"""some updated description"""
str = Field(default="Test", description="This description is very important")
text: int = Field(default=4, description="This integer is very important")
inty:
sub: Substr] = None
nu: ty.Optional[
my: New
@model_validator(mode='after')
def v(self):
self.text = "custom validation stuff..."
return self
= ConfigDict(json_schema_extra=dict(show_raw=True))
model_config
ui.update_model(Example2)
Wholesale updates of the model are not allowed.
# this will fail as the model is completely different.
# in this case you just want to new AutoUi object.
try:
ui.update_model(Sub)except Exception as e:
print(e)
widgets must match on schema change. changes intended for modifications of existing widgets only.
# this will fail as the widgets that define the model need to change
# as `inty` has changed from an `int` to a `str`
class Example1(BaseModel):
str = Field(default="Test", description="This description is very important")
text: str = "1"
inty:
sub: Substr] = None
nu: ty.Optional[
my: My
try:
ui.update_model(Example1)except Exception as e:
print(e)
widgets must match on schema change. changes intended for modifications of existing widgets only.