Rename Sud's Download/Upload to Save/Load throughout

Renames everywhere the concept appears: Sud.download()/upload() ->
save()/load(), the 'Download'/'Upload' websocket messages ->
'Save'/'Load', the brewpi_gui menu actions, handlers and
sud_download_path -> sud_save_path, and the demo script. Behavior is
unchanged - this is naming only, from the client's perspective (save
to / load from a local file) rather than the server's.
This commit is contained in:
2026-06-20 23:58:21 +02:00
parent 5d884ca3da
commit 13e507e2b5
6 changed files with 51 additions and 51 deletions
+6 -6
View File
@@ -3712,8 +3712,8 @@
<property name="title">
<string>&amp;File</string>
</property>
<addaction name="actionSudDownload"/>
<addaction name="actionSudUpload"/>
<addaction name="actionSudSave"/>
<addaction name="actionSudLoad"/>
</widget>
<widget class="QMenu" name="menu_Help">
<property name="title">
@@ -3765,17 +3765,17 @@
<string>Stop</string>
</property>
</action>
<action name="actionSudDownload">
<action name="actionSudSave">
<property name="text">
<string>&amp;Download Sud...</string>
<string>&amp;Save Sud...</string>
</property>
<property name="toolTip">
<string>Save the running Sud's schedule to a local sud.json</string>
</property>
</action>
<action name="actionSudUpload">
<action name="actionSudLoad">
<property name="text">
<string>&amp;Upload Sud...</string>
<string>&amp;Load Sud...</string>
</property>
<property name="toolTip">
<string>Replace the running Sud's schedule with a local sud.json</string>
+15 -15
View File
@@ -209,8 +209,8 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow):
self.actionStart.triggered.connect(self.on_action_sud_start)
self.actionPause.triggered.connect(self.on_action_sud_pause)
self.actionStop.triggered.connect(self.on_action_sud_stop)
self.actionSudDownload.triggered.connect(self.on_action_sud_download)
self.actionSudUpload.triggered.connect(self.on_action_sud_upload)
self.actionSudSave.triggered.connect(self.on_action_sud_save)
self.actionSudLoad.triggered.connect(self.on_action_sud_load)
self.Slider_pwr_soll.valueChanged.connect(self.on_slider_pwr_soll_changed)
self.Slider_temp_soll.valueChanged.connect(self.on_slider_temp_soll_changed)
self.Slider_speed_soll.valueChanged.connect(self.on_slider_stirrer_speed_soll_changed)
@@ -227,7 +227,7 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow):
self.checkbox_heater_activate_initial_update = True
self.checkbox_stirrer_activate_initial_update = True
self.heatrate_soll_initial_update = True
self.sud_download_path = None
self.sud_save_path = None
# Latest values sampled by the plot timer - written from the
# websocket recv thread, read from the GUI thread; plain floats so
@@ -263,10 +263,10 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow):
self.plot.reset()
self.ws_client.connect(uri=self.plainTextUri.toPlainText())
# Fetch the schedule for the Automatic tab's forecast preview - not
# a user-initiated download, so sud_download_path stays None and
# a user-initiated save, so sud_save_path stays None and
# on_sud_changed() routes the reply to update_sud_forecast() instead
# of a save dialog.
self.msg_sud.send({'Download': True})
self.msg_sud.send({'Save': True})
def on_plot_timer(self):
self.plot.sample(
@@ -352,23 +352,23 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow):
def on_action_sud_stop(self):
self.msg_sud.send({'Stop': True})
def on_action_sud_download(self):
def on_action_sud_save(self):
# Pick the destination up front, on the GUI thread - the actual
# write happens in on_sud_changed(), which runs off a worker thread
# and must not touch Qt (e.g. open a file dialog) itself.
path, _ = QtWidgets.QFileDialog.getSaveFileName(self, "Download Sud", filter="JSON files (*.json)")
path, _ = QtWidgets.QFileDialog.getSaveFileName(self, "Save Sud", filter="JSON files (*.json)")
if not path:
return
self.sud_download_path = path
self.msg_sud.send({'Download': True})
self.sud_save_path = path
self.msg_sud.send({'Save': True})
def on_action_sud_upload(self):
path, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Upload Sud", filter="JSON files (*.json)")
def on_action_sud_load(self):
path, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Load Sud", filter="JSON files (*.json)")
if not path:
return
with open(path) as f:
data = json.load(f)
self.msg_sud.send({'Upload': data})
self.msg_sud.send({'Load': data})
def on_pot_changed(self, msg):
print("on_pot_changed {}".format(msg))
@@ -458,10 +458,10 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow):
self.sud_loaded = True
for key in msg:
if "Json" in key:
if self.sud_download_path:
with open(self.sud_download_path, 'w') as f:
if self.sud_save_path:
with open(self.sud_save_path, 'w') as f:
json.dump(msg['Json'], f, indent='\t')
self.sud_download_path = None
self.sud_save_path = None
else:
self.update_sud_forecast(msg['Json'])
elif "Name" in key:
+10 -10
View File
@@ -1255,12 +1255,12 @@ class Ui_MainWindow(object):
self.actionPause.setObjectName("actionPause")
self.actionStop = QtWidgets.QAction(MainWindow)
self.actionStop.setObjectName("actionStop")
self.actionSudDownload = QtWidgets.QAction(MainWindow)
self.actionSudDownload.setObjectName("actionSudDownload")
self.actionSudUpload = QtWidgets.QAction(MainWindow)
self.actionSudUpload.setObjectName("actionSudUpload")
self.menu_File.addAction(self.actionSudDownload)
self.menu_File.addAction(self.actionSudUpload)
self.actionSudSave = QtWidgets.QAction(MainWindow)
self.actionSudSave.setObjectName("actionSudSave")
self.actionSudLoad = QtWidgets.QAction(MainWindow)
self.actionSudLoad.setObjectName("actionSudLoad")
self.menu_File.addAction(self.actionSudSave)
self.menu_File.addAction(self.actionSudLoad)
self.menubar.addAction(self.menu_File.menuAction())
self.menubar.addAction(self.menu_Help.menuAction())
self.toolBar.addAction(self.actionStart)
@@ -1306,7 +1306,7 @@ class Ui_MainWindow(object):
self.actionPause.setToolTip(_translate("MainWindow", "Pause"))
self.actionStop.setText(_translate("MainWindow", "Stop"))
self.actionStop.setToolTip(_translate("MainWindow", "Stop"))
self.actionSudDownload.setText(_translate("MainWindow", "&Download Sud..."))
self.actionSudDownload.setToolTip(_translate("MainWindow", "Save the running Sud\'s schedule to a local sud.json"))
self.actionSudUpload.setText(_translate("MainWindow", "&Upload Sud..."))
self.actionSudUpload.setToolTip(_translate("MainWindow", "Replace the running Sud\'s schedule with a local sud.json"))
self.actionSudSave.setText(_translate("MainWindow", "&Save Sud..."))
self.actionSudSave.setToolTip(_translate("MainWindow", "Save the running Sud\'s schedule to a local sud.json"))
self.actionSudLoad.setText(_translate("MainWindow", "&Load Sud..."))
self.actionSudLoad.setToolTip(_translate("MainWindow", "Replace the running Sud\'s schedule with a local sud.json"))
+5 -5
View File
@@ -63,7 +63,7 @@ class Sud(AttributeChange):
def _parse_data(data):
"""Parses a sud.json document into the (name, description, schedule,
pot_mass, pot_material) tuple Sud needs. Computed up front rather
than assigned straight onto self, so a malformed upload() can't
than assigned straight onto self, so a malformed load() can't
leave a half-applied schedule in place."""
name = data.get('Name', '')
description = data.get('Description', '')
@@ -78,7 +78,7 @@ class Sud(AttributeChange):
def _reset_run_state(self):
"""Resets run-time progress back to a freshly-loaded, not-yet-started
IDLE state. Shared by __init__, upload(), and stop()."""
IDLE state. Shared by __init__, load(), and stop()."""
self.index = -1
self.hold_remaining = 0.0
self.state = SudState.IDLE
@@ -86,13 +86,13 @@ class Sud(AttributeChange):
self.user_message = None
self._paused_from = None
def download(self):
def save(self):
"""Returns the sud.json document currently on disk, for a client to
edit and hand back to upload()."""
edit and hand back to load()."""
with open(self.path) as f:
return json.load(f)
def upload(self, data):
def load(self, data):
"""Replaces the schedule with a new sud.json document and persists
it to disk, resetting to IDLE as if freshly loaded from that file.
Refused while a brew is in progress, or if data is malformed - in
@@ -5,7 +5,7 @@ from pathlib import Path
from components.sud import Sud, SudState
# Console-only walkthrough of Sud.download()/upload() (no plot - there's no
# Console-only walkthrough of Sud.save()/load() (no plot - there's no
# numeric data here, just JSON plumbing). Runs against a scratch copy of a
# real sud.json so sude/sud_0010.json itself is never touched.
@@ -17,29 +17,29 @@ if __name__ == '__main__':
sud = Sud(str(path))
print(f"Loaded '{sud.name}', {len(sud.schedule)} steps")
doc = sud.download()
doc = sud.save()
assert doc['Name'] == sud.name
print("download() returned the on-disk document")
print("save() returned the on-disk document")
sud.state = SudState.RAMPING
assert sud.upload(doc) is False
print("upload() refused while RAMPING")
assert sud.load(doc) is False
print("load() refused while RAMPING")
sud.state = SudState.IDLE
doc['Name'] = 'Sud-Renamed'
doc['steps'][0]['descr'] = 'Edited step'
assert sud.upload(doc) is True
assert sud.load(doc) is True
assert sud.name == 'Sud-Renamed'
assert sud.schedule[0]['descr'] == 'Edited step'
assert sud.state == SudState.IDLE
print("upload() applied the edit and reset to IDLE")
print("load() applied the edit and reset to IDLE")
on_disk = json.loads(path.read_text())
assert on_disk['Name'] == 'Sud-Renamed'
print("upload() persisted the edit to disk")
print("load() persisted the edit to disk")
assert sud.upload({'Name': 'broken'}) is False
assert sud.load({'Name': 'broken'}) is False
assert sud.name == 'Sud-Renamed'
print("upload() rejected malformed data, left schedule untouched")
print("load() rejected malformed data, left schedule untouched")
print("All sud upload/download checks passed")
print("All sud save/load checks passed")
+4 -4
View File
@@ -73,10 +73,10 @@ class SudTask(ATask):
self.sud.pause()
elif 'Stop' in pair[0]:
self.sud.stop()
elif 'Download' in pair[0]:
await self.send({'Json': self.sud.download()})
elif 'Upload' in pair[0]:
if self.sud.upload(pair[1]):
elif 'Save' in pair[0]:
await self.send({'Json': self.sud.save()})
elif 'Load' in pair[0]:
if self.sud.load(pair[1]):
await self.send({'Name': self.sud.name, 'Description': self.sud.description})
await self.send({'Json': pair[1]})