dearpygui-forms 0.2.0__py3-none-any.whl → 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,6 +9,7 @@ from loguru import logger
9
9
 
10
10
  from .models import PropertySchema
11
11
  from .widgets import *
12
+ from . import exceptions
12
13
 
13
14
 
14
15
  def extract_defs(schema: dict[str, Any]) -> tuple[dict[str, Any], dict[str, Any]]:
@@ -46,6 +47,9 @@ class DPGForm:
46
47
  except pydantic.ValidationError as e:
47
48
  with dpg.window(modal=True, label="Validation Error"):
48
49
  dpg.add_text(f"Validation error: {e}")
50
+ except exceptions.DearpyguiFormsError as e:
51
+ with dpg.window(modal=True, label="Form Error"):
52
+ dpg.add_text(f"Form error: {e}")
49
53
  else:
50
54
  self._callback(data)
51
55
 
@@ -0,0 +1,2 @@
1
+ class DearpyguiFormsError(Exception):
2
+ pass
dearpygui_forms/models.py CHANGED
@@ -9,6 +9,7 @@ class PropertySchema:
9
9
  self.anyOf: list[dict[str, Any]] = schema.get("anyOf", [])
10
10
  self.properties: dict[str, dict[str, Any]] = schema.get("properties", {})
11
11
  self.default = schema.get("default", None)
12
+ self.items = schema.get("items", None)
12
13
 
13
14
  def __repr__(self) -> str:
14
15
  return f"PropertySchema(title={self.title}, type={self.type}, anyOf={self.anyOf}, properties={self.properties}, default={self.default})"
@@ -6,6 +6,7 @@ from loguru import logger
6
6
 
7
7
 
8
8
  from .models import PropertySchema
9
+ from .exceptions import DearpyguiFormsError
9
10
 
10
11
 
11
12
  @logger.catch
@@ -26,7 +27,8 @@ class Widget:
26
27
  self._defs = defs
27
28
  self._kwargs = kwargs
28
29
  with dpg.stage() as self._staging_container_id:
29
- self._ui()
30
+ with dpg.group() as self._root_item:
31
+ self._ui()
30
32
 
31
33
  if schema.default:
32
34
  self.set_value(schema.default)
@@ -34,8 +36,25 @@ class Widget:
34
36
  def _ui(self):
35
37
  dpg.add_text(f"Property {self.schema.title}, type: {self.schema.type}")
36
38
 
37
- def add(self):
38
- dpg.unstage(self._staging_container_id)
39
+ def add(self, parent=None, hidden=False):
40
+ """
41
+ Add widget as dpg ui item.
42
+ """
43
+ if parent is not None:
44
+ dpg.push_container_stack(parent)
45
+ dpg.unstage(self._staging_container_id)
46
+ dpg.pop_container_stack()
47
+ else:
48
+ dpg.unstage(self._staging_container_id)
49
+
50
+ if hidden:
51
+ self.hide()
52
+
53
+ def hide(self):
54
+ dpg.hide_item(self._root_item)
55
+
56
+ def show(self):
57
+ dpg.show_item(self._root_item)
39
58
 
40
59
  def set_value(self, value: Any):
41
60
  pass
@@ -43,17 +62,20 @@ class Widget:
43
62
  def get_value(self) -> Any:
44
63
  pass
45
64
 
65
+ def __del__(self):
66
+ dpg.delete_item(self._root_item)
46
67
 
47
68
 
48
69
  class ObjectWidget(Widget):
49
70
  def __init__(self, schema, defs, **kwargs):
50
- self._properties = {}
71
+ self._properties: dict[str, Widget] = {}
51
72
  super().__init__(schema, defs, **kwargs)
52
73
 
53
74
  def _ui(self):
54
75
  for property_name, property in self.schema.properties.items():
55
76
  property_widget = generate_widget(property, self._defs, generate_object=False)
56
77
  property_widget.add()
78
+ dpg.add_spacer(height=10)
57
79
  self._properties[property_name] = property_widget
58
80
 
59
81
  def get_value(self) -> dict[str, Any]:
