From d65eca4ffe8568d20d27eac90dd0a9225d9cc418 Mon Sep 17 00:00:00 2001 From: Suraj3620 Date: Thu, 23 Jan 2025 10:56:58 +0100 Subject: [PATCH 1/8] successfully creating forms for dictionaries now --- ipywidgets_jsonschema/form.py | 195 +++++++++++++++++++++++++++++++--- 1 file changed, 178 insertions(+), 17 deletions(-) diff --git a/ipywidgets_jsonschema/form.py b/ipywidgets_jsonschema/form.py index 7465805..e7fb638 100644 --- a/ipywidgets_jsonschema/form.py +++ b/ipywidgets_jsonschema/form.py @@ -289,27 +289,65 @@ def _construct_object(self, schema, label=None, root=False): if "properties" in schema: for prop, subschema in schema["properties"].items(): elements[prop] = self._construct(subschema, label=prop) + elif "additionalProperties" in schema: + # Handle dictionaries with dynamically defined keys and values + elements["dict_container"] = self._construct_dict( + schema, label=label + ) # call the new function for dict + + widget_list = elements[ + "dict_container" + ].widgets # get dict_container widgets + # Maybe wrap this in an Accordion widget + wrapped_widget_list = widget_list + if not root and label is not None: + wrapped_widget_list = self._wrap_accordion( + widget_list, schema, label=label + ) - # Add conditional elements - def add_conditional_elements(s): - # Check whether we have an if statement - cond = s.get("if", None) - if cond is None: - return + def _getter(): + return elements["dict_container"].getter() - for cprop, csubschema in ( - s.get("then", {}).get("properties", {}).items() - ): - celem = self._construct(csubschema, label=cprop) - conditionals.append((cond, cprop, celem)) - elements[cprop] = celem + def _setter(_d): + elements["dict_container"].setter(_d) + + def _register_observer(h, n, t): + elements["dict_container"].register_observer(h, n, t) + + def _resetter(): + elements["dict_container"].resetter() + + return self.construct_element( + getter=_getter, + setter=_setter, + resetter=_resetter, + widgets=wrapped_widget_list, + subelements=elements, + register_observer=_register_observer, + ) + + else: + widget_list = [] + + # Handle the conditionals + def add_conditional_elements(s): + # Check whether we have an if statement + cond = s.get("if", None) + if cond is None: + return + + for cprop, csubschema in s.get("then", {}).get("properties", {}).items(): + celem = self._construct(csubschema, label=cprop) + conditionals.append((cond, cprop, celem)) + elements[cprop] = celem - if "else" in s: - add_conditional_elements(s["else"]) + if "else" in s: + add_conditional_elements(s["else"]) - add_conditional_elements(schema) + add_conditional_elements(schema) - # Apply sorting to the keys + # Apply sorting to the keys + if "properties" in schema: keys = schema["properties"].keys() try: keys = self.sorter(keys) @@ -330,7 +368,11 @@ def add_conditional_elements(s): # Maybe wrap this in an Accordion widget wrapped_widget_list = widget_list - if not root and len(schema.get("properties", {})) > 1: + if ( + not root + and len(schema.get("properties", {})) > 1 + and not "additionalProperties" in schema + ): wrapped_widget_list = self._wrap_accordion(widget_list, schema, label=label) def _getter(): @@ -364,11 +406,15 @@ def _register_observer(h, n, t): if "properties" in schema: for e in elements.values(): e.register_observer(h, n, t) + elif "additionalProperties" in schema: + elements["dict_container"].register_observer(h, n, t) def _resetter(): if "properties" in schema: for e in elements.values(): e.resetter() + elif "additionalProperties" in schema: + elements["dict_container"].resetter() # Add the conditional information if "properties" in schema: @@ -417,6 +463,121 @@ def _cond_observer(_): register_observer=_register_observer, ) + def _construct_dict(self, schema, label=None): + if "additionalProperties" not in schema: + raise FormError( + f"Expecting 'additionalProperties' key in schema for type dict: {schema}" + ) + + additional_props_schema = schema["additionalProperties"] + + # container for the input widgets + + widget = ipywidgets.VBox([]) + + elements = [] # list of widgets corresponding to each key + + def _update_widget(): + widget.children = [ipywidgets.VBox(e.widgets) for e in elements] + + def add_dict_entry(key=None, value=None): + if key is None or key == "": + key = "key" + str(len(elements)) + + key_widget = ipywidgets.Text(value=key, description="key") + + elem_dict = self._construct(additional_props_schema) + + trash = ipywidgets.Button(icon="trash") + + def remove_entry(_): + # Identify the current list index of the entry + for index, child in enumerate(widget.children): + if trash in child.children: + break + + elements.pop(index) + + # Remove it from the widget list and the handler list + _update_widget() + + trash.on_click(remove_entry) + + def _dict_getter(): + return {key_widget.value: elem_dict.getter()} + + def _dict_setter(_dict): + + if key_widget.value in _dict: + elem_dict.setter(_dict[key_widget.value]) + else: + elem_dict.resetter() + + elements.append( + self.construct_element( + getter=_dict_getter, + setter=_dict_setter, + resetter=elem_dict.resetter, + widgets=[ + ipywidgets.HBox( + [key_widget, ipywidgets.VBox(elem_dict.widgets), trash] + ) + ], + ) + ) + _update_widget() + + add_btn = ipywidgets.Button( + description="Add key value", + icon="plus", + layout=ipywidgets.Layout(width="100%"), + ) + add_btn.on_click(lambda x: add_dict_entry()) + + widget_list = [widget, add_btn] + + def _getter(): + + data = {} + for e in elements: + data.update(e.getter()) + + return data + + def _setter(_d): + + for e in elements: + key = list(e.getter().keys())[0] + if key in _d: + e.setter(_d) + else: + e.resetter() + + # check for keys that need to added + keys = [list(e.getter().keys())[0] for e in elements] + for key, value in _d.items(): + + if key not in keys: + add_dict_entry(key=key, value=value) + + def _register_observer(h, n, t): + for e in elements: + e.register_observer(h, n, t) + + def _resetter(): + if "default" in schema: + _setter(schema["default"]) + + _resetter() + + return self.construct_element( + getter=_getter, + setter=_setter, + resetter=_resetter, + widgets=widget_list, + register_observer=_register_observer, + ) + def _construct_simple(self, schema, widget, label=None, root=False): # Extract the best description that we have tooltip = schema.get("description", None) From 571b460574a1f9ac14efd434eb8bd9c39c3fa9b3 Mon Sep 17 00:00:00 2001 From: Shiki <64834708+xshiki@users.noreply.github.com> Date: Mon, 3 Feb 2025 15:44:31 +0100 Subject: [PATCH 2/8] Fixed form for refs --- ipywidgets_jsonschema/form.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ipywidgets_jsonschema/form.py b/ipywidgets_jsonschema/form.py index bfd3536..173f15e 100644 --- a/ipywidgets_jsonschema/form.py +++ b/ipywidgets_jsonschema/form.py @@ -219,8 +219,8 @@ def data(self, _data): self._form_element.setter(_data) def _construct(self, schema, label=None, root=False): - if schema in self._construction_stack: - return self.construct_element() + if schema in self._construction_stack and not ("$ref" in schema or "enum" in schema): + return self.construct_element() self._construction_stack.append(schema) # Enumerations are handled a dropdowns @@ -958,7 +958,7 @@ def _move(b): children = [] if recelem.widgets and recelem.widgets[0].children: children = [ - recelem.widgets[0].children[0], + recelem.widgets[0], ] if not fixed_length: children.append( From c953fe911176826a0f58d0417b745538c621110d Mon Sep 17 00:00:00 2001 From: Suraj3620 Date: Mon, 3 Feb 2025 19:31:02 +0100 Subject: [PATCH 3/8] added a test model and schema for the construct_dict fix --- .DS_Store | Bin 0 -> 8196 bytes ipywidgets_jsonschema/form.py | 22 ++++++++++++---------- tests/.DS_Store | Bin 0 -> 6148 bytes tests/models/.DS_Store | Bin 0 -> 8196 bytes 4 files changed, 12 insertions(+), 10 deletions(-) create mode 100644 .DS_Store create mode 100644 tests/.DS_Store create mode 100644 tests/models/.DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..b49b601209ecf5177f9e99c18c0e182c858a62eb GIT binary patch literal 8196 zcmeHML2uJA6n<_qnr;kLXk+65MB+NesD#ACrR%oCB;c?jH~=cil6GNjT-tPHnkMxM zh`+#JK%Dp`@Lv!I_-tn-aXX1!Hl*2A{1W?p?>&F^OX8G>SherpBU&UP8;6jk8B`OB z=oiOW$t5kGHFkl!k3>XIf2L|xW7R5f{xvzRnZ5S{N zTu27Q{lUQ@WF?V9CFQLHmD~bAT4&b`*kUk;{#269n8`K;l?kR7uK6kxmVKAtd=GJ)>yI~Y`B_Q+zsJwh0Mm`@@c|Y=d5?fOpcF``@ zOACjG<#Kt+SuGzeIftv|l_lrF{qoUK(VoA3_u+PZuhowDdkhYRB~KQbRoA2X1I|t{ zU@bXr{yXWI#sCx9#3YL)-56UUViBg7(lkAyEn25ddO|hS%UBG4cIxu$z@(?{icBMs z2pkhHk|+i)mIS%a?KtG<4?~COesvJ1?0fDAakkSOT6p35zJcjpif?3-NjaxWY z2<=L{<2XATdmP0v02!@k7r+2OkFMA`X4qkRUwz9up+|3utC8atIUaC_Y%AM3{-Of9 zc73i^h9|so?Y`G9yDqAHT2xbJ=<9JwAAUMxOIbN8l(@$;*L%e{)EW`%Jz^bVLDr0n z0;_heod1^lGFg^IRnD2icMV5;qJPsC9CKXhEvgh{N3~9x8DyMIg(b(hV=nR$RXyF{ ztvUA@N1|F}l$DTTdtYjV2R tCiEM+n&#CW8wwk4D`u{4#b`$~oOas;)*+a7*0Vjh6Q(&(Od;zJxaE|~0 literal 0 HcmV?d00001 diff --git a/tests/models/.DS_Store b/tests/models/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..a2774fc194c60433808966f077a02158c097263c GIT binary patch literal 8196 zcmeHM&2AGh5FRIcs1zEdrAXm`*e9sO8*H02QV}hP!Z~b{5GrkcNHY425Efmc90 z3=e}iz&B&JalB5%2_eOf?AdPoeV+Mt?A4@1qz>o(7eq}W+CpdBsA2Fl{+@fORm>d* zE8vNGl%jv40d-5W!;PRoP#`D}6bK3g1^x#G@XqG8wc@?6zYSwhASker3h?<5qq9wn zEwq)R1A~+Run}%c!!_yv!NkTU#unNN6r8$xPzI_@iJ>$c-^V;1HZiu)R>MhYI4QHT zG8KxF)q#s;I;lk4Fa`yJ0%ZlbcCVpY@6wcRmg@KJaW?6lXOnZx;7xUazW-Yqu84MU zXNFG-T!${`8dZOv&T#bwSNqK8Fnn_uwyBNTJ<2goXbh$qxI9Sp%t7vYk?+BwnS30# zC5{edSU1J`Cp5=3`!R(b&};hW_2Z|*@tBUWCjZ_s12zZO81W3iH-Q!daCtnb{BT%m z!jePJ3@j;K`cT!DgL*_SF_U#$yIS?TgR9Xita1r&kAR)i$hTVb+(B(WptQ=Lf%HD* z=*~gv^>WcDMTFkyqF)Yb$BOCzevT0->&rZSpU0A)U#uIxB#+t0RPN@! zCoDU_=6kZl_eLVTGTQQq#QV>iE3zkSCRTT$5I?&i`nAss*%>yrL5p*TPlFt%;r+Sd zc{;K`Z2Yc;*IsCrQ_;k~$9T8c9D5eWJDj0Yc>fo^@Sah1YtMi-w2e`qsv~W3{eQIj z_y3L2BLo^0*hB?X)IMt;B63q(mo(s7J4XM2&W-04+6n}Nl;f~cj>A6u!w}aorZOfm dw$K)L(Ej-k0jOod`yaxanl8NmB@H)j_yfMj<+cC- literal 0 HcmV?d00001 From b1116781ce91a97d9aed0c0caf280895bf41d42c Mon Sep 17 00:00:00 2001 From: Suraj3620 Date: Mon, 3 Feb 2025 19:32:09 +0100 Subject: [PATCH 4/8] added test model and schema for the _construct_dict fix --- tests/models/DictionaryMinProperties.py | 30 +++++++++++++++ tests/schemas/dictionary-minproperties.json | 41 +++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 tests/models/DictionaryMinProperties.py create mode 100644 tests/schemas/dictionary-minproperties.json diff --git a/tests/models/DictionaryMinProperties.py b/tests/models/DictionaryMinProperties.py new file mode 100644 index 0000000..178784d --- /dev/null +++ b/tests/models/DictionaryMinProperties.py @@ -0,0 +1,30 @@ +from pydantic import BaseModel, Field +from typing import Dict, Any, Optional + + +class DictionaryMinProperties(BaseModel): + name: str + settings: Dict[str, Optional[Any]] = Field(..., min_properties=1) + + @classmethod + def valid_cases(cls): + """Provide valid cases for the model.""" + return [ + {"name": "Test", "settings": {"key1": 1}}, + { + "name": "Test", + "settings": {"key1": 1, "key2": "value", "key3": [1,2,3]} + }, + {"name": "Test", "settings": {"key1": None}}, + {"name": "Test2", "settings": {"key1": "test"}} + ] + + @classmethod + def invalid_cases(cls): + """Provide invalid cases for the model.""" + return [{"name": "Test", "settings": {}}] + + @classmethod + def default_values(cls): + """Provide default values for the model.""" + return {} \ No newline at end of file diff --git a/tests/schemas/dictionary-minproperties.json b/tests/schemas/dictionary-minproperties.json new file mode 100644 index 0000000..e5e2980 --- /dev/null +++ b/tests/schemas/dictionary-minproperties.json @@ -0,0 +1,41 @@ +{ + "schema": { + "properties": { + "name": { + "title": "Name", + "type": "string" + }, + "settings": { + "additionalProperties": true, + "minProperties": 1, + "title": "Settings", + "type": "object" + } + }, + "required": [ + "name", + "settings" + ], + "title": "DictMinProperties", + "type": "object" + }, + "valid": [ + { + "name": "Test", + "settings": {"key1": 1} + }, + { + "name": "Test", + "settings": {"key1": 1, "key2": "value", "key3": [1,2,3]} + }, + { + "name": "Test", + "settings": {"key1": null} + }, + { + "name": "Test2", + "settings": {"key1": "test"} + } + + ] + } \ No newline at end of file From db1645c7b4c8810b679c44ff3fb367041a0f8490 Mon Sep 17 00:00:00 2001 From: Shiki <64834708+xshiki@users.noreply.github.com> Date: Mon, 3 Feb 2025 19:36:28 +0100 Subject: [PATCH 5/8] Deleted DS_Store files --- .DS_Store | Bin 8196 -> 0 bytes tests/.DS_Store | Bin 6148 -> 6148 bytes tests/models/.DS_Store | Bin 8196 -> 0 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store delete mode 100644 tests/models/.DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index b49b601209ecf5177f9e99c18c0e182c858a62eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8196 zcmeHML2uJA6n<_qnr;kLXk+65MB+NesD#ACrR%oCB;c?jH~=cil6GNjT-tPHnkMxM zh`+#JK%Dp`@Lv!I_-tn-aXX1!Hl*2A{1W?p?>&F^OX8G>SherpBU&UP8;6jk8B`OB z=oiOW$t5kGHFkl!k3>XIf2L|xW7R5f{xvzRnZ5S{N zTu27Q{lUQ@WF?V9CFQLHmD~bAT4&b`*kUk;{#269n8`K;l?kR7uK6kxmVKAtd=GJ)>yI~Y`B_Q+zsJwh0Mm`@@c|Y=d5?fOpcF``@ zOACjG<#Kt+SuGzeIftv|l_lrF{qoUK(VoA3_u+PZuhowDdkhYRB~KQbRoA2X1I|t{ zU@bXr{yXWI#sCx9#3YL)-56UUViBg7(lkAyEn25ddO|hS%UBG4cIxu$z@(?{icBMs z2pkhHk|+i)mIS%a?KtG<4?~1!b5&#rX3G@4C{t)t$F3FA_u@IU3MjL!+Ll-*W zEk&CF!+>GnzcD~(w}_|JgFd|B+5I`cUNBDkK`a7{_ze1Sln$%aFSe7*@9tTaZ56FY zw=2f(&>xP{ra!o+-i;7(Fl+n4ZPXcirNc{+4E-qS3}iwSb};1OE=oc%Zi-P7rZU%6 z4%;r+Ua35p)Eeg%epWx9R`{e*t5$fuQJYTf!qM@`#kKbm_Y(20=wx{NNIB3rgAZ)1 z*j<>m;{aDnp({dO-9ZwI20z;yA!^vq0GC``_d-{&$Mn4{2G!+>F6k%64*mgxPz zT3!DyCYhdLz%Z~?46uC5Z8dRA`fXj>9KE$1^$C@P;xdIY1&w}=WrLpLGO85xacUqs U8Z(7Bf@1y%NE(bW46K!bZ!lM%jQ{`u delta 388 zcmZoMXfc=|#>B)qu~2NHo+2a1#(>?7j2x4BS*7YdbMljua`KZH7#IYA*b#{J{(}LK z#lXPLkj#+JkjIe5P{NSPPz)sX7z!9F(R8gx)5XS+3)GbY)RDtbjH;GV7Der3MK)bD zH!yais9<1V2ilv=kO4F;mm!g%xGcCRFDE}Q9jJ;Chk-3X2;Vf1;Tx z2G?gB&rk~VR0_~=kSF7T24n)QEC!N!4C&YmV**(Y4W`Y49AYdJ8n~ diff --git a/tests/models/.DS_Store b/tests/models/.DS_Store deleted file mode 100644 index a2774fc194c60433808966f077a02158c097263c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8196 zcmeHM&2AGh5FRIcs1zEdrAXm`*e9sO8*H02QV}hP!Z~b{5GrkcNHY425Efmc90 z3=e}iz&B&JalB5%2_eOf?AdPoeV+Mt?A4@1qz>o(7eq}W+CpdBsA2Fl{+@fORm>d* zE8vNGl%jv40d-5W!;PRoP#`D}6bK3g1^x#G@XqG8wc@?6zYSwhASker3h?<5qq9wn zEwq)R1A~+Run}%c!!_yv!NkTU#unNN6r8$xPzI_@iJ>$c-^V;1HZiu)R>MhYI4QHT zG8KxF)q#s;I;lk4Fa`yJ0%ZlbcCVpY@6wcRmg@KJaW?6lXOnZx;7xUazW-Yqu84MU zXNFG-T!${`8dZOv&T#bwSNqK8Fnn_uwyBNTJ<2goXbh$qxI9Sp%t7vYk?+BwnS30# zC5{edSU1J`Cp5=3`!R(b&};hW_2Z|*@tBUWCjZ_s12zZO81W3iH-Q!daCtnb{BT%m z!jePJ3@j;K`cT!DgL*_SF_U#$yIS?TgR9Xita1r&kAR)i$hTVb+(B(WptQ=Lf%HD* z=*~gv^>WcDMTFkyqF)Yb$BOCzevT0->&rZSpU0A)U#uIxB#+t0RPN@! zCoDU_=6kZl_eLVTGTQQq#QV>iE3zkSCRTT$5I?&i`nAss*%>yrL5p*TPlFt%;r+Sd zc{;K`Z2Yc;*IsCrQ_;k~$9T8c9D5eWJDj0Yc>fo^@Sah1YtMi-w2e`qsv~W3{eQIj z_y3L2BLo^0*hB?X)IMt;B63q(mo(s7J4XM2&W-04+6n}Nl;f~cj>A6u!w}aorZOfm dw$K)L(Ej-k0jOod`yaxanl8NmB@H)j_yfMj<+cC- From 3e569b4d9b808769a5c1207340b4623ebbd0a524 Mon Sep 17 00:00:00 2001 From: Shiki <64834708+xshiki@users.noreply.github.com> Date: Mon, 3 Feb 2025 20:08:59 +0100 Subject: [PATCH 6/8] Removed unsupported model --- tests/models/Dictionary.py | 2 +- tests/models/DictionaryMinProperties.py | 30 --------------- tests/schemas/dictionary-minproperties.json | 41 --------------------- 3 files changed, 1 insertion(+), 72 deletions(-) delete mode 100644 tests/models/DictionaryMinProperties.py delete mode 100644 tests/schemas/dictionary-minproperties.json diff --git a/tests/models/Dictionary.py b/tests/models/Dictionary.py index e2ba027..8c9ae73 100644 --- a/tests/models/Dictionary.py +++ b/tests/models/Dictionary.py @@ -13,7 +13,7 @@ def valid_cases(cls): @classmethod def invalid_cases(cls): """Provide invalid cases for the model.""" - return [{"name": "Test", "settings": {}}, {"name": "Test"}] + return [{"name": "Test", "settings": {"key1": "string"}}, {"name": "Test"}] @classmethod def default_values(cls): diff --git a/tests/models/DictionaryMinProperties.py b/tests/models/DictionaryMinProperties.py deleted file mode 100644 index 178784d..0000000 --- a/tests/models/DictionaryMinProperties.py +++ /dev/null @@ -1,30 +0,0 @@ -from pydantic import BaseModel, Field -from typing import Dict, Any, Optional - - -class DictionaryMinProperties(BaseModel): - name: str - settings: Dict[str, Optional[Any]] = Field(..., min_properties=1) - - @classmethod - def valid_cases(cls): - """Provide valid cases for the model.""" - return [ - {"name": "Test", "settings": {"key1": 1}}, - { - "name": "Test", - "settings": {"key1": 1, "key2": "value", "key3": [1,2,3]} - }, - {"name": "Test", "settings": {"key1": None}}, - {"name": "Test2", "settings": {"key1": "test"}} - ] - - @classmethod - def invalid_cases(cls): - """Provide invalid cases for the model.""" - return [{"name": "Test", "settings": {}}] - - @classmethod - def default_values(cls): - """Provide default values for the model.""" - return {} \ No newline at end of file diff --git a/tests/schemas/dictionary-minproperties.json b/tests/schemas/dictionary-minproperties.json deleted file mode 100644 index e5e2980..0000000 --- a/tests/schemas/dictionary-minproperties.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "schema": { - "properties": { - "name": { - "title": "Name", - "type": "string" - }, - "settings": { - "additionalProperties": true, - "minProperties": 1, - "title": "Settings", - "type": "object" - } - }, - "required": [ - "name", - "settings" - ], - "title": "DictMinProperties", - "type": "object" - }, - "valid": [ - { - "name": "Test", - "settings": {"key1": 1} - }, - { - "name": "Test", - "settings": {"key1": 1, "key2": "value", "key3": [1,2,3]} - }, - { - "name": "Test", - "settings": {"key1": null} - }, - { - "name": "Test2", - "settings": {"key1": "test"} - } - - ] - } \ No newline at end of file From 24ce149e730c7727d4a92a42d9a66c2fd101697a Mon Sep 17 00:00:00 2001 From: Shiki <64834708+xshiki@users.noreply.github.com> Date: Mon, 3 Feb 2025 20:11:48 +0100 Subject: [PATCH 7/8] Removed DS_Store --- tests/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tests/.DS_Store diff --git a/tests/.DS_Store b/tests/.DS_Store deleted file mode 100644 index a1789371c8a0a87a9c50352f45709a6705e1430e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK!A=4(5S1!b5&#rX3G@4C{t)t$F3FA_u@IU3MjL!+Ll-*W zEk&CF!+>GnzcD~(w}_|JgFd|B+5I`cUNBDkK`a7{_ze1Sln$%aFSe7*@9tTaZ56FY zw=2f(&>xP{ra!o+-i;7(Fl+n4ZPXcirNc{+4E-qS3}iwSb};1OE=oc%Zi-P7rZU%6 z4%;r+Ua35p)Eeg%epWx9R`{e*t5$fuQJYTf!qM@`#kKbm_Y(20=wx{NNIB3rgAZ)1 z*j<>m;{aDnp({dO-9ZwI20z;yA!^vq0GC``_d-{&$Mn4{2G!+>F6k%64*mgxPz zT3!DyCYhdLz%Z~?46uC5Z8dRA`fXj>9KE$1^$C@P;xdIY1&w}=WrLpLGO85xacUqs U8Z(7Bf@1y%NE(bW46K!bZ!lM%jQ{`u From 42e054aa5958f595fb45d9a0e8851e6330739fef Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 19:18:37 +0000 Subject: [PATCH 8/8] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- ipywidgets_jsonschema/form.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ipywidgets_jsonschema/form.py b/ipywidgets_jsonschema/form.py index 0e40940..823c6d5 100644 --- a/ipywidgets_jsonschema/form.py +++ b/ipywidgets_jsonschema/form.py @@ -219,8 +219,10 @@ def data(self, _data): self._form_element.setter(_data) def _construct(self, schema, label=None, root=False): - if schema in self._construction_stack and not ("$ref" in schema or "enum" in schema): - return self.construct_element() + if schema in self._construction_stack and not ( + "$ref" in schema or "enum" in schema + ): + return self.construct_element() self._construction_stack.append(schema) # Enumerations are handled a dropdowns