diff --git a/.appveyor.yml b/.appveyor.yml
index 7aaaffa61..f9f72e3ca 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -20,7 +20,7 @@ environment:
# Set the Appveyor Python version for windows, macos and linux here. Does not affect windows_legacy.
PYTHON_V: 3.11
# Upgrade to specific version (for platforms supporting upgrade). Upgrade skipped if env var is missing or blank.
- PYUPGRADE_V: 3.11.5
+# PYUPGRADE_V: 3.11.5 # causes ssl problems failing to connect to plus
matrix:
- job_name: windows_legacy
diff --git a/src/artisanlib/canvas.py b/src/artisanlib/canvas.py
index 988c618f2..516c075c9 100644
--- a/src/artisanlib/canvas.py
+++ b/src/artisanlib/canvas.py
@@ -3304,7 +3304,7 @@ def update_additional_artists(self) -> None:
linestyle = '-', linewidth= 1, alpha = .5,sketch_params=None,path_effects=[])
else:
self.l_timeline.set_xdata(tx)
- self.ax.draw_artist(self.l_timeline)
+ self.ax.draw_artist(self.l_timeline)
if self.projectFlag:
if self.l_BTprojection is not None and self.BTcurve:
self.ax.draw_artist(self.l_BTprojection)
@@ -6673,6 +6673,8 @@ def reset(self,redraw=True,soundOn=True,sampling=False,keepProperties=False,fire
self.l_event_flags_dict = {} # initiate the event id to temp/time annotation dict for flags
self.l_background_annotations = [] # initiate the background event annotations
+ self.l_timeline = None # clear timeline Artist to get the linecount correct after changning a machine setup
+
if not sampling:
self.aw.hideDefaultButtons()
self.aw.updateExtraButtonsVisibility()
diff --git a/src/artisanlib/curves.py b/src/artisanlib/curves.py
index 250025758..46888cd9c 100644
--- a/src/artisanlib/curves.py
+++ b/src/artisanlib/curves.py
@@ -1504,16 +1504,16 @@ def renameBT(self):
self.aw.BTname = str(self.renameBTLine.text()).strip()
if self.aw.BTname == '':
self.aw.BTname = QApplication.translate('Label', 'BT')
- self.aw.label3.setText('' + self.aw.BTname + '')
- self.aw.label5.setText(deltaLabelBigPrefix + self.aw.BTname + '')
+ self.aw.label3.setText(f'{self.aw.BTname}'.format(self.aw.qmc.etypes[0],self.aw.qmc.etypes[1],self.aw.qmc.etypes[2],self.aw.qmc.etypes[3]))
+ self.aw.label5.setText(f'{deltaLabelBigPrefix}{self.aw.BTname}'.format(self.aw.qmc.etypes[0],self.aw.qmc.etypes[1],self.aw.qmc.etypes[2],self.aw.qmc.etypes[3]))
@pyqtSlot()
def renameET(self):
self.aw.ETname = str(self.renameETLine.text()).strip()
if self.aw.ETname == '':
self.aw.ETname = QApplication.translate('Label', 'ET')
- self.aw.label2.setText('' + self.aw.ETname + '')
- self.aw.label4.setText(deltaLabelBigPrefix + self.aw.ETname + '')
+ self.aw.label2.setText(f'{self.aw.ETname}'.format(self.aw.qmc.etypes[0],self.aw.qmc.etypes[1],self.aw.qmc.etypes[2],self.aw.qmc.etypes[3]))
+ self.aw.label4.setText(f'{deltaLabelBigPrefix}{self.aw.ETname}'.format(self.aw.qmc.etypes[0],self.aw.qmc.etypes[1],self.aw.qmc.etypes[2],self.aw.qmc.etypes[3]))
@pyqtSlot(int)
def toggleWebLCDsAlerts(self,_):
@@ -1526,7 +1526,7 @@ def changeWebLCDsPort(self):
def setWebLCDsURL(self):
url_str = self.getWebLCDsURL()
# set URL label
- self.WebLCDsURL.setText('' + url_str + '')
+ self.WebLCDsURL.setText(f'{url_str}')
# set QR label
try:
from artisanlib.qrcode import QRlabel
@@ -1541,7 +1541,7 @@ def getWebLCDsURL(self):
s.connect(('8.8.8.8', 80))
localIP = s.getsockname()[0]
s.close()
- return 'http://' + str(localIP) + ':' + str(self.aw.WebLCDsPort) + '/artisan'
+ return f'http://{str(localIP)}:{str(self.aw.WebLCDsPort)}/artisan'
@pyqtSlot(bool)
def toggleWebLCDs(self,b):
diff --git a/src/artisanlib/large_lcds.py b/src/artisanlib/large_lcds.py
index 8306e317a..a842f6d5a 100644
--- a/src/artisanlib/large_lcds.py
+++ b/src/artisanlib/large_lcds.py
@@ -361,7 +361,7 @@ def makeLCDs(self):
self.lcd0.display('00:00')
# ET
ETlcd = self.makeLCD('et') # Environmental Temperature ET
- ETlabelUpper = self.makeLabel('' + self.aw.ETname + ' ')
+ ETlabelUpper = self.makeLabel(f'{self.aw.ETname.format(self.aw.qmc.etypes[0],self.aw.qmc.etypes[1],self.aw.qmc.etypes[2],self.aw.qmc.etypes[3])} ')
ETlabelLower = self.makeLabel(' ')
#
self.lcds1 = [ETlcd]
@@ -371,7 +371,7 @@ def makeLCDs(self):
self.lcds1frames = [self.makeLCDframe(ETlabelUpper,ETlcd,ETlabelLower)]
# BT
BTlcd = self.makeLCD('bt') # Bean Temperature BT
- BTlabelUpper = self.makeLabel('' + self.aw.BTname + ' ')
+ BTlabelUpper = self.makeLabel(f'{self.aw.BTname.format(self.aw.qmc.etypes[0],self.aw.qmc.etypes[1],self.aw.qmc.etypes[2],self.aw.qmc.etypes[3])} ')
BTlabelLower = self.makeLabel(' ')
#
self.lcds2 = [BTlcd]
@@ -490,7 +490,7 @@ def __init__(self, parent = None, aw = None) -> None:
def makeLCDs(self):
self.lcds1styles = ['deltaet']
self.lcds1 = [self.makeLCD(self.lcds1styles[0])] # DeltaET
- label1Upper = self.makeLabel('Δ' + self.aw.ETname + ' ')
+ label1Upper = self.makeLabel(f'Δ{self.aw.ETname.format(self.aw.qmc.etypes[0],self.aw.qmc.etypes[1],self.aw.qmc.etypes[2],self.aw.qmc.etypes[3])} ')
label1Lower = self.makeLabel(' ')
self.lcds1labelsUpper = [label1Upper]
self.lcds1labelsLower = [label1Lower]
@@ -498,7 +498,7 @@ def makeLCDs(self):
#
self.lcds2styles = ['deltabt']
self.lcds2 = [self.makeLCD(self.lcds2styles[0])] # DeltaBT
- label2Upper = self.makeLabel('Δ' + self.aw.BTname + ' ')
+ label2Upper = self.makeLabel(f'Δ{self.aw.BTname.format(self.aw.qmc.etypes[0],self.aw.qmc.etypes[1],self.aw.qmc.etypes[2],self.aw.qmc.etypes[3])} ')
label2Lower = self.makeLabel(' ')
self.lcds2labelsUpper = [label2Upper]
self.lcds2labelsLower = [label2Lower]
diff --git a/src/artisanlib/main.py b/src/artisanlib/main.py
index 8cae34098..4f916193a 100644
--- a/src/artisanlib/main.py
+++ b/src/artisanlib/main.py
@@ -3175,31 +3175,31 @@ def __init__(self, parent:Optional[QWidget] = None, *, locale:str, WebEngineSupp
#MET
self.label2 = QLabel()
self.label2.setAlignment(Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignRight)
- self.label2.setText('' + QApplication.translate('Label', 'ET') + '')
+ self.label2.setText(f"{QApplication.translate('Label', 'ET')}")
self.setLabelColor(self.label2,QColor(self.qmc.palette['et']))
#BT
self.label3 = QLabel()
self.label3.setAlignment(Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignRight)
- self.label3.setText('' + QApplication.translate('Label', 'BT') + '')
+ self.label3.setText(f"{QApplication.translate('Label', 'BT')}")
self.setLabelColor(self.label3,QColor(self.qmc.palette['bt']))
#DELTA MET
self.label4 = QLabel()
self.label4.setAlignment(Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignRight)
- self.label4.setText(deltaLabelBigPrefix + QApplication.translate('Label', 'ET') + '')
+ self.label4.setText(f"{deltaLabelBigPrefix}{QApplication.translate('Label', 'ET')}")
self.setLabelColor(self.label4,QColor(self.qmc.palette['deltaet']))
# DELTA BT
self.label5 = QLabel()
self.label5.setAlignment(Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignRight)
- self.label5.setText(deltaLabelBigPrefix + QApplication.translate('Label', 'BT') + '')
+ self.label5.setText(f"{deltaLabelBigPrefix}{QApplication.translate('Label', 'BT')}")
self.setLabelColor(self.label5,QColor(self.qmc.palette['deltabt']))
# pid sv
self.label6 = QLabel()
self.label6.setAlignment(Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignRight)
- self.label6.setText('' + QApplication.translate('Label', 'PID SV') + '')
+ self.label6.setText(f"{QApplication.translate('Label', 'PID SV')}")
# pid power % duty cycle
self.label7 = QLabel()
self.label7.setAlignment(Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignRight)
- self.label7.setText('' + QApplication.translate('Label', 'PID %') + '')
+ self.label7.setText(f"{QApplication.translate('Label', 'PID %')}")
#extra LCDs
self.nLCDS: Final[int] = 10 # maximum number of LCDs and extra devices
@@ -4989,6 +4989,12 @@ def recentRoastsMenuList(self):
return [self.recentRoastLabel(rr) for rr in self.recentRoasts]
def establish_etypes(self):
+ # update ET/BT LCD label substitutions
+ self.label2.setText(f'{self.ETname}'.format(self.qmc.etypes[0],self.qmc.etypes[1],self.qmc.etypes[2],self.qmc.etypes[3]))
+ self.label3.setText(f'{self.BTname}'.format(self.qmc.etypes[0],self.qmc.etypes[1],self.qmc.etypes[2],self.qmc.etypes[3]))
+ # update ET/BT Delta LCD lable substitutions
+ self.label4.setText(f'{deltaLabelBigPrefix}{self.ETname}'.format(self.qmc.etypes[0],self.qmc.etypes[1],self.qmc.etypes[2],self.qmc.etypes[3]))
+ self.label5.setText(f'{deltaLabelBigPrefix}{self.BTname}'.format(self.qmc.etypes[0],self.qmc.etypes[1],self.qmc.etypes[2],self.qmc.etypes[3]))
# update extra LCD label substitutions
for i in range(len(self.qmc.extradevices)):
if i < len(self.qmc.extraname1):
@@ -16173,17 +16179,16 @@ def settingsLoad(self, filename=None, theme=False, machine=False, redraw=True):
self.qmc.eventsGraphflag = toInt(settings.value('eventsGraphflag',int(self.qmc.eventsGraphflag)))
if settings.contains('etypes'):
self.qmc.etypes = toStringList(settings.value('etypes',self.qmc.etypes))
+ # etype specified as empty strings are replaced by their defaults to enable translations in partially customized etypes
+ for i, name in enumerate(self.qmc.etypes):
+ if name == '':
+ self.qmc.etypes[i] = self.qmc.etypesdefault[i]
# update minieditor event type ComboBox
self.etypeComboBox.clear()
self.etypeComboBox.addItems(self.qmc.etypes)
else:
# etypes have not been saved in the setting to presever the translations, we have to reset those to their default
- self.qmc.etypes = [
- QApplication.translate('ComboBox', 'Air'),
- QApplication.translate('ComboBox', 'Drum'),
- QApplication.translate('ComboBox', 'Damper'),
- QApplication.translate('ComboBox', 'Burner')
- ]
+ self.qmc.etypes = self.qmc.etypesdefault
self.qmc.eventsshowflag = toInt(settings.value('eventsshowflag',int(self.qmc.eventsshowflag)))
self.qmc.clampEvents = bool(toBool(settings.value('clampEvents',self.qmc.clampEvents)))
self.qmc.renderEventsDescr = bool(toBool(settings.value('renderEventsDescr',self.qmc.renderEventsDescr)))
@@ -16773,14 +16778,14 @@ def settingsLoad(self, filename=None, theme=False, machine=False, redraw=True):
self.qmc.graphfont = toInt(settings.value('graphfont',self.qmc.graphfont))
if settings.contains('ETname'):
self.ETname = settings.value('ETname')
- self.label2.setText('' + self.ETname + '')
- self.label4.setText(deltaLabelBigPrefix + self.ETname + '')
+ self.label2.setText(f'{self.ETname}'.format(self.qmc.etypes[0],self.qmc.etypes[1],self.qmc.etypes[2],self.qmc.etypes[3]))
+ self.label4.setText(f'{deltaLabelBigPrefix}{self.ETname}'.format(self.qmc.etypes[0],self.qmc.etypes[1],self.qmc.etypes[2],self.qmc.etypes[3]))
else:
self.ETname = QApplication.translate('Label', 'ET')
if settings.contains('BTname'):
self.BTname = settings.value('BTname')
- self.label3.setText('' + self.BTname + '')
- self.label5.setText(deltaLabelBigPrefix + self.BTname + '')
+ self.label3.setText(f'{self.BTname}'.format(self.qmc.etypes[0],self.qmc.etypes[1],self.qmc.etypes[2],self.qmc.etypes[3]))
+ self.label5.setText(f'{deltaLabelBigPrefix}{self.BTname}'.format(self.qmc.etypes[0],self.qmc.etypes[1],self.qmc.etypes[2],self.qmc.etypes[3]))
else:
self.BTname = QApplication.translate('Label', 'BT')
settings.endGroup()
@@ -18026,7 +18031,12 @@ def saveAllSettings(self, settings:QSettings, default_settings:Optional[Dict[str
(self.qmc.etypes[1] != QApplication.translate('ComboBox', 'Drum')) or
(self.qmc.etypes[2] != QApplication.translate('ComboBox', 'Damper')) or
(self.qmc.etypes[3] != QApplication.translate('ComboBox', 'Burner'))):
- self.settingsSetValue(settings, default_settings, 'etypes',self.qmc.etypes, read_defaults)
+ etypes = self.qmc.etypes
+ if not read_defaults:
+ for i, _ in enumerate(self.qmc.etypes):
+ if self.qmc.etypes[i] == self.qmc.etypesdefault[i]:
+ etypes[i] = '' # we save empty strings for default event type names to ensure correct translation on re-loading those settings
+ self.settingsSetValue(settings, default_settings, 'etypes',etypes, read_defaults)
else:
settings.remove('etypes')
self.settingsSetValue(settings, default_settings, 'eventsshowflag',self.qmc.eventsshowflag, read_defaults)
diff --git a/src/includes/Machines/Buehler/RM_20_Legacy.aset b/src/includes/Machines/Buehler/RM_20_Legacy.aset
index b60857670..38e3f36fd 100644
--- a/src/includes/Machines/Buehler/RM_20_Legacy.aset
+++ b/src/includes/Machines/Buehler/RM_20_Legacy.aset
@@ -1,11 +1,17 @@
[General]
Delay=1000
Oversampling=false
-roastertype_setup=B\xfchler Roastmaster
+roastertype_setup=B\xfchler RM 20 Legacy
+
+[MachineSetup]
+capacity=20
[Device]
id=79
+[Style]
+ETname=IT
+
[ExtraComm]
extrabaudrate=19200, 19200
extrabytesize=8, 8
@@ -15,17 +21,17 @@ extrastopbits=1, 1
extratimeout=1, 1
[ExtraDev]
-extraCurveVisibility1=true, false, true, true, true, true, true, true, true, true
+extraCurveVisibility1=false, false, true, true, true, true, true, true, true, true
extraCurveVisibility2=true, false, true, true, true, true, true, true, true, true
extraLCDvisibility1=true, true, false, false, false, false, false, false, false, false
extraLCDvisibility2=true, true, false, false, false, false, false, false, false, false
-extradevicecolor1=black, black
-extradevicecolor2=black, black
+extradevicecolor1=#d27d1c, #49b260
+extradevicecolor2=#333333, #45a6cf
extradevices=80, 81
extramathexpression1=,
extramathexpression2=,
-extraname1=AT, Speed
-extraname2=Drum, Air
+extraname1=AT, {1}
+extraname2=Pa, {0}
[S7]
PID_OFF_action=
@@ -47,6 +53,19 @@ port=102
rack=0
slot=1
start=16, 12, 32, 20, 8, 24, 0, 0, 0, 0
-type=1, 1, 1, 1, 1, 1, 0, 0, 0, 0
+type=1, 1, 1, 1, 2, 2, 0, 0, 0, 0
optimizer=true
fetch_max_blocks=true
+
+[Sliders]
+eventsliderunits=%, %, ,
+
+[Quantifiers]
+clusterEventsFlag=false
+eventquantifierSV=0, 0, 0, 0
+eventquantifieraction=0, 0, 0, 0
+quantifieractive=1, 1, 0, 0
+quantifiercoarse=0, 0, 0, 0
+quantifiermax=100, 100, 100, 100
+quantifiermin=0, 0, 0, 0
+quantifiersource=5, 4, 0, 0
\ No newline at end of file
diff --git a/src/includes/Machines/Buehler/RM_20_Playone.aset b/src/includes/Machines/Buehler/RM_20_Playone.aset
new file mode 100644
index 000000000..25187c0ee
--- /dev/null
+++ b/src/includes/Machines/Buehler/RM_20_Playone.aset
@@ -0,0 +1,71 @@
+[General]
+Delay=1000
+Oversampling=false
+roastertype_setup=B\xfchler RM Playone
+
+[MachineSetup]
+capacity=20
+
+[Device]
+id=79
+
+[Style]
+ETname=IT
+
+[ExtraComm]
+extrabaudrate=19200, 19200
+extrabytesize=8, 8
+extracomport=COM1, COM1
+extraparity=E, E
+extrastopbits=1, 1
+extratimeout=1, 1
+
+[ExtraDev]
+extraCurveVisibility1=false, false, true, true, true, true, true, true, true, true
+extraCurveVisibility2=true, false, true, true, true, true, true, true, true, true
+extraLCDvisibility1=true, true, false, false, false, false, false, false, false, false
+extraLCDvisibility2=true, true, false, false, false, false, false, false, false, false
+extradevicecolor1=#d27d1c, #49b260
+extradevicecolor2=#333333, #45a6cf
+extradevices=80, 81
+extramathexpression1=,
+extramathexpression2=,
+extraname1=AT, {1}
+extraname2=Pa, {0}
+
+[S7]
+PID_OFF_action=
+PID_ON_action=
+PID_SV_register=0
+PID_area=0
+PID_d_register=0
+PID_db_nr=0
+PID_i_register=0
+PID_p_register=0
+PIDmultiplier=0
+SVmultiplier=0
+area=6, 6, 6, 6, 6, 6, 0, 0, 0, 0
+db_nr=1606, 1606, 1606, 1606, 1606, 1606, 1, 1, 1, 1
+div=0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+host=192.168.1.10
+mode=1, 1, 1, 0, 0, 0, 0, 0, 0, 0
+port=102
+rack=0
+slot=1
+start=240, 244, 252, 248,228, 232, 0, 0, 0, 0
+type=1, 1, 1, 1, 2, 2, 0, 0, 0, 0
+optimizer=true
+fetch_max_blocks=true
+
+[Sliders]
+eventsliderunits=%, %, ,
+
+[Quantifiers]
+clusterEventsFlag=false
+eventquantifierSV=0, 0, 0, 0
+eventquantifieraction=0, 0, 0, 0
+quantifieractive=1, 1, 0, 0
+quantifiercoarse=0, 0, 0, 0
+quantifiermax=100, 100, 100, 100
+quantifiermin=0, 0, 0, 0
+quantifiersource=5, 4, 0, 0
\ No newline at end of file
diff --git a/src/includes/Machines/Buehler/RM_60-240.aset b/src/includes/Machines/Buehler/RM_60-240.aset
new file mode 100644
index 000000000..8b420f9d4
--- /dev/null
+++ b/src/includes/Machines/Buehler/RM_60-240.aset
@@ -0,0 +1,71 @@
+[General]
+Delay=1000
+Oversampling=false
+roastertype_setup=B\xfchler RM 60-240 OC
+
+[Device]
+id=79
+
+[Style]
+ETname=IT
+
+[ExtraComm]
+extrabaudrate=19200, 19200, 19200
+extrabytesize=8, 8, 8
+extracomport=COM1, COM1, COM1
+extraparity=E, E, E
+extrastopbits=1, 1, 1
+extratimeout=0.3, 0.3, 0.3
+
+[ExtraDev]
+extraCurveVisibility1=false, false, false, true, true, true, true, true, true, true
+extraCurveVisibility2=true, false, false, true, true, true, true, true, true, true
+extraLCDvisibility1=true, true, true, false, false, false, false, false, false, false
+extraLCDvisibility2=true, true, true, false, false, false, false, false, false, false
+extradevicecolor1=#d27d1c, #49b260, #333333
+extradevicecolor2=#333333, #45a6cf, #810081
+extradevices=80, 81, 82
+extramathexpression1=, ,
+extramathexpression2=, ,
+extraname1=XT, {1}, TT
+extraname2=Pa, {0}, RC
+
+[S7]
+PID_OFF_action=
+PID_ON_action=
+PID_SV_register=0
+PID_area=0
+PID_d_register=0
+PID_db_nr=0
+PID_i_register=0
+PID_p_register=0
+PIDmultiplier=0
+SVmultiplier=0
+area=6, 6, 6, 6, 6, 6, 6, 6, 0, 0
+db_nr=84, 84, 84, 84, 84, 84, 1652, 84, 1, 1
+div=0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+host=192.168.1.10
+mode=1, 1, 1, 0, 0, 0, 1, 1, 0, 0
+port=102
+rack=0
+slot=1
+start=8, 4, 12, 44, 0, 20, 40, 36, 0, 0
+type=1, 1, 1, 1, 2, 2, 1, 2, 0, 0
+optimizer=true
+fetch_max_blocks=true
+
+[events]
+etypes=, , RC, ,
+
+[Sliders]
+eventsliderunits=%, %, ,
+
+[Quantifiers]
+clusterEventsFlag=false
+eventquantifierSV=0, 0, 0, 0
+eventquantifieraction=0, 0, 0, 0
+quantifieractive=1, 1, 1, 0
+quantifiercoarse=0, 0, 0, 0
+quantifiermax=100, 100, 100, 100
+quantifiermin=0, 0, 0, 0
+quantifiersource=5, 4, 7, 0
\ No newline at end of file
diff --git a/src/requirements-dev.txt b/src/requirements-dev.txt
index 417e4b163..707fdfaa3 100644
--- a/src/requirements-dev.txt
+++ b/src/requirements-dev.txt
@@ -4,13 +4,13 @@ types-psutil==5.9.5.16
types-pyserial==3.5.0.10
types-python-dateutil==2.8.19.14
types-PyYAML==6.0.12.12
-types-requests==2.31.0.7
+types-requests==2.31.0.8
types-setuptools==68.2.0.0
types-urllib3==1.26.25.14
mypy==1.5.1
pyright==1.1.329
ruff>=0.0.285
-pylint==3.0.0
+pylint==3.0.1
pre-commit>=3.3.3
pytest==7.4.2
pytest-cov==4.1.0
@@ -21,6 +21,6 @@ pytest-qt==4.2.0
#pytest-bdd==6.1.1
#pytest-benchmark==4.0.0
#pytest-mock==3.11.1
-hypothesis==6.87.0
+hypothesis==6.87.2
coverage==7.3.2
coverage-badge==1.1.0
diff --git a/src/requirements.txt b/src/requirements.txt
index a5932ed24..e1929bd9f 100644
--- a/src/requirements.txt
+++ b/src/requirements.txt
@@ -61,7 +61,7 @@ lxml==4.9.3
matplotlib==3.7.3; python_version < '3.9' # last Python 3.8 release
matplotlib==3.8.0; python_version >= '3.9'
jinja2==3.1.2
-aiohttp==3.8.5
+aiohttp==3.8.6
aiohttp_jinja2==1.5.1
#
#