@@ -64,38 +86,112 @@ class ObjectWidget(Widget):
64
86
  property_widget.set_value(value.get(property_name))
65
87
 
66
88
 
89
+ class ExternalWidget(Widget):
90
+ def __init__(self, schema, defs, **kwargs):
91
+ self._external_id = dpg.generate_uuid()
92
+ self._widget: Widget | None = None
93
+ super().__init__(schema, defs, **kwargs)
94
+
95
+ def _ui(self):
96
+ if self.schema.title:
97
+ dpg.add_text(self.schema.title)
98
+ with dpg.group(indent=25) as self._form:
99
+ self._edit_button = dpg.add_button(label=f"Edit", callback=self.show_object_form)
100
+
101
+ def show_object_form(self):
102
+ if self._widget is None:
103
+ dpg.delete_item(self._edit_button)
104
+ self._widget = ObjectWidget(self.schema, self._defs)
105
+ self._widget.add(parent=self._form)
106
+
107
+ def get_value(self):
108
+ if self._widget is None:
109
+ raise DearpyguiFormsError(f"{self.schema.title}: set up object.")
110
+ return self._widget.get_value()
111
+
112
+ def set_value(self, value):
113
+ self.show_object_form()
114
+ self._widget.set_value(value)
115
+
116
+
117
+
67
118
  class ArrayWidget(Widget):
68
119
  def __init__(self, schema, defs, **kwargs):
69
120
  super().__init__(schema, defs, **kwargs)
121
+ self.widgets: list[Widget] = []
122
+
123
+ def _ui(self):
124
+ with dpg.group(horizontal=True):
125
+ dpg.add_text(f"{self.schema.title}")
126
+ dpg.add_button(label="Add", callback=self.add_item)
127
+ dpg.add_button(label="Remove", callback=self.remove_item)
128
+ with dpg.group(indent=25) as self._form:
129
+ pass
130
+
131
+ def add_item(self):
132
+ widget = generate_widget(self.schema.items, self._defs)
133
+ self.widgets.append(widget)
134
+ widget.add(parent=self._form)
135
+
136
+ def remove_item(self):
137
+ if self.widgets:
138
+ widget = self.widgets.pop()
139
+ dpg.delete_item(widget._root_item)
140
+
141
+ def get_value(self):
142
+ return [widget.get_value() for widget in self.widgets]
143
+
144
+ def set_value(self, value):
145
+ self.widgets = []
146
+ for item in value:
147
+ widget = generate_widget(self.schema.items, self._defs)
148
+ self.widgets.append(widget)
149
+ widget.set_value(item)
150
+ widget.add(parent=self._form)
151
+
70
152
 
71
153
 
72
154
  class MultiTypeWidget(Widget):
73
155
  def __init__(self, schema, defs, **kwargs):
74
156
  self._type_switcher_id = dpg.generate_uuid()
75
157
  self._widget: Widget | None = None
76
- self._widgets = [generate_widget(type_schema, defs) for type_schema in schema.anyOf]
77
- super().__init__(schema, defs, **kwargs)
78
- logger.debug(defs)
158
+ self._widgets: dict[str, Widget] = {}
159
+ for type_schema in schema.anyOf:
160
+ widget = generate_widget(type_schema, defs, generate_object=False)
161
+ self._widgets[widget.schema.title or widget.schema.type] = widget
79
162
 
163
+ super().__init__(schema, defs, **kwargs)
80
164
 
81
165
  def _ui(self):
82
- dpg.add_text(self.schema.title)
83
- with dpg.group(indent=10):
84
- dpg.add_combo(label="Type", tag=self._type_switcher_id, items=tuple(x.schema.title or x.schema.type for x in self._widgets), callback=self.switch_value_type)
85
-
166
+ with dpg.group(horizontal=True):
167
+ if self.schema.title:
168
+ dpg.add_text(self.schema.title)
169
+ items = list(self._widgets.keys())
170
+ for i in items:
171
+ dpg.add_button(label=i,
172
+ user_data=i,
173
+ callback=lambda sender, app_data, user_data: self.switch_value_type(user_data),
174
+ small=True
175
+ )
176
+ with dpg.group() as self._form:
177
+ for widget in self._widgets.values():
178
+ widget.add(hidden=True)
86
179
 
