syd 1.2.1__py3-none-any.whl → 1.2.3__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.
- syd/__init__.py +1 -1
- syd/flask_deployment/deployer.py +9 -1
- syd/flask_deployment/static/js/modules/api.js +4 -3
- syd/notebook_deployment/deployer.py +12 -2
- syd/parameters.py +18 -4
- syd/viewer.py +32 -6
- {syd-1.2.1.dist-info → syd-1.2.3.dist-info}/METADATA +3 -2
- {syd-1.2.1.dist-info → syd-1.2.3.dist-info}/RECORD +10 -10
- {syd-1.2.1.dist-info → syd-1.2.3.dist-info}/WHEEL +0 -0
- {syd-1.2.1.dist-info → syd-1.2.3.dist-info}/licenses/LICENSE +0 -0
syd/__init__.py
CHANGED
syd/flask_deployment/deployer.py
CHANGED
|
@@ -252,6 +252,7 @@ class FlaskDeployer:
|
|
|
252
252
|
with plot_context():
|
|
253
253
|
# Use the viewer's plot method with its current state
|
|
254
254
|
fig = self.viewer.plot(self.viewer.state)
|
|
255
|
+
self.viewer._figure = fig
|
|
255
256
|
if not isinstance(fig, mpl.figure.Figure):
|
|
256
257
|
raise TypeError(
|
|
257
258
|
f"viewer.plot() must return a matplotlib Figure, but got {type(fig)}"
|
|
@@ -310,6 +311,7 @@ class FlaskDeployer:
|
|
|
310
311
|
return jsonify({"error": f"Parameter '{name}' not found"}), 404
|
|
311
312
|
|
|
312
313
|
parameter = self.viewer.parameters[name]
|
|
314
|
+
replot = True
|
|
313
315
|
|
|
314
316
|
# Optionally suppress warnings during updates
|
|
315
317
|
with warnings.catch_warnings():
|
|
@@ -323,6 +325,7 @@ class FlaskDeployer:
|
|
|
323
325
|
if isinstance(parameter, ButtonAction) and parameter.callback:
|
|
324
326
|
# Pass the current state dictionary to the callback
|
|
325
327
|
parameter.callback(self.viewer.state)
|
|
328
|
+
replot = parameter.replot
|
|
326
329
|
else:
|
|
327
330
|
app.logger.warning(
|
|
328
331
|
f"Received action request for non-action parameter: {name}"
|
|
@@ -351,7 +354,12 @@ class FlaskDeployer:
|
|
|
351
354
|
for name, param in self.viewer.parameters.items()
|
|
352
355
|
}
|
|
353
356
|
return jsonify(
|
|
354
|
-
{
|
|
357
|
+
{
|
|
358
|
+
"success": True,
|
|
359
|
+
"state": final_state,
|
|
360
|
+
"params": final_param_info,
|
|
361
|
+
"replot": replot,
|
|
362
|
+
}
|
|
355
363
|
)
|
|
356
364
|
|
|
357
365
|
except Exception as e:
|
|
@@ -48,7 +48,7 @@ export async function updateParameterOnServer(name, value, action = false) {
|
|
|
48
48
|
if (!response.ok) {
|
|
49
49
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
50
50
|
}
|
|
51
|
-
return await response.json(); // Return the server response
|
|
51
|
+
return await response.json(); // Return the server response
|
|
52
52
|
} catch (error) {
|
|
53
53
|
console.error('Error updating parameter:', error);
|
|
54
54
|
updateStatus('Error updating parameter');
|
|
@@ -76,8 +76,9 @@ export function handleButtonClick(name) {
|
|
|
76
76
|
} else {
|
|
77
77
|
// Update state with any changes from callbacks
|
|
78
78
|
updateStateFromServer(data.state, data.params);
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
if (data.replot) {
|
|
80
|
+
updatePlot();
|
|
81
|
+
}
|
|
81
82
|
updateStatus('Ready!');
|
|
82
83
|
}
|
|
83
84
|
})
|
|
@@ -244,15 +244,18 @@ class NotebookDeployer:
|
|
|
244
244
|
# If the component is an action, call the callback
|
|
245
245
|
parameter = self.viewer.parameters[name]
|
|
246
246
|
parameter.callback(self.viewer.state)
|
|
247
|
+
replot = parameter.replot
|
|
247
248
|
else:
|
|
248
249
|
# Otherwise, update the parameter value
|
|
249
250
|
self.viewer.set_parameter_value(name, component.value)
|
|
251
|
+
replot = True
|
|
250
252
|
|
|
251
253
|
# Update any components that changed due to dependencies
|
|
252
254
|
self.sync_components_with_state()
|
|
253
255
|
|
|
254
256
|
# Update the plot
|
|
255
|
-
|
|
257
|
+
if replot:
|
|
258
|
+
self.update_plot()
|
|
256
259
|
|
|
257
260
|
def sync_components_with_state(self, exclude: Optional[str] = None) -> None:
|
|
258
261
|
"""Sync component values with viewer state."""
|
|
@@ -270,6 +273,7 @@ class NotebookDeployer:
|
|
|
270
273
|
|
|
271
274
|
with plot_context():
|
|
272
275
|
figure = self.viewer.plot(state)
|
|
276
|
+
self.viewer._figure = figure
|
|
273
277
|
|
|
274
278
|
# Update components if plot function updated a parameter
|
|
275
279
|
self.sync_components_with_state()
|
|
@@ -296,7 +300,13 @@ class NotebookDeployer:
|
|
|
296
300
|
display(figure.canvas)
|
|
297
301
|
|
|
298
302
|
else:
|
|
299
|
-
|
|
303
|
+
display(figure)
|
|
304
|
+
plt.close(figure)
|
|
305
|
+
print(
|
|
306
|
+
f"Backend type: ({self.backend_type}) is not explicitly supported."
|
|
307
|
+
"If you encounter weird behavior, try restarting with '%matplotlib inline' or '%matplotlib widget'."
|
|
308
|
+
"And please report this issue on github please :)."
|
|
309
|
+
)
|
|
300
310
|
|
|
301
311
|
if store_figure:
|
|
302
312
|
self._last_figure = figure
|
syd/parameters.py
CHANGED
|
@@ -1305,12 +1305,15 @@ class ButtonAction(Parameter[None]):
|
|
|
1305
1305
|
Text to display on the button (default is the button's name)
|
|
1306
1306
|
callback : callable
|
|
1307
1307
|
Function to execute when the button is clicked
|
|
1308
|
+
replot : bool, optional
|
|
1309
|
+
Whether to replot the figure after the callback is called.
|
|
1310
|
+
(default: True)
|
|
1308
1311
|
|
|
1309
1312
|
Examples
|
|
1310
1313
|
--------
|
|
1311
1314
|
>>> def print_hello():
|
|
1312
1315
|
... print("Hello!")
|
|
1313
|
-
>>> button = ButtonAction("greeting", label="Say Hello", callback=print_hello)
|
|
1316
|
+
>>> button = ButtonAction("greeting", label="Say Hello", callback=print_hello, replot=False)
|
|
1314
1317
|
>>> button.callback() # Simulates clicking the button
|
|
1315
1318
|
Hello!
|
|
1316
1319
|
>>> # Update the button's label and callback
|
|
@@ -1323,14 +1326,14 @@ class ButtonAction(Parameter[None]):
|
|
|
1323
1326
|
Notes
|
|
1324
1327
|
-----
|
|
1325
1328
|
Unlike other Parameter types, ButtonAction:
|
|
1326
|
-
- Has no value (always None
|
|
1327
|
-
- Is marked as an action (_is_action = True)
|
|
1329
|
+
- Has no value (always None, therefore cannot be updated through the value property
|
|
1328
1330
|
- Executes code directly rather than storing state
|
|
1329
|
-
-
|
|
1331
|
+
- Has an option to turn off replotting after the callback is called for cases where you want to access the last figure only.
|
|
1330
1332
|
"""
|
|
1331
1333
|
|
|
1332
1334
|
label: str
|
|
1333
1335
|
callback: Callable
|
|
1336
|
+
replot: bool
|
|
1334
1337
|
value: None = field(default=None, repr=False)
|
|
1335
1338
|
_is_action: bool = field(default=True, repr=False)
|
|
1336
1339
|
|
|
@@ -1339,6 +1342,7 @@ class ButtonAction(Parameter[None]):
|
|
|
1339
1342
|
name: str,
|
|
1340
1343
|
label: Union[str, NoInitialValue],
|
|
1341
1344
|
callback: Callable,
|
|
1345
|
+
replot: bool = True,
|
|
1342
1346
|
):
|
|
1343
1347
|
"""
|
|
1344
1348
|
Initialize a button.
|
|
@@ -1351,12 +1355,16 @@ class ButtonAction(Parameter[None]):
|
|
|
1351
1355
|
Text to display on the button (default is the button's name)
|
|
1352
1356
|
callback : callable
|
|
1353
1357
|
Function to execute when the button is clicked
|
|
1358
|
+
replot : bool, optional
|
|
1359
|
+
Whether to replot the figure after the callback is called.
|
|
1360
|
+
(default: True)
|
|
1354
1361
|
"""
|
|
1355
1362
|
self.name = name
|
|
1356
1363
|
if isinstance(label, NoInitialValue):
|
|
1357
1364
|
label = name
|
|
1358
1365
|
self.label = label
|
|
1359
1366
|
self.callback = callback
|
|
1367
|
+
self.replot = replot
|
|
1360
1368
|
self._value = None
|
|
1361
1369
|
|
|
1362
1370
|
def _validate(self, new_value: Any) -> None:
|
|
@@ -1371,6 +1379,12 @@ class ButtonAction(Parameter[None]):
|
|
|
1371
1379
|
type(self).__name__,
|
|
1372
1380
|
f"Callback {self.callback} is not callable",
|
|
1373
1381
|
)
|
|
1382
|
+
if not isinstance(self.replot, bool):
|
|
1383
|
+
raise ParameterUpdateError(
|
|
1384
|
+
self.name,
|
|
1385
|
+
type(self).__name__,
|
|
1386
|
+
f"Replet must be a boolean, got {type(self.replot)}",
|
|
1387
|
+
)
|
|
1374
1388
|
try:
|
|
1375
1389
|
str(self.label)
|
|
1376
1390
|
except Exception:
|
syd/viewer.py
CHANGED
|
@@ -157,12 +157,14 @@ class Viewer:
|
|
|
157
157
|
>>> viewer = MyViewer()
|
|
158
158
|
>>> viewer.add_float('x', value=1.0, min=0, max=10)
|
|
159
159
|
>>> viewer.on_change('x', viewer.update_based_on_x)
|
|
160
|
+
>>> viewer.show()
|
|
160
161
|
"""
|
|
161
162
|
|
|
162
163
|
parameters: Dict[str, Parameter]
|
|
163
164
|
callbacks: Dict[str, List[Callable]]
|
|
164
165
|
_app_deployed: bool
|
|
165
166
|
_in_callbacks: bool
|
|
167
|
+
_figure: Figure
|
|
166
168
|
|
|
167
169
|
def __new__(cls, *args, **kwargs):
|
|
168
170
|
instance = super().__new__(cls)
|
|
@@ -170,6 +172,7 @@ class Viewer:
|
|
|
170
172
|
instance.callbacks = {}
|
|
171
173
|
instance._app_deployed = False
|
|
172
174
|
instance._in_callbacks = False
|
|
175
|
+
instance._figure = None
|
|
173
176
|
return instance
|
|
174
177
|
|
|
175
178
|
@property
|
|
@@ -196,6 +199,13 @@ class Viewer:
|
|
|
196
199
|
if not param._is_action
|
|
197
200
|
}
|
|
198
201
|
|
|
202
|
+
@property
|
|
203
|
+
def figure(self) -> Figure:
|
|
204
|
+
"""
|
|
205
|
+
Get the last opened figure. Returns None if no figure has been opened yet.
|
|
206
|
+
"""
|
|
207
|
+
return self._figure
|
|
208
|
+
|
|
199
209
|
def plot(self, state: Dict[str, Any]) -> Figure:
|
|
200
210
|
"""Create and return a matplotlib figure.
|
|
201
211
|
|
|
@@ -942,6 +952,7 @@ class Viewer:
|
|
|
942
952
|
*,
|
|
943
953
|
label: Union[str, NoInitialValue] = NO_INITIAL_VALUE,
|
|
944
954
|
callback: Callable[[], None],
|
|
955
|
+
replot: bool = True,
|
|
945
956
|
) -> None:
|
|
946
957
|
"""
|
|
947
958
|
Add a button parameter to the viewer.
|
|
@@ -959,16 +970,24 @@ class Viewer:
|
|
|
959
970
|
If not provided, the parameter's label will be set to the name.
|
|
960
971
|
callback : callable
|
|
961
972
|
Function to call when the button is clicked (takes state as a single argument)
|
|
973
|
+
replot : bool, optional
|
|
974
|
+
Whether to replot the figure after the callback is called.
|
|
975
|
+
(default: True)
|
|
962
976
|
|
|
963
977
|
Examples
|
|
964
978
|
--------
|
|
965
|
-
>>> def
|
|
966
|
-
... print("
|
|
967
|
-
|
|
979
|
+
>>> def save_figure(state):
|
|
980
|
+
... print("Saving figure...")
|
|
981
|
+
... viewer.figure.savefig('last_figure.png')
|
|
982
|
+
>>> viewer.add_button('save', label='Save Figure', callback=save_figure, replot=False)
|
|
968
983
|
|
|
969
984
|
>>> def print_plot_info(state):
|
|
970
985
|
... print(f"Current plot info: {state['plot_info']}")
|
|
971
|
-
>>> viewer.add_button('print_info', label='Print Plot Info', callback=print_plot_info)
|
|
986
|
+
>>> viewer.add_button('print_info', label='Print Plot Info', callback=print_plot_info, replot=False)
|
|
987
|
+
|
|
988
|
+
>>> def reset_plot(state):
|
|
989
|
+
... print("Resetting plot...")
|
|
990
|
+
>>> viewer.add_button('reset', label='Reset Plot', callback=reset_plot)
|
|
972
991
|
"""
|
|
973
992
|
try:
|
|
974
993
|
callback = self._prepare_function(
|
|
@@ -976,7 +995,7 @@ class Viewer:
|
|
|
976
995
|
context="Setting button callback:",
|
|
977
996
|
)
|
|
978
997
|
|
|
979
|
-
new_param = ActionType.button.value(name, label, callback)
|
|
998
|
+
new_param = ActionType.button.value(name, label, callback, replot)
|
|
980
999
|
except Exception as e:
|
|
981
1000
|
raise ParameterAddError(name, "button", str(e)) from e
|
|
982
1001
|
else:
|
|
@@ -1398,6 +1417,7 @@ class Viewer:
|
|
|
1398
1417
|
*,
|
|
1399
1418
|
label: Union[str, NoUpdate] = NO_UPDATE,
|
|
1400
1419
|
callback: Union[Callable[[], None], NoUpdate] = NO_UPDATE,
|
|
1420
|
+
replot: Union[bool, NoUpdate] = NO_UPDATE,
|
|
1401
1421
|
) -> None:
|
|
1402
1422
|
"""
|
|
1403
1423
|
Update a button parameter's label and/or callback function.
|
|
@@ -1413,6 +1433,9 @@ class Viewer:
|
|
|
1413
1433
|
New text to display on the button (if not provided, no change)
|
|
1414
1434
|
callback : Union[callable, NoUpdate], optional
|
|
1415
1435
|
New function to call when clicked (if not provided, no change)
|
|
1436
|
+
replot : Union[bool, NoUpdate], optional
|
|
1437
|
+
Whether to replot the figure after the callback is called.
|
|
1438
|
+
(default: True)
|
|
1416
1439
|
|
|
1417
1440
|
Examples
|
|
1418
1441
|
--------
|
|
@@ -1420,7 +1443,8 @@ class Viewer:
|
|
|
1420
1443
|
... print("New action...")
|
|
1421
1444
|
>>> viewer.update_button('reset',
|
|
1422
1445
|
... label='New Action!',
|
|
1423
|
-
... callback=new_callback
|
|
1446
|
+
... callback=new_callback,
|
|
1447
|
+
... replot=False)
|
|
1424
1448
|
"""
|
|
1425
1449
|
updates = {}
|
|
1426
1450
|
if not label == NO_UPDATE:
|
|
@@ -1439,5 +1463,7 @@ class Viewer:
|
|
|
1439
1463
|
) from e
|
|
1440
1464
|
else:
|
|
1441
1465
|
updates["callback"] = callback
|
|
1466
|
+
if not replot == NO_UPDATE:
|
|
1467
|
+
updates["replot"] = replot
|
|
1442
1468
|
if updates:
|
|
1443
1469
|
self.parameters[name].update(updates)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: syd
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.3
|
|
4
4
|
Summary: A Python package for making GUIs for data science easy.
|
|
5
5
|
Project-URL: Homepage, https://github.com/landoskape/syd
|
|
6
6
|
Author-email: Andrew Landau <andrew+tyler+landau+getridofthisanddtheplusses@gmail.com>
|
|
@@ -12,12 +12,13 @@ Classifier: Intended Audience :: Developers
|
|
|
12
12
|
Classifier: Intended Audience :: Science/Research
|
|
13
13
|
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
|
14
14
|
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
15
16
|
Classifier: Programming Language :: Python :: 3.9
|
|
16
17
|
Classifier: Programming Language :: Python :: 3.10
|
|
17
18
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
20
|
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
-
Requires-Python: >=3.
|
|
21
|
+
Requires-Python: >=3.8
|
|
21
22
|
Requires-Dist: flask
|
|
22
23
|
Requires-Dist: ipykernel
|
|
23
24
|
Requires-Dist: ipympl
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
syd/__init__.py,sha256=
|
|
2
|
-
syd/parameters.py,sha256=
|
|
1
|
+
syd/__init__.py,sha256=F9xhgvOaysdyubOmYiL698xHAJAEfmXPb6mLNpaZC2c,117
|
|
2
|
+
syd/parameters.py,sha256=lzCHSMGYEdQ_FMbcXnntdPF1XvCm7fybB6CNy3TFn04,43543
|
|
3
3
|
syd/support.py,sha256=LoHOsTN0byyDxk9uibjM0BKnI-vAJ4aU-tWILMCXz1Y,6783
|
|
4
|
-
syd/viewer.py,sha256=
|
|
4
|
+
syd/viewer.py,sha256=d1-uca7WPEoH8InDUg1osK5uQU6RQ0QXydwS_81EME0,52681
|
|
5
5
|
syd/flask_deployment/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
6
|
-
syd/flask_deployment/deployer.py,sha256=
|
|
6
|
+
syd/flask_deployment/deployer.py,sha256=GruWJ3pA6NI8tmMavQo4Sl8_jvZbFi1k8LGPPd2JkmU,29554
|
|
7
7
|
syd/flask_deployment/testing_principles.md,sha256=GyULM97sDeie8h3tSPoduOckdMNGyWuwm1RdHo5jzK0,10130
|
|
8
8
|
syd/flask_deployment/static/__init__.py,sha256=ieWE8NKR-APw7h4Ge0ooZGk6wZrneSSs_1cMyTPbQSA,65
|
|
9
9
|
syd/flask_deployment/static/css/styles.css,sha256=GQgIPbWMdfTgU-HN80FCObA8bd1FPiwa1Dq0yRANsPc,5944
|
|
10
10
|
syd/flask_deployment/static/css/viewer.css,sha256=rViWJ4w6vahuOr0RIpowgJfg7HN4TzMAuYrQmqhi1V0,805
|
|
11
11
|
syd/flask_deployment/static/js/old_viewer.js,sha256=aIh0gxrwMWUYVge4taj0pucg2RiCcWVuV9ekBvUVsPU,40594
|
|
12
12
|
syd/flask_deployment/static/js/viewer.js,sha256=D-I0hUZQPMSIgB9b8taWNVIsBBUeK1VpLjWI1KtOgSo,2672
|
|
13
|
-
syd/flask_deployment/static/js/modules/api.js,sha256=
|
|
13
|
+
syd/flask_deployment/static/js/modules/api.js,sha256=4qZW9DKH-IqslOKj4ypV5Vju9wr9Qfhckf7BQGk1KqM,3117
|
|
14
14
|
syd/flask_deployment/static/js/modules/config.js,sha256=XxvyNhOUoyXXcacmhNzawKZiy9Q473sY98y7WipofLs,850
|
|
15
15
|
syd/flask_deployment/static/js/modules/plot.js,sha256=dHZAaw_hjrrMa1IGet8HhYJvB0Ze3KoFjmB6duuhFhg,2622
|
|
16
16
|
syd/flask_deployment/static/js/modules/state.js,sha256=-sfQ9ppDgr0p3XO5_oN3g-waf1-j0iwSfSSGS_lIK70,3133
|
|
@@ -20,9 +20,9 @@ syd/flask_deployment/static/js/modules/utils.js,sha256=xqIBRvTrZCnm65xZ9R6mqeHFn
|
|
|
20
20
|
syd/flask_deployment/templates/__init__.py,sha256=ieWE8NKR-APw7h4Ge0ooZGk6wZrneSSs_1cMyTPbQSA,65
|
|
21
21
|
syd/flask_deployment/templates/index.html,sha256=OmGaEdEPZ_ALPq7ZHk47jw-ZX9pOUUk57M3gXT0V1Lk,1608
|
|
22
22
|
syd/notebook_deployment/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
|
-
syd/notebook_deployment/deployer.py,sha256=
|
|
23
|
+
syd/notebook_deployment/deployer.py,sha256=ovuFvj5_qXB5WToNhCxrEHmPuKYypIeLqrUg0KjovQs,12706
|
|
24
24
|
syd/notebook_deployment/widgets.py,sha256=ptys7exVA6NCF4eCRZMTPJblT0ZbtPdN4o2A0Yh5Cfc,20781
|
|
25
|
-
syd-1.2.
|
|
26
|
-
syd-1.2.
|
|
27
|
-
syd-1.2.
|
|
28
|
-
syd-1.2.
|
|
25
|
+
syd-1.2.3.dist-info/METADATA,sha256=__2yUadLeltLH-FVG6A9BMQlMrf8PoY3R15iDe6ViCU,14984
|
|
26
|
+
syd-1.2.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
27
|
+
syd-1.2.3.dist-info/licenses/LICENSE,sha256=YF6QR6Vjxcg5b_sYIyqkME7FZYau5TfEUGTG-0JeRK0,35129
|
|
28
|
+
syd-1.2.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|