Upload folder using huggingface_hub
Browse files- README.md +21 -6
- app.py +6 -5
- space.py +7 -6
- src/README.md +21 -6
- src/backend/gradio_propertysheet/propertysheet.py +30 -8
- src/demo/app.py +6 -5
- src/demo/space.py +7 -6
- src/pyproject.toml +1 -1
README.md
CHANGED
@@ -10,7 +10,7 @@ app_file: space.py
|
|
10 |
---
|
11 |
|
12 |
# `gradio_propertysheet`
|
13 |
-
<img alt="Static Badge" src="https://img.shields.io/badge/version%20-%200.0.
|
14 |
|
15 |
The **PropertySheet** component for Gradio allows you to automatically generate a complete and interactive settings panel from a standard Python `dataclass`. It's designed to bring the power of IDE-like property editors directly into your Gradio applications.
|
16 |
|
@@ -39,6 +39,7 @@ The **PropertySheet** component for Gradio allows you to automatically generate
|
|
39 |
|
40 |
## Installation
|
41 |
|
|
|
42 |
```bash
|
43 |
pip install gradio_propertysheet
|
44 |
```
|
@@ -65,7 +66,7 @@ class ModelSettings:
|
|
65 |
default="/path/to/default.safetensors",
|
66 |
metadata={
|
67 |
"label": "Custom Model Path",
|
68 |
-
"interactive_if": {"field": "
|
69 |
},
|
70 |
)
|
71 |
vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
|
@@ -101,7 +102,7 @@ class SamplingSettings:
|
|
101 |
"minimum": 0.0,
|
102 |
"maximum": 1.0,
|
103 |
"step": 0.01,
|
104 |
-
"interactive_if": {"field": "
|
105 |
},
|
106 |
)
|
107 |
temperature: float = field(
|
@@ -114,6 +115,7 @@ class SamplingSettings:
|
|
114 |
"step": 0.1
|
115 |
}
|
116 |
)
|
|
|
117 |
@dataclass
|
118 |
class RenderConfig:
|
119 |
randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
|
@@ -124,7 +126,6 @@ class RenderConfig:
|
|
124 |
model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
|
125 |
sampling: SamplingSettings = field(default_factory=SamplingSettings)
|
126 |
|
127 |
-
|
128 |
@dataclass
|
129 |
class Lighting:
|
130 |
sun_intensity: float = field(
|
@@ -235,7 +236,7 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
|
|
235 |
height=550,
|
236 |
visible=False,
|
237 |
root_label="Generator",
|
238 |
-
interactive=True
|
239 |
)
|
240 |
environment_sheet = PropertySheet(
|
241 |
value=initial_env_config,
|
@@ -244,7 +245,8 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
|
|
244 |
open=False,
|
245 |
visible=False,
|
246 |
root_label="General",
|
247 |
-
interactive=True
|
|
|
248 |
)
|
249 |
|
250 |
def change_visibility(is_visible, render_cfg, env_cfg):
|
@@ -551,6 +553,19 @@ bool
|
|
551 |
<td align="left">If True, only the group name is shown when there is a single group.</td>
|
552 |
</tr>
|
553 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
554 |
<tr>
|
555 |
<td align="left"><code>disable_accordion</code></td>
|
556 |
<td align="left" style="width: 25%;">
|
|
|
10 |
---
|
11 |
|
12 |
# `gradio_propertysheet`
|
13 |
+
<img alt="Static Badge" src="https://img.shields.io/badge/version%20-%200.0.9%20-%20blue"> <a href="https://huggingface.co/spaces/elismasilva/gradio_propertysheet"><img src="https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-Demo-blue"></a><p><span>💻 <a href='https://github.com/DEVAIEXP/gradio_component_propertysheet'>Component GitHub Code</a></span></p>
|
14 |
|
15 |
The **PropertySheet** component for Gradio allows you to automatically generate a complete and interactive settings panel from a standard Python `dataclass`. It's designed to bring the power of IDE-like property editors directly into your Gradio applications.
|
16 |
|
|
|
39 |
|
40 |
## Installation
|
41 |
|
42 |
+
|
43 |
```bash
|
44 |
pip install gradio_propertysheet
|
45 |
```
|
|
|
66 |
default="/path/to/default.safetensors",
|
67 |
metadata={
|
68 |
"label": "Custom Model Path",
|
69 |
+
"interactive_if": {"field": "model_type", "value": "Custom"},
|
70 |
},
|
71 |
)
|
72 |
vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
|
|
|
102 |
"minimum": 0.0,
|
103 |
"maximum": 1.0,
|
104 |
"step": 0.01,
|
105 |
+
"interactive_if": {"field": "enable_advanced", "value": True},
|
106 |
},
|
107 |
)
|
108 |
temperature: float = field(
|
|
|
115 |
"step": 0.1
|
116 |
}
|
117 |
)
|
118 |
+
|
119 |
@dataclass
|
120 |
class RenderConfig:
|
121 |
randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
|
|
|
126 |
model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
|
127 |
sampling: SamplingSettings = field(default_factory=SamplingSettings)
|
128 |
|
|
|
129 |
@dataclass
|
130 |
class Lighting:
|
131 |
sun_intensity: float = field(
|
|
|
236 |
height=550,
|
237 |
visible=False,
|
238 |
root_label="Generator",
|
239 |
+
interactive=True
|
240 |
)
|
241 |
environment_sheet = PropertySheet(
|
242 |
value=initial_env_config,
|
|
|
245 |
open=False,
|
246 |
visible=False,
|
247 |
root_label="General",
|
248 |
+
interactive=True,
|
249 |
+
root_properties_first=False
|
250 |
)
|
251 |
|
252 |
def change_visibility(is_visible, render_cfg, env_cfg):
|
|
|
553 |
<td align="left">If True, only the group name is shown when there is a single group.</td>
|
554 |
</tr>
|
555 |
|
556 |
+
<tr>
|
557 |
+
<td align="left"><code>root_properties_first</code></td>
|
558 |
+
<td align="left" style="width: 25%;">
|
559 |
+
|
560 |
+
```python
|
561 |
+
bool
|
562 |
+
```
|
563 |
+
|
564 |
+
</td>
|
565 |
+
<td align="left"><code>True</code></td>
|
566 |
+
<td align="left">If True (default), root-level properties are rendered before nested groups. If False, they are rendered after.</td>
|
567 |
+
</tr>
|
568 |
+
|
569 |
<tr>
|
570 |
<td align="left"><code>disable_accordion</code></td>
|
571 |
<td align="left" style="width: 25%;">
|
app.py
CHANGED
@@ -17,7 +17,7 @@ class ModelSettings:
|
|
17 |
default="/path/to/default.safetensors",
|
18 |
metadata={
|
19 |
"label": "Custom Model Path",
|
20 |
-
"interactive_if": {"field": "
|
21 |
},
|
22 |
)
|
23 |
vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
|
@@ -53,7 +53,7 @@ class SamplingSettings:
|
|
53 |
"minimum": 0.0,
|
54 |
"maximum": 1.0,
|
55 |
"step": 0.01,
|
56 |
-
"interactive_if": {"field": "
|
57 |
},
|
58 |
)
|
59 |
temperature: float = field(
|
@@ -66,6 +66,7 @@ class SamplingSettings:
|
|
66 |
"step": 0.1
|
67 |
}
|
68 |
)
|
|
|
69 |
@dataclass
|
70 |
class RenderConfig:
|
71 |
randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
|
@@ -76,7 +77,6 @@ class RenderConfig:
|
|
76 |
model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
|
77 |
sampling: SamplingSettings = field(default_factory=SamplingSettings)
|
78 |
|
79 |
-
|
80 |
@dataclass
|
81 |
class Lighting:
|
82 |
sun_intensity: float = field(
|
@@ -187,7 +187,7 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
|
|
187 |
height=550,
|
188 |
visible=False,
|
189 |
root_label="Generator",
|
190 |
-
interactive=True
|
191 |
)
|
192 |
environment_sheet = PropertySheet(
|
193 |
value=initial_env_config,
|
@@ -196,7 +196,8 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
|
|
196 |
open=False,
|
197 |
visible=False,
|
198 |
root_label="General",
|
199 |
-
interactive=True
|
|
|
200 |
)
|
201 |
|
202 |
def change_visibility(is_visible, render_cfg, env_cfg):
|
|
|
17 |
default="/path/to/default.safetensors",
|
18 |
metadata={
|
19 |
"label": "Custom Model Path",
|
20 |
+
"interactive_if": {"field": "model_type", "value": "Custom"},
|
21 |
},
|
22 |
)
|
23 |
vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
|
|
|
53 |
"minimum": 0.0,
|
54 |
"maximum": 1.0,
|
55 |
"step": 0.01,
|
56 |
+
"interactive_if": {"field": "enable_advanced", "value": True},
|
57 |
},
|
58 |
)
|
59 |
temperature: float = field(
|
|
|
66 |
"step": 0.1
|
67 |
}
|
68 |
)
|
69 |
+
|
70 |
@dataclass
|
71 |
class RenderConfig:
|
72 |
randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
|
|
|
77 |
model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
|
78 |
sampling: SamplingSettings = field(default_factory=SamplingSettings)
|
79 |
|
|
|
80 |
@dataclass
|
81 |
class Lighting:
|
82 |
sun_intensity: float = field(
|
|
|
187 |
height=550,
|
188 |
visible=False,
|
189 |
root_label="Generator",
|
190 |
+
interactive=True
|
191 |
)
|
192 |
environment_sheet = PropertySheet(
|
193 |
value=initial_env_config,
|
|
|
196 |
open=False,
|
197 |
visible=False,
|
198 |
root_label="General",
|
199 |
+
interactive=True,
|
200 |
+
root_properties_first=False
|
201 |
)
|
202 |
|
203 |
def change_visibility(is_visible, render_cfg, env_cfg):
|
space.py
CHANGED
@@ -3,7 +3,7 @@ import gradio as gr
|
|
3 |
from app import demo as app
|
4 |
import os
|
5 |
|
6 |
-
_docs = {'PropertySheet': {'description': 'A Gradio component that renders a dynamic UI from a Python dataclass instance.\nIt allows for nested settings and automatically infers input types.', 'members': {'__init__': {'value': {'type': 'typing.Optional[typing.Any][Any, None]', 'default': 'None', 'description': 'The initial dataclass instance to render.'}, 'label': {'type': 'str | None', 'default': 'None', 'description': 'The main label for the component, displayed in the accordion header.'}, 'root_label': {'type': 'str', 'default': '"General"', 'description': 'The label for the root group of properties.'}, 'show_group_name_only_one': {'type': 'bool', 'default': 'True', 'description': 'If True, only the group name is shown when there is a single group.'}, 'disable_accordion': {'type': 'bool', 'default': 'False', 'description': 'If True, disables the accordion functionality.'}, 'visible': {'type': 'bool', 'default': 'True', 'description': 'If False, the component will be hidden.'}, 'open': {'type': 'bool', 'default': 'True', 'description': 'If False, the accordion will be collapsed by default.'}, 'elem_id': {'type': 'str | None', 'default': 'None', 'description': 'An optional string that is assigned as the id of this component in the DOM.'}, 'scale': {'type': 'int | None', 'default': 'None', 'description': 'The relative size of the component in its container.'}, 'width': {'type': 'int | str | None', 'default': 'None', 'description': 'The width of the component in pixels.'}, 'height': {'type': 'int | str | None', 'default': 'None', 'description': "The maximum height of the component's content area in pixels before scrolling."}, 'min_width': {'type': 'int | None', 'default': 'None', 'description': 'The minimum width of the component in pixels.'}, 'container': {'type': 'bool', 'default': 'True', 'description': 'If True, wraps the component in a container with a background.'}, 'elem_classes': {'type': 'list[str] | str | None', 'default': 'None', 'description': 'An optional list of strings that are assigned as the classes of this component in the DOM.'}}, 'postprocess': {'value': {'type': 'Any', 'description': 'The dataclass instance to process.'}}, 'preprocess': {'return': {'type': 'Any', 'description': 'A new, updated instance of the dataclass.'}, 'value': None}}, 'events': {'change': {'type': None, 'default': None, 'description': 'Triggered when the value of the PropertySheet changes either because of user input (e.g. a user types in a textbox) OR because of a function update (e.g. an image receives a value from the output of an event trigger). See `.input()` for a listener that is only triggered by user input.'}, 'input': {'type': None, 'default': None, 'description': 'This listener is triggered when the user changes the value of the PropertySheet.'}, 'expand': {'type': None, 'default': None, 'description': 'This listener is triggered when the PropertySheet is expanded.'}, 'collapse': {'type': None, 'default': None, 'description': 'This listener is triggered when the PropertySheet is collapsed.'}, 'undo': {'type': None, 'default': None, 'description': 'This listener is triggered when the user clicks the undo button in component.'}}}, '__meta__': {'additional_interfaces': {}, 'user_fn_refs': {'PropertySheet': []}}}
|
7 |
|
8 |
abs_path = os.path.join(os.path.dirname(__file__), "css.css")
|
9 |
|
@@ -57,7 +57,7 @@ class ModelSettings:
|
|
57 |
default="/path/to/default.safetensors",
|
58 |
metadata={
|
59 |
"label": "Custom Model Path",
|
60 |
-
"interactive_if": {"field": "
|
61 |
},
|
62 |
)
|
63 |
vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
|
@@ -93,7 +93,7 @@ class SamplingSettings:
|
|
93 |
"minimum": 0.0,
|
94 |
"maximum": 1.0,
|
95 |
"step": 0.01,
|
96 |
-
"interactive_if": {"field": "
|
97 |
},
|
98 |
)
|
99 |
temperature: float = field(
|
@@ -106,6 +106,7 @@ class SamplingSettings:
|
|
106 |
"step": 0.1
|
107 |
}
|
108 |
)
|
|
|
109 |
@dataclass
|
110 |
class RenderConfig:
|
111 |
randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
|
@@ -116,7 +117,6 @@ class RenderConfig:
|
|
116 |
model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
|
117 |
sampling: SamplingSettings = field(default_factory=SamplingSettings)
|
118 |
|
119 |
-
|
120 |
@dataclass
|
121 |
class Lighting:
|
122 |
sun_intensity: float = field(
|
@@ -227,7 +227,7 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
|
|
227 |
height=550,
|
228 |
visible=False,
|
229 |
root_label="Generator",
|
230 |
-
interactive=True
|
231 |
)
|
232 |
environment_sheet = PropertySheet(
|
233 |
value=initial_env_config,
|
@@ -236,7 +236,8 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
|
|
236 |
open=False,
|
237 |
visible=False,
|
238 |
root_label="General",
|
239 |
-
interactive=True
|
|
|
240 |
)
|
241 |
|
242 |
def change_visibility(is_visible, render_cfg, env_cfg):
|
|
|
3 |
from app import demo as app
|
4 |
import os
|
5 |
|
6 |
+
_docs = {'PropertySheet': {'description': 'A Gradio component that renders a dynamic UI from a Python dataclass instance.\nIt allows for nested settings and automatically infers input types.', 'members': {'__init__': {'value': {'type': 'typing.Optional[typing.Any][Any, None]', 'default': 'None', 'description': 'The initial dataclass instance to render.'}, 'label': {'type': 'str | None', 'default': 'None', 'description': 'The main label for the component, displayed in the accordion header.'}, 'root_label': {'type': 'str', 'default': '"General"', 'description': 'The label for the root group of properties.'}, 'show_group_name_only_one': {'type': 'bool', 'default': 'True', 'description': 'If True, only the group name is shown when there is a single group.'}, 'root_properties_first': {'type': 'bool', 'default': 'True', 'description': 'If True (default), root-level properties are rendered before nested groups. If False, they are rendered after.'}, 'disable_accordion': {'type': 'bool', 'default': 'False', 'description': 'If True, disables the accordion functionality.'}, 'visible': {'type': 'bool', 'default': 'True', 'description': 'If False, the component will be hidden.'}, 'open': {'type': 'bool', 'default': 'True', 'description': 'If False, the accordion will be collapsed by default.'}, 'elem_id': {'type': 'str | None', 'default': 'None', 'description': 'An optional string that is assigned as the id of this component in the DOM.'}, 'scale': {'type': 'int | None', 'default': 'None', 'description': 'The relative size of the component in its container.'}, 'width': {'type': 'int | str | None', 'default': 'None', 'description': 'The width of the component in pixels.'}, 'height': {'type': 'int | str | None', 'default': 'None', 'description': "The maximum height of the component's content area in pixels before scrolling."}, 'min_width': {'type': 'int | None', 'default': 'None', 'description': 'The minimum width of the component in pixels.'}, 'container': {'type': 'bool', 'default': 'True', 'description': 'If True, wraps the component in a container with a background.'}, 'elem_classes': {'type': 'list[str] | str | None', 'default': 'None', 'description': 'An optional list of strings that are assigned as the classes of this component in the DOM.'}}, 'postprocess': {'value': {'type': 'Any', 'description': 'The dataclass instance to process.'}}, 'preprocess': {'return': {'type': 'Any', 'description': 'A new, updated instance of the dataclass.'}, 'value': None}}, 'events': {'change': {'type': None, 'default': None, 'description': 'Triggered when the value of the PropertySheet changes either because of user input (e.g. a user types in a textbox) OR because of a function update (e.g. an image receives a value from the output of an event trigger). See `.input()` for a listener that is only triggered by user input.'}, 'input': {'type': None, 'default': None, 'description': 'This listener is triggered when the user changes the value of the PropertySheet.'}, 'expand': {'type': None, 'default': None, 'description': 'This listener is triggered when the PropertySheet is expanded.'}, 'collapse': {'type': None, 'default': None, 'description': 'This listener is triggered when the PropertySheet is collapsed.'}, 'undo': {'type': None, 'default': None, 'description': 'This listener is triggered when the user clicks the undo button in component.'}}}, '__meta__': {'additional_interfaces': {}, 'user_fn_refs': {'PropertySheet': []}}}
|
7 |
|
8 |
abs_path = os.path.join(os.path.dirname(__file__), "css.css")
|
9 |
|
|
|
57 |
default="/path/to/default.safetensors",
|
58 |
metadata={
|
59 |
"label": "Custom Model Path",
|
60 |
+
"interactive_if": {"field": "model_type", "value": "Custom"},
|
61 |
},
|
62 |
)
|
63 |
vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
|
|
|
93 |
"minimum": 0.0,
|
94 |
"maximum": 1.0,
|
95 |
"step": 0.01,
|
96 |
+
"interactive_if": {"field": "enable_advanced", "value": True},
|
97 |
},
|
98 |
)
|
99 |
temperature: float = field(
|
|
|
106 |
"step": 0.1
|
107 |
}
|
108 |
)
|
109 |
+
|
110 |
@dataclass
|
111 |
class RenderConfig:
|
112 |
randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
|
|
|
117 |
model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
|
118 |
sampling: SamplingSettings = field(default_factory=SamplingSettings)
|
119 |
|
|
|
120 |
@dataclass
|
121 |
class Lighting:
|
122 |
sun_intensity: float = field(
|
|
|
227 |
height=550,
|
228 |
visible=False,
|
229 |
root_label="Generator",
|
230 |
+
interactive=True
|
231 |
)
|
232 |
environment_sheet = PropertySheet(
|
233 |
value=initial_env_config,
|
|
|
236 |
open=False,
|
237 |
visible=False,
|
238 |
root_label="General",
|
239 |
+
interactive=True,
|
240 |
+
root_properties_first=False
|
241 |
)
|
242 |
|
243 |
def change_visibility(is_visible, render_cfg, env_cfg):
|
src/README.md
CHANGED
@@ -10,7 +10,7 @@ app_file: space.py
|
|
10 |
---
|
11 |
|
12 |
# `gradio_propertysheet`
|
13 |
-
<img alt="Static Badge" src="https://img.shields.io/badge/version%20-%200.0.
|
14 |
|
15 |
The **PropertySheet** component for Gradio allows you to automatically generate a complete and interactive settings panel from a standard Python `dataclass`. It's designed to bring the power of IDE-like property editors directly into your Gradio applications.
|
16 |
|
@@ -39,6 +39,7 @@ The **PropertySheet** component for Gradio allows you to automatically generate
|
|
39 |
|
40 |
## Installation
|
41 |
|
|
|
42 |
```bash
|
43 |
pip install gradio_propertysheet
|
44 |
```
|
@@ -65,7 +66,7 @@ class ModelSettings:
|
|
65 |
default="/path/to/default.safetensors",
|
66 |
metadata={
|
67 |
"label": "Custom Model Path",
|
68 |
-
"interactive_if": {"field": "
|
69 |
},
|
70 |
)
|
71 |
vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
|
@@ -101,7 +102,7 @@ class SamplingSettings:
|
|
101 |
"minimum": 0.0,
|
102 |
"maximum": 1.0,
|
103 |
"step": 0.01,
|
104 |
-
"interactive_if": {"field": "
|
105 |
},
|
106 |
)
|
107 |
temperature: float = field(
|
@@ -114,6 +115,7 @@ class SamplingSettings:
|
|
114 |
"step": 0.1
|
115 |
}
|
116 |
)
|
|
|
117 |
@dataclass
|
118 |
class RenderConfig:
|
119 |
randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
|
@@ -124,7 +126,6 @@ class RenderConfig:
|
|
124 |
model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
|
125 |
sampling: SamplingSettings = field(default_factory=SamplingSettings)
|
126 |
|
127 |
-
|
128 |
@dataclass
|
129 |
class Lighting:
|
130 |
sun_intensity: float = field(
|
@@ -235,7 +236,7 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
|
|
235 |
height=550,
|
236 |
visible=False,
|
237 |
root_label="Generator",
|
238 |
-
interactive=True
|
239 |
)
|
240 |
environment_sheet = PropertySheet(
|
241 |
value=initial_env_config,
|
@@ -244,7 +245,8 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
|
|
244 |
open=False,
|
245 |
visible=False,
|
246 |
root_label="General",
|
247 |
-
interactive=True
|
|
|
248 |
)
|
249 |
|
250 |
def change_visibility(is_visible, render_cfg, env_cfg):
|
@@ -551,6 +553,19 @@ bool
|
|
551 |
<td align="left">If True, only the group name is shown when there is a single group.</td>
|
552 |
</tr>
|
553 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
554 |
<tr>
|
555 |
<td align="left"><code>disable_accordion</code></td>
|
556 |
<td align="left" style="width: 25%;">
|
|
|
10 |
---
|
11 |
|
12 |
# `gradio_propertysheet`
|
13 |
+
<img alt="Static Badge" src="https://img.shields.io/badge/version%20-%200.0.9%20-%20blue"> <a href="https://huggingface.co/spaces/elismasilva/gradio_propertysheet"><img src="https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-Demo-blue"></a><p><span>💻 <a href='https://github.com/DEVAIEXP/gradio_component_propertysheet'>Component GitHub Code</a></span></p>
|
14 |
|
15 |
The **PropertySheet** component for Gradio allows you to automatically generate a complete and interactive settings panel from a standard Python `dataclass`. It's designed to bring the power of IDE-like property editors directly into your Gradio applications.
|
16 |
|
|
|
39 |
|
40 |
## Installation
|
41 |
|
42 |
+
|
43 |
```bash
|
44 |
pip install gradio_propertysheet
|
45 |
```
|
|
|
66 |
default="/path/to/default.safetensors",
|
67 |
metadata={
|
68 |
"label": "Custom Model Path",
|
69 |
+
"interactive_if": {"field": "model_type", "value": "Custom"},
|
70 |
},
|
71 |
)
|
72 |
vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
|
|
|
102 |
"minimum": 0.0,
|
103 |
"maximum": 1.0,
|
104 |
"step": 0.01,
|
105 |
+
"interactive_if": {"field": "enable_advanced", "value": True},
|
106 |
},
|
107 |
)
|
108 |
temperature: float = field(
|
|
|
115 |
"step": 0.1
|
116 |
}
|
117 |
)
|
118 |
+
|
119 |
@dataclass
|
120 |
class RenderConfig:
|
121 |
randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
|
|
|
126 |
model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
|
127 |
sampling: SamplingSettings = field(default_factory=SamplingSettings)
|
128 |
|
|
|
129 |
@dataclass
|
130 |
class Lighting:
|
131 |
sun_intensity: float = field(
|
|
|
236 |
height=550,
|
237 |
visible=False,
|
238 |
root_label="Generator",
|
239 |
+
interactive=True
|
240 |
)
|
241 |
environment_sheet = PropertySheet(
|
242 |
value=initial_env_config,
|
|
|
245 |
open=False,
|
246 |
visible=False,
|
247 |
root_label="General",
|
248 |
+
interactive=True,
|
249 |
+
root_properties_first=False
|
250 |
)
|
251 |
|
252 |
def change_visibility(is_visible, render_cfg, env_cfg):
|
|
|
553 |
<td align="left">If True, only the group name is shown when there is a single group.</td>
|
554 |
</tr>
|
555 |
|
556 |
+
<tr>
|
557 |
+
<td align="left"><code>root_properties_first</code></td>
|
558 |
+
<td align="left" style="width: 25%;">
|
559 |
+
|
560 |
+
```python
|
561 |
+
bool
|
562 |
+
```
|
563 |
+
|
564 |
+
</td>
|
565 |
+
<td align="left"><code>True</code></td>
|
566 |
+
<td align="left">If True (default), root-level properties are rendered before nested groups. If False, they are rendered after.</td>
|
567 |
+
</tr>
|
568 |
+
|
569 |
<tr>
|
570 |
<td align="left"><code>disable_accordion</code></td>
|
571 |
<td align="left" style="width: 25%;">
|
src/backend/gradio_propertysheet/propertysheet.py
CHANGED
@@ -42,6 +42,7 @@ class PropertySheet(Component):
|
|
42 |
label: str | None = None,
|
43 |
root_label: str = "General",
|
44 |
show_group_name_only_one: bool = True,
|
|
|
45 |
disable_accordion: bool = False,
|
46 |
visible: bool = True,
|
47 |
open: bool = True,
|
@@ -62,6 +63,7 @@ class PropertySheet(Component):
|
|
62 |
label: The main label for the component, displayed in the accordion header.
|
63 |
root_label: The label for the root group of properties.
|
64 |
show_group_name_only_one: If True, only the group name is shown when there is a single group.
|
|
|
65 |
disable_accordion: If True, disables the accordion functionality.
|
66 |
visible: If False, the component will be hidden.
|
67 |
open: If False, the accordion will be collapsed by default.
|
@@ -86,6 +88,7 @@ class PropertySheet(Component):
|
|
86 |
self.open = open
|
87 |
self.root_label = root_label
|
88 |
self.show_group_name_only_one = show_group_name_only_one
|
|
|
89 |
self.disable_accordion = disable_accordion
|
90 |
|
91 |
super().__init__(
|
@@ -132,23 +135,39 @@ class PropertySheet(Component):
|
|
132 |
if is_nested_dataclass:
|
133 |
group_obj = getattr(current_value, field.name)
|
134 |
group_props = []
|
135 |
-
|
136 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
137 |
metadata["name"] = f"{field.name}.{group_field.name}"
|
138 |
group_props.append(metadata)
|
139 |
|
140 |
-
base_group_name = field.
|
141 |
unique_group_name = base_group_name
|
142 |
counter = 2
|
143 |
-
# If the name is already used, append a counter until it's unique
|
144 |
while unique_group_name in used_group_names:
|
145 |
unique_group_name = f"{base_group_name} ({counter})"
|
146 |
counter += 1
|
147 |
|
148 |
-
used_group_names.add(unique_group_name)
|
149 |
json_schema.append({"group_name": unique_group_name, "properties": group_props})
|
150 |
else:
|
151 |
-
# Collect root properties to be processed later
|
152 |
root_properties.append(extract_prop_metadata(current_value, field))
|
153 |
|
154 |
# Process root properties, if any exist
|
@@ -161,8 +180,11 @@ class PropertySheet(Component):
|
|
161 |
unique_root_label = f"{base_root_label} ({counter})"
|
162 |
counter += 1
|
163 |
|
164 |
-
|
165 |
-
|
|
|
|
|
|
|
166 |
|
167 |
return json_schema
|
168 |
|
|
|
42 |
label: str | None = None,
|
43 |
root_label: str = "General",
|
44 |
show_group_name_only_one: bool = True,
|
45 |
+
root_properties_first: bool = True,
|
46 |
disable_accordion: bool = False,
|
47 |
visible: bool = True,
|
48 |
open: bool = True,
|
|
|
63 |
label: The main label for the component, displayed in the accordion header.
|
64 |
root_label: The label for the root group of properties.
|
65 |
show_group_name_only_one: If True, only the group name is shown when there is a single group.
|
66 |
+
root_properties_first: If True (default), root-level properties are rendered before nested groups. If False, they are rendered after.
|
67 |
disable_accordion: If True, disables the accordion functionality.
|
68 |
visible: If False, the component will be hidden.
|
69 |
open: If False, the accordion will be collapsed by default.
|
|
|
88 |
self.open = open
|
89 |
self.root_label = root_label
|
90 |
self.show_group_name_only_one = show_group_name_only_one
|
91 |
+
self.root_properties_first = root_properties_first
|
92 |
self.disable_accordion = disable_accordion
|
93 |
|
94 |
super().__init__(
|
|
|
135 |
if is_nested_dataclass:
|
136 |
group_obj = getattr(current_value, field.name)
|
137 |
group_props = []
|
138 |
+
group_type = type(group_obj)
|
139 |
+
parent_dataclass = next((b for b in group_type.__bases__ if dataclasses.is_dataclass(b)), None)
|
140 |
+
|
141 |
+
reordered_fields = []
|
142 |
+
if parent_dataclass:
|
143 |
+
all_fields = dataclasses.fields(group_type)
|
144 |
+
parent_field_names = {f.name for f in dataclasses.fields(parent_dataclass)}
|
145 |
+
|
146 |
+
own_fields = [f for f in all_fields if f.name not in parent_field_names]
|
147 |
+
inherited_fields = [f for f in all_fields if f.name in parent_field_names]
|
148 |
+
reordered_fields = own_fields + inherited_fields
|
149 |
+
else:
|
150 |
+
reordered_fields = dataclasses.fields(group_type)
|
151 |
+
|
152 |
+
for group_field in reordered_fields:
|
153 |
+
metadata = extract_prop_metadata(group_obj, group_field)
|
154 |
+
if "interactive_if" in metadata and "." not in metadata["interactive_if"]["field"]:
|
155 |
+
relative_field_name = metadata["interactive_if"]["field"]
|
156 |
+
metadata["interactive_if"]["field"] = f"{field.name}.{relative_field_name}"
|
157 |
+
|
158 |
metadata["name"] = f"{field.name}.{group_field.name}"
|
159 |
group_props.append(metadata)
|
160 |
|
161 |
+
base_group_name = field.name.replace("_", " ").title()
|
162 |
unique_group_name = base_group_name
|
163 |
counter = 2
|
|
|
164 |
while unique_group_name in used_group_names:
|
165 |
unique_group_name = f"{base_group_name} ({counter})"
|
166 |
counter += 1
|
167 |
|
168 |
+
used_group_names.add(unique_group_name)
|
169 |
json_schema.append({"group_name": unique_group_name, "properties": group_props})
|
170 |
else:
|
|
|
171 |
root_properties.append(extract_prop_metadata(current_value, field))
|
172 |
|
173 |
# Process root properties, if any exist
|
|
|
180 |
unique_root_label = f"{base_root_label} ({counter})"
|
181 |
counter += 1
|
182 |
|
183 |
+
root_group = {"group_name": unique_root_label, "properties": root_properties}
|
184 |
+
if self.root_properties_first:
|
185 |
+
json_schema.insert(0, root_group)
|
186 |
+
else:
|
187 |
+
json_schema.append(root_group)
|
188 |
|
189 |
return json_schema
|
190 |
|
src/demo/app.py
CHANGED
@@ -17,7 +17,7 @@ class ModelSettings:
|
|
17 |
default="/path/to/default.safetensors",
|
18 |
metadata={
|
19 |
"label": "Custom Model Path",
|
20 |
-
"interactive_if": {"field": "
|
21 |
},
|
22 |
)
|
23 |
vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
|
@@ -53,7 +53,7 @@ class SamplingSettings:
|
|
53 |
"minimum": 0.0,
|
54 |
"maximum": 1.0,
|
55 |
"step": 0.01,
|
56 |
-
"interactive_if": {"field": "
|
57 |
},
|
58 |
)
|
59 |
temperature: float = field(
|
@@ -66,6 +66,7 @@ class SamplingSettings:
|
|
66 |
"step": 0.1
|
67 |
}
|
68 |
)
|
|
|
69 |
@dataclass
|
70 |
class RenderConfig:
|
71 |
randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
|
@@ -76,7 +77,6 @@ class RenderConfig:
|
|
76 |
model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
|
77 |
sampling: SamplingSettings = field(default_factory=SamplingSettings)
|
78 |
|
79 |
-
|
80 |
@dataclass
|
81 |
class Lighting:
|
82 |
sun_intensity: float = field(
|
@@ -187,7 +187,7 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
|
|
187 |
height=550,
|
188 |
visible=False,
|
189 |
root_label="Generator",
|
190 |
-
interactive=True
|
191 |
)
|
192 |
environment_sheet = PropertySheet(
|
193 |
value=initial_env_config,
|
@@ -196,7 +196,8 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
|
|
196 |
open=False,
|
197 |
visible=False,
|
198 |
root_label="General",
|
199 |
-
interactive=True
|
|
|
200 |
)
|
201 |
|
202 |
def change_visibility(is_visible, render_cfg, env_cfg):
|
|
|
17 |
default="/path/to/default.safetensors",
|
18 |
metadata={
|
19 |
"label": "Custom Model Path",
|
20 |
+
"interactive_if": {"field": "model_type", "value": "Custom"},
|
21 |
},
|
22 |
)
|
23 |
vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
|
|
|
53 |
"minimum": 0.0,
|
54 |
"maximum": 1.0,
|
55 |
"step": 0.01,
|
56 |
+
"interactive_if": {"field": "enable_advanced", "value": True},
|
57 |
},
|
58 |
)
|
59 |
temperature: float = field(
|
|
|
66 |
"step": 0.1
|
67 |
}
|
68 |
)
|
69 |
+
|
70 |
@dataclass
|
71 |
class RenderConfig:
|
72 |
randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
|
|
|
77 |
model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
|
78 |
sampling: SamplingSettings = field(default_factory=SamplingSettings)
|
79 |
|
|
|
80 |
@dataclass
|
81 |
class Lighting:
|
82 |
sun_intensity: float = field(
|
|
|
187 |
height=550,
|
188 |
visible=False,
|
189 |
root_label="Generator",
|
190 |
+
interactive=True
|
191 |
)
|
192 |
environment_sheet = PropertySheet(
|
193 |
value=initial_env_config,
|
|
|
196 |
open=False,
|
197 |
visible=False,
|
198 |
root_label="General",
|
199 |
+
interactive=True,
|
200 |
+
root_properties_first=False
|
201 |
)
|
202 |
|
203 |
def change_visibility(is_visible, render_cfg, env_cfg):
|
src/demo/space.py
CHANGED
@@ -3,7 +3,7 @@ import gradio as gr
|
|
3 |
from app import demo as app
|
4 |
import os
|
5 |
|
6 |
-
_docs = {'PropertySheet': {'description': 'A Gradio component that renders a dynamic UI from a Python dataclass instance.\nIt allows for nested settings and automatically infers input types.', 'members': {'__init__': {'value': {'type': 'typing.Optional[typing.Any][Any, None]', 'default': 'None', 'description': 'The initial dataclass instance to render.'}, 'label': {'type': 'str | None', 'default': 'None', 'description': 'The main label for the component, displayed in the accordion header.'}, 'root_label': {'type': 'str', 'default': '"General"', 'description': 'The label for the root group of properties.'}, 'show_group_name_only_one': {'type': 'bool', 'default': 'True', 'description': 'If True, only the group name is shown when there is a single group.'}, 'disable_accordion': {'type': 'bool', 'default': 'False', 'description': 'If True, disables the accordion functionality.'}, 'visible': {'type': 'bool', 'default': 'True', 'description': 'If False, the component will be hidden.'}, 'open': {'type': 'bool', 'default': 'True', 'description': 'If False, the accordion will be collapsed by default.'}, 'elem_id': {'type': 'str | None', 'default': 'None', 'description': 'An optional string that is assigned as the id of this component in the DOM.'}, 'scale': {'type': 'int | None', 'default': 'None', 'description': 'The relative size of the component in its container.'}, 'width': {'type': 'int | str | None', 'default': 'None', 'description': 'The width of the component in pixels.'}, 'height': {'type': 'int | str | None', 'default': 'None', 'description': "The maximum height of the component's content area in pixels before scrolling."}, 'min_width': {'type': 'int | None', 'default': 'None', 'description': 'The minimum width of the component in pixels.'}, 'container': {'type': 'bool', 'default': 'True', 'description': 'If True, wraps the component in a container with a background.'}, 'elem_classes': {'type': 'list[str] | str | None', 'default': 'None', 'description': 'An optional list of strings that are assigned as the classes of this component in the DOM.'}}, 'postprocess': {'value': {'type': 'Any', 'description': 'The dataclass instance to process.'}}, 'preprocess': {'return': {'type': 'Any', 'description': 'A new, updated instance of the dataclass.'}, 'value': None}}, 'events': {'change': {'type': None, 'default': None, 'description': 'Triggered when the value of the PropertySheet changes either because of user input (e.g. a user types in a textbox) OR because of a function update (e.g. an image receives a value from the output of an event trigger). See `.input()` for a listener that is only triggered by user input.'}, 'input': {'type': None, 'default': None, 'description': 'This listener is triggered when the user changes the value of the PropertySheet.'}, 'expand': {'type': None, 'default': None, 'description': 'This listener is triggered when the PropertySheet is expanded.'}, 'collapse': {'type': None, 'default': None, 'description': 'This listener is triggered when the PropertySheet is collapsed.'}, 'undo': {'type': None, 'default': None, 'description': 'This listener is triggered when the user clicks the undo button in component.'}}}, '__meta__': {'additional_interfaces': {}, 'user_fn_refs': {'PropertySheet': []}}}
|
7 |
|
8 |
abs_path = os.path.join(os.path.dirname(__file__), "css.css")
|
9 |
|
@@ -57,7 +57,7 @@ class ModelSettings:
|
|
57 |
default="/path/to/default.safetensors",
|
58 |
metadata={
|
59 |
"label": "Custom Model Path",
|
60 |
-
"interactive_if": {"field": "
|
61 |
},
|
62 |
)
|
63 |
vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
|
@@ -93,7 +93,7 @@ class SamplingSettings:
|
|
93 |
"minimum": 0.0,
|
94 |
"maximum": 1.0,
|
95 |
"step": 0.01,
|
96 |
-
"interactive_if": {"field": "
|
97 |
},
|
98 |
)
|
99 |
temperature: float = field(
|
@@ -106,6 +106,7 @@ class SamplingSettings:
|
|
106 |
"step": 0.1
|
107 |
}
|
108 |
)
|
|
|
109 |
@dataclass
|
110 |
class RenderConfig:
|
111 |
randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
|
@@ -116,7 +117,6 @@ class RenderConfig:
|
|
116 |
model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
|
117 |
sampling: SamplingSettings = field(default_factory=SamplingSettings)
|
118 |
|
119 |
-
|
120 |
@dataclass
|
121 |
class Lighting:
|
122 |
sun_intensity: float = field(
|
@@ -227,7 +227,7 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
|
|
227 |
height=550,
|
228 |
visible=False,
|
229 |
root_label="Generator",
|
230 |
-
interactive=True
|
231 |
)
|
232 |
environment_sheet = PropertySheet(
|
233 |
value=initial_env_config,
|
@@ -236,7 +236,8 @@ with gr.Blocks(title="PropertySheet Demos") as demo:
|
|
236 |
open=False,
|
237 |
visible=False,
|
238 |
root_label="General",
|
239 |
-
interactive=True
|
|
|
240 |
)
|
241 |
|
242 |
def change_visibility(is_visible, render_cfg, env_cfg):
|
|
|
3 |
from app import demo as app
|
4 |
import os
|
5 |
|
6 |
+
_docs = {'PropertySheet': {'description': 'A Gradio component that renders a dynamic UI from a Python dataclass instance.\nIt allows for nested settings and automatically infers input types.', 'members': {'__init__': {'value': {'type': 'typing.Optional[typing.Any][Any, None]', 'default': 'None', 'description': 'The initial dataclass instance to render.'}, 'label': {'type': 'str | None', 'default': 'None', 'description': 'The main label for the component, displayed in the accordion header.'}, 'root_label': {'type': 'str', 'default': '"General"', 'description': 'The label for the root group of properties.'}, 'show_group_name_only_one': {'type': 'bool', 'default': 'True', 'description': 'If True, only the group name is shown when there is a single group.'}, 'root_properties_first': {'type': 'bool', 'default': 'True', 'description': 'If True (default), root-level properties are rendered before nested groups. If False, they are rendered after.'}, 'disable_accordion': {'type': 'bool', 'default': 'False', 'description': 'If True, disables the accordion functionality.'}, 'visible': {'type': 'bool', 'default': 'True', 'description': 'If False, the component will be hidden.'}, 'open': {'type': 'bool', 'default': 'True', 'description': 'If False, the accordion will be collapsed by default.'}, 'elem_id': {'type': 'str | None', 'default': 'None', 'description': 'An optional string that is assigned as the id of this component in the DOM.'}, 'scale': {'type': 'int | None', 'default': 'None', 'description': 'The relative size of the component in its container.'}, 'width': {'type': 'int | str | None', 'default': 'None', 'description': 'The width of the component in pixels.'}, 'height': {'type': 'int | str | None', 'default': 'None', 'description': "The maximum height of the component's content area in pixels before scrolling."}, 'min_width': {'type': 'int | None', 'default': 'None', 'description': 'The minimum width of the component in pixels.'}, 'container': {'type': 'bool', 'default': 'True', 'description': 'If True, wraps the component in a container with a background.'}, 'elem_classes': {'type': 'list[str] | str | None', 'default': 'None', 'description': 'An optional list of strings that are assigned as the classes of this component in the DOM.'}}, 'postprocess': {'value': {'type': 'Any', 'description': 'The dataclass instance to process.'}}, 'preprocess': {'return': {'type': 'Any', 'description': 'A new, updated instance of the dataclass.'}, 'value': None}}, 'events': {'change': {'type': None, 'default': None, 'description': 'Triggered when the value of the PropertySheet changes either because of user input (e.g. a user types in a textbox) OR because of a function update (e.g. an image receives a value from the output of an event trigger). See `.input()` for a listener that is only triggered by user input.'}, 'input': {'type': None, 'default': None, 'description': 'This listener is triggered when the user changes the value of the PropertySheet.'}, 'expand': {'type': None, 'default': None, 'description': 'This listener is triggered when the PropertySheet is expanded.'}, 'collapse': {'type': None, 'default': None, 'description': 'This listener is triggered when the PropertySheet is collapsed.'}, 'undo': {'type': None, 'default': None, 'description': 'This listener is triggered when the user clicks the undo button in component.'}}}, '__meta__': {'additional_interfaces': {}, 'user_fn_refs': {'PropertySheet': []}}}
|
7 |
|
8 |
abs_path = os.path.join(os.path.dirname(__file__), "css.css")
|
9 |
|
|
|
57 |
default="/path/to/default.safetensors",
|
58 |
metadata={
|
59 |
"label": "Custom Model Path",
|
60 |
+
"interactive_if": {"field": "model_type", "value": "Custom"},
|
61 |
},
|
62 |
)
|
63 |
vae_path: str = field(default="", metadata={"label": "VAE Path (optional)"})
|
|
|
93 |
"minimum": 0.0,
|
94 |
"maximum": 1.0,
|
95 |
"step": 0.01,
|
96 |
+
"interactive_if": {"field": "enable_advanced", "value": True},
|
97 |
},
|
98 |
)
|
99 |
temperature: float = field(
|
|
|
106 |
"step": 0.1
|
107 |
}
|
108 |
)
|
109 |
+
|
110 |
@dataclass
|
111 |
class RenderConfig:
|
112 |
randomize_seed: bool = field(default=True, metadata={"label": "Randomize Seed"})
|
|
|
117 |
model: ModelSettings = field(default_factory=ModelSettings, metadata={"label": "Model Settings"})
|
118 |
sampling: SamplingSettings = field(default_factory=SamplingSettings)
|
119 |
|
|
|
120 |
@dataclass
|
121 |
class Lighting:
|
122 |
sun_intensity: float = field(
|
|
|
227 |
height=550,
|
228 |
visible=False,
|
229 |
root_label="Generator",
|
230 |
+
interactive=True
|
231 |
)
|
232 |
environment_sheet = PropertySheet(
|
233 |
value=initial_env_config,
|
|
|
236 |
open=False,
|
237 |
visible=False,
|
238 |
root_label="General",
|
239 |
+
interactive=True,
|
240 |
+
root_properties_first=False
|
241 |
)
|
242 |
|
243 |
def change_visibility(is_visible, render_cfg, env_cfg):
|
src/pyproject.toml
CHANGED
@@ -8,7 +8,7 @@ build-backend = "hatchling.build"
|
|
8 |
|
9 |
[project]
|
10 |
name = "gradio_propertysheet"
|
11 |
-
version = "0.0.
|
12 |
description = "Property sheet"
|
13 |
readme = "README.md"
|
14 |
license = "apache-2.0"
|
|
|
8 |
|
9 |
[project]
|
10 |
name = "gradio_propertysheet"
|
11 |
+
version = "0.0.9"
|
12 |
description = "Property sheet"
|
13 |
readme = "README.md"
|
14 |
license = "apache-2.0"
|