87
180
  def switch_value_type(self, new_type):
88
- logger.debug(f"Switching to type {dpg.get_value(self._type_switcher_id)}")
89
-
181
+ if self._widget is not None:
182
+ self._widget.hide()
183
+ self._widget = self._widgets[new_type]
184
+ self._widget.show()
90
185
 
91
186
  def get_value(self):
92
187
  if self._widget:
93
188
  return self._widget.get_value()
94
189
  else:
95
- return None
190
+ raise DearpyguiFormsError(f"{self.schema.title}: choose value type")
96
191
 
97
192
  def set_value(self, value):
98
- dpg.set_value(self._type_switcher_id, value)
193
+ pass
194
+ # dpg.set_value(self._type_switcher_id, value)
99
195
 
100
196
 
101
197
  class StringWidget(Widget):
@@ -104,7 +200,9 @@ class StringWidget(Widget):
104
200
  super().__init__(schema, defs, **kwargs)
105
201
 
106
202
  def _ui(self):
107
- dpg.add_input_text(label=self.schema.title, tag=self._input_id)
203
+ if self.schema.title:
204
+ dpg.add_text(self.schema.title)
205
+ dpg.add_input_text(tag=self._input_id)
108
206
 
109
207
  def get_value(self):
110
208
  return dpg.get_value(self._input_id)
@@ -119,7 +217,9 @@ class IntegerWidget(Widget):
119
217
  super().__init__(schema, defs, **kwargs)
120
218
 
121
219
  def _ui(self):
122
- dpg.add_input_int(label=self.schema.title, tag=self._input_id)
220
+ if self.schema.title:
221
+ dpg.add_text(self.schema.title)
222
+ dpg.add_input_int(tag=self._input_id)
123
223
 
124
224
  def get_value(self):
125
225
  return dpg.get_value(self._input_id)
@@ -134,7 +234,9 @@ class NumberWidget(Widget):
134
234
  super().__init__(schema, defs, **kwargs)
135
235
 
136
236
  def _ui(self):
137
- dpg.add_input_float(label=self.schema.title, tag=self._input_id)
237
+ if self.schema.title:
238
+ dpg.add_text(self.schema.title)
239
+ dpg.add_input_float(tag=self._input_id)
138
240
 
139
241
  def get_value(self):
140
242
  return dpg.get_value(self._input_id)
@@ -149,7 +251,9 @@ class BooleanWidget(Widget):
149
251
  super().__init__(schema, defs, **kwargs)
150
252
 
151
253
  def _ui(self):
152
- dpg.add_checkbox(label=self.schema.title, tag=self._checkbox_id)
254
+ if self.schema.title:
255
+ dpg.add_text(self.schema.title)
256
+ dpg.add_checkbox(tag=self._checkbox_id)
153
257
 
154
258
  def get_value(self):
155
259
  return dpg.get_value(self._checkbox_id)
@@ -163,22 +267,9 @@ class NoneWidget(Widget):
163
267
  super().__init__(schema, defs, **kwargs)
164
268
 
165
269
  def _ui(self):
166
- dpg.add_input_text(default_value='<None>', label=self.schema.title, tag=self._none_id, enabled=False)
167
-
168
- def get_value(self):
169
- return None
170
-
171
- def set_value(self, value):
172
- pass
173
-
174
-
175
- class ExternalWidget(Widget):
176
- def __init__(self, schema, defs, **kwargs):
177
- self._external_id = dpg.generate_uuid()
178
- super().__init__(schema, defs, **kwargs)
179
-
180
- def _ui(self):
181
- dpg.add_button(label=self.schema.title, tag=self._external_id, enabled=False)
270
+ if self.schema.title:
271
+ dpg.add_text(self.schema.title)
272
+ dpg.add_text("<None>", color=(128, 128, 128))
182
273
 
183
274
  def get_value(self):
184
275
  return None
@@ -194,10 +285,8 @@ def generate_widget(json_schema: dict[str, Any], defs: dict[str, Any], generate
194
285
  if generate_object:
195
286
  return ObjectWidget(schema, defs, **kwargs)
196
287
  else:
197
- raise NotImplementedError("ExternalWidget is not implemented yet")
198
288
  return ExternalWidget(schema, defs, **kwargs)
199
289
  case PropertySchema(type='array'):
200
- raise NotImplementedError("ArrayWidget is not implemented yet")
201
290
  return ArrayWidget(schema, defs, **kwargs)
202
291
  case PropertySchema(type='string'):
203
292
  return StringWidget(schema, defs, **kwargs)
@@ -210,7 +299,6 @@ def generate_widget(json_schema: dict[str, Any], defs: dict[str, Any], generate
210
299
  case PropertySchema(type='null'):
211
300
  return NoneWidget(schema, defs, **kwargs)
212
301
  case PropertySchema(anyOf=types) if len(types) > 0:
213
- raise NotImplementedError("MultiTypeWidget is not implemented yet")
214
- # return MultiTypeWidget(schema, defs, **kwargs)
302
+ return MultiTypeWidget(schema, defs, **kwargs)
215
303
  case _:
216
304
  raise ValueError(f"Unsupported schema: {schema}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dearpygui-forms
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Dearpygui extention for autogeneration forms powered by pydantic.
5
5
  Project-URL: homepage, https://github.com/vlewicki/dearpygui-forms
6
6
  Author-email: Valentin Lewicki <vlewicki@vlewicki.ru>
@@ -21,6 +21,8 @@ Generate GUI forms for your Pydantic models.
21
21
 
22
22
 
23
23
  Currently supported Pydantic fields:
24
+ - nested entities
25
+ - arrays
24
26
  - str
25
27
  - int
26
28
  - float
@@ -28,6 +30,8 @@ Currently supported Pydantic fields:
28
30
  - datetime
29
31
  - date
30
32
  - time
33
+ - anyOf sequences
34
+
31
35
 
32
36
  ## Example:
33
37
  ```python
@@ -0,0 +1,8 @@
1
+ dearpygui_forms/__init__.py,sha256=G_SP5hMol1eeOBLl0Lsphe1yyQ800aaCzI0gp03UagE,104
2
+ dearpygui_forms/dpg_form.py,sha256=ShdPOPKSjOFS2jC2aG1f_8-c3V3Vhc2JJLrPxqBjvJc,1778
3
+ dearpygui_forms/exceptions.py,sha256=3ZEGpeCdkIIpH92yoNu6pVcF6HxyFSuWdjAOwfIdVuU,47
4
+ dearpygui_forms/models.py,sha256=4AisK4HjX1ksZDxiwpZ5PKnFTbIg3Z7gyhFM2OCGfUA,683
5
+ dearpygui_forms/widgets.py,sha256=ShkQ622lQYjZQzxq3gBXnHuWxpL5m77A9Nq4DX4dwhE,9640
6
+ dearpygui_forms-0.3.0.dist-info/METADATA,sha256=zVFXnVE7AG1kSNZ8izM3vpXl4nGlYOIGjeROsdRK7W0,1503
7
+ dearpygui_forms-0.3.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
+ dearpygui_forms-0.3.0.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- dearpygui_forms/__init__.py,sha256=G_SP5hMol1eeOBLl0Lsphe1yyQ800aaCzI0gp03UagE,104
2
- dearpygui_forms/dpg_form.py,sha256=hFSWL3BSc0sxVbA2b-_GLGUPIld1VXkGwImQVs8j3nE,1591
3
- dearpygui_forms/models.py,sha256=74CL8WvfY5Qrh-Fx1uSmRU-TY33r_LtFtS1unYqWI5M,636
4
- dearpygui_forms/widgets.py,sha256=hZsepjOtJtMloNeOaNVgAzNaTeZoznfPNwS7gnstLyw,6851
5
- dearpygui_forms-0.2.0.dist-info/METADATA,sha256=MDdweUUm5niI4vdOvI5b7YRSpB_ss4VS7C1a9Ls01MA,1457
6
- dearpygui_forms-0.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
- dearpygui_forms-0.2.0.dist-info/RECORD,,