Skip to content

Commit cd9f9e7

Browse files
lots of typing fixes
1 parent 1a8a70a commit cd9f9e7

24 files changed

+109
-64
lines changed

core/pioreactor/actions/leader/backup_database.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def _local_available_space(path: str) -> int:
5050

5151
def count_writes_occurring() -> int:
5252
with local_intermittent_storage("mqtt_to_db_streaming") as c:
53-
return c.get("inserts_in_last_60s", 0)
53+
return int(c.get("inserts_in_last_60s", 0)) # type: ignore[call-overload]
5454

5555

5656
def backup_database(output_file: str, force: bool = False, backup_to_workers: int = 0) -> None:

core/pioreactor/actions/led_intensity.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def change_leds_intensities_temporarily(
4444
old_state = {}
4545
try:
4646
with local_intermittent_storage("leds") as cache:
47-
old_state = {c: float(cache.get(c, 0.0)) for c in desired_state.keys()}
47+
old_state = {c: float(cache.get(c, 0.0)) for c in desired_state.keys()} # type: ignore[arg-type]
4848
if not led_intensity(desired_state, **kwargs):
4949
raise ValueError("Unable to update LED.")
5050

@@ -86,15 +86,17 @@ def _update_current_state(
8686
with local_intermittent_storage("leds") as led_cache:
8787
# rehydrate old cache
8888
old_state: LEDsToIntensityMapping = {
89-
channel: led_cache.get(str(channel), 0.0) for channel in ALL_LED_CHANNELS
89+
channel: float(led_cache.get(str(channel), 0.0)) # type: ignore[arg-type]
90+
for channel in ALL_LED_CHANNELS
9091
}
9192

9293
# update cache
9394
for channel, intensity in state.items():
9495
led_cache[channel] = intensity
9596

9697
new_state: LEDsToIntensityMapping = {
97-
channel: led_cache.get(str(channel), 0.0) for channel in ALL_LED_CHANNELS
98+
channel: float(led_cache.get(str(channel), 0.0)) # type: ignore[arg-type]
99+
for channel in ALL_LED_CHANNELS
98100
}
99101

100102
return new_state, old_state

core/pioreactor/actions/od_blank.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from json import dumps
55
from json import loads
66
from typing import Any
7+
from typing import cast
78
from typing import Iterator
89
from typing import Optional
910

@@ -113,7 +114,7 @@ def delete_od_blank(unit: pt.Unit | None = None, experiment: pt.Experiment | Non
113114
retain=True,
114115
)
115116

116-
means = loads(cache[experiment])
117+
means = loads(cast(str | bytes | bytearray, cache[experiment]))
117118
for channel, mean in means.items():
118119
pubsub.publish(
119120
f"pioreactor/{unit}/{experiment}/{action_name}/mean/{channel}",

core/pioreactor/actions/self_test.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,9 @@ def test_REF_is_in_correct_position(
132132
reference_channel = cast(PdChannel, next((k for k, v in pd_channels.items() if v == REF_keyword), None))
133133
assert reference_channel is not None, "REF required for this self-test"
134134

135-
signal_channels = [channel for channel, angle in pd_channels.items() if angle != REF_keyword]
135+
signal_channels: list[PdChannel] = [
136+
cast(PdChannel, channel) for channel, angle in pd_channels.items() if angle != REF_keyword
137+
]
136138

137139
test_channels = {str(channel): "90" for channel, angle in pd_channels.items()}
138140

@@ -467,6 +469,7 @@ def test_PD_is_near_0_volts_for_blank(
467469
signal_pd_channels = {k: v for k, v in pd_channels.items() if v != REF_keyword}
468470

469471
for channel, angle in signal_pd_channels.items():
472+
channel = cast(PdChannel, channel)
470473
assert angle in ["90", "45", "135"], f"Angle {angle} not valid for this test."
471474

472475
signals = []

core/pioreactor/automations/base.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ def latest_growth_rate(self) -> float:
148148
"readings are too stale (over 5 minutes old) - are `od_reading` and `growth_rate_calculating` running?"
149149
)
150150

151-
return cast(float, self._latest_growth_rate)
151+
return self._latest_growth_rate
152152

153153
@property
154154
def latest_normalized_od(self) -> float:
@@ -169,7 +169,7 @@ def latest_normalized_od(self) -> float:
169169
"readings are too stale (over 5 minutes old) - are `od_reading` and `growth_rate_calculating` running?"
170170
)
171171

172-
return cast(float, self._latest_normalized_od)
172+
return self._latest_normalized_od
173173

174174
@property
175175
def latest_od(self) -> dict[pt.PdChannel, float]:
@@ -211,7 +211,7 @@ def latest_od_fused(self) -> float:
211211
f"fused readings are too stale (over 5 minutes old) - is `od_reading` running?. Last reading occurred at {self.latest_od_fused_at}."
212212
)
213213

214-
return cast(float, self._latest_od_fused)
214+
return self._latest_od_fused
215215

216216
def latest_biomass_value(
217217
self,

core/pioreactor/background_jobs/base.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from os import getpid
99
from time import sleep
1010
from time import time
11+
from types import FunctionType
1112
from typing import Self
1213

1314
from msgspec.json import decode as loads
@@ -271,7 +272,7 @@ def wrapped_init(self: t.Any, *args: t.Any, **kwargs: t.Any) -> None:
271272
pass
272273
raise
273274

274-
cls.__init__ = wrapped_init
275+
setattr(cls, "__init__", t.cast(FunctionType, wrapped_init))
275276

276277
def __init__(self, unit: pt.Unit, experiment: pt.Experiment, source: str = "app") -> None:
277278
if self.job_name in DISALLOWED_JOB_NAMES:
@@ -368,6 +369,10 @@ def __post__init__(self) -> None:
368369
def job_key(self) -> str:
369370
return f"{self.job_name}/{self.job_id}"
370371

372+
@staticmethod
373+
def _ignore_future_sighups(*args: t.Any) -> None:
374+
signal.signal(signal.SIGHUP, signal.SIG_IGN)
375+
371376
def start_passive_listeners(self) -> None:
372377
# overwrite this to in subclasses to subscribe to topics in MQTT
373378
# using this handles reconnects correctly.
@@ -738,7 +743,7 @@ def exit_gracefully(reason: int | str, *args: object) -> None:
738743
[
739744
exit_gracefully,
740745
# add a "ignore all future SIGUPs" onto the top of the stack.
741-
lambda *args: signal.signal(signal.SIGHUP, signal.SIG_IGN),
746+
self._ignore_future_sighups,
742747
],
743748
)
744749
except AttributeError:

core/pioreactor/background_jobs/dosing_automation.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -557,10 +557,10 @@ def _init_volume_throughput(self) -> None:
557557
)
558558

559559
with local_persistent_storage("alt_media_throughput") as cache:
560-
self.alt_media_throughput = cache.get(self.experiment, 0.0)
560+
self.alt_media_throughput = float(cache.get(self.experiment, 0.0)) # type: ignore[arg-type]
561561

562562
with local_persistent_storage("media_throughput") as cache:
563-
self.media_throughput = cache.get(self.experiment, 0.0)
563+
self.media_throughput = float(cache.get(self.experiment, 0.0)) # type: ignore[arg-type]
564564

565565
return
566566

core/pioreactor/background_jobs/growth_rate_calculating.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -321,31 +321,31 @@ def _get_od_blank_from_cache(self) -> dict[pt.PdChannel, float]:
321321
result = cache.get(self.experiment)
322322

323323
if result is not None:
324-
od_blanks = result
324+
od_blanks = cast(bytes | str, result)
325325
return loads(od_blanks)
326326
else:
327327
return defaultdict(lambda: 0.0)
328328

329329
def _get_growth_rate_from_cache(self) -> float:
330330
with local_persistent_storage("growth_rate") as cache:
331-
return cache.get(self.experiment, 0.0)
331+
return float(cast(float | int, cache.get(self.experiment, 0.0)))
332332

333333
def _get_filtered_od_from_cache(self) -> float:
334334
with local_persistent_storage("od_filtered") as cache:
335-
return cache.get(self.experiment, 1.0)
335+
return float(cast(float | int, cache.get(self.experiment, 1.0)))
336336

337337
def _get_filtered_od_from_iterator(self, od_iter: Iterator[structs.ODReadings]) -> float:
338338
scaled_od_readings = self.scale_raw_observations(next(od_iter))
339339
return mean(scaled_od_readings[channel] for channel in scaled_od_readings.keys())
340340

341341
def _get_od_normalization_from_cache(self) -> dict[pt.PdChannel, float]:
342342
with local_persistent_storage("od_normalization_mean") as cache:
343-
result = cache[self.experiment]
343+
result = cast(bytes | str, cache[self.experiment])
344344
return loads(result)
345345

346346
def _get_od_variances_from_cache(self) -> dict[pt.PdChannel, float]:
347347
with local_persistent_storage("od_normalization_variance") as cache:
348-
result = cache[self.experiment]
348+
result = cast(bytes | str, cache[self.experiment])
349349
return loads(result)
350350

351351
@staticmethod
@@ -402,7 +402,9 @@ def _update_state_from_observation(
402402
updated_state_, covariance_ = self.ekf.update(
403403
list(scaled_observations.values()), dt, self._recent_dilution
404404
)
405-
latest_od_filtered, latest_growth_rate = float(updated_state_[0]), float(updated_state_[1])
405+
updated_state = cast(Any, updated_state_)
406+
covariance = cast(Any, covariance_)
407+
latest_od_filtered, latest_growth_rate = float(updated_state[0]), float(updated_state[1])
406408

407409
if self._obs_since_last_dose is not None and self._obs_required_to_reset is not None:
408410
self._obs_since_last_dose += 1
@@ -422,8 +424,8 @@ def _update_state_from_observation(
422424
)
423425

424426
kf_outputs = structs.KalmanFilterOutput(
425-
state=self.ekf.state_.tolist(),
426-
covariance_matrix=covariance_.tolist(),
427+
state=cast(Any, self.ekf.state_).tolist(),
428+
covariance_matrix=covariance.tolist(),
427429
timestamp=timestamp,
428430
)
429431

@@ -539,6 +541,7 @@ def click_growth_rate_calculating(ctx: click.Context, ignore_cache: bool) -> Non
539541
experiment = whoami.get_assigned_experiment_name(unit)
540542

541543
use_fused_od = _should_use_fused_od(unit)
544+
od_stream: MqttODSource | MqttODFusedSource
542545
if use_fused_od:
543546
od_stream = MqttODFusedSource(unit=unit, experiment=experiment, skip_first=5)
544547
else:

core/pioreactor/background_jobs/leader/mqtt_to_db_streaming.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ def callback(message: pt.MQTTMessage) -> None:
140140
values_placeholder = ", ".join(":" + c for c in new_row.keys())
141141
SQL = f"""INSERT INTO {table} ({cols_placeholder}) VALUES ({values_placeholder})"""
142142
try:
143-
self.sqliteworker.execute(SQL, new_row)
143+
self.sqliteworker.execute(SQL, cast(object, new_row)) # type: ignore[arg-type]
144144
except Exception as e:
145145
self.logger.warning(e)
146146
self.logger.debug(f"SQL that caused error: `{SQL}`")

core/pioreactor/background_jobs/monitor.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from threading import Thread
66
from time import sleep
77
from typing import Callable
8+
from typing import cast
89
from typing import Optional
910

1011
import click
@@ -47,8 +48,10 @@
4748

4849

4950
class classproperty(property):
50-
def __get__(self, obj: object, objtype: type[object] | None = None) -> object:
51-
return self.fget(objtype)
51+
def __get__(self, obj: object | None, objtype: type[object] | None = None) -> object: # type: ignore[override]
52+
assert self.fget is not None
53+
owner = objtype if objtype is not None else type(obj)
54+
return self.fget(owner)
5255

5356

5457
class Monitor(LongRunningBackgroundJob):
@@ -119,7 +122,7 @@ def pretty_version(info: tuple | None) -> str:
119122

120123
# previously I had pioreactor_version and model name here, but this starts before the webserver is online, and it
121124
# would crash this job.
122-
self.versions = {
125+
self.versions: dict[str, str | None] = {
123126
"app": pretty_version(version.software_version_info),
124127
"hat": pretty_version(version.hardware_version_info),
125128
"firmware": pretty_version(version.get_firmware_version()),
@@ -373,7 +376,7 @@ def check_heater_pcb_temperature(self) -> None:
373376

374377
observed_tmp = tmp_driver.get_temperature()
375378

376-
if observed_tmp >= self.MAX_TEMP_TO_SHUTDOWN:
379+
if observed_tmp >= cast(float, self.MAX_TEMP_TO_SHUTDOWN):
377380
# something is wrong - temperature_automation should have detected this, but didn't, so it must have failed / incorrectly cleaned up.
378381
# we're going to just shutdown to be safe.
379382
self.logger.error(
@@ -382,9 +385,9 @@ def check_heater_pcb_temperature(self) -> None:
382385

383386
subprocess.call("sudo shutdown now --poweroff", shell=True)
384387

385-
elif observed_tmp >= self.MAX_TEMP_TO_SHUTDOWN_IF_NO_TEMP_AUTOMATION and not utils.is_pio_job_running(
386-
"temperature_automation"
387-
):
388+
elif observed_tmp >= cast(
389+
float, self.MAX_TEMP_TO_SHUTDOWN_IF_NO_TEMP_AUTOMATION
390+
) and not utils.is_pio_job_running("temperature_automation"):
388391
# errant PWM?
389392
# false positive: small chance this is in an incubator?
390393

@@ -431,7 +434,7 @@ def check_for_mqtt_connection_to_leader(self) -> None:
431434
def check_for_last_backup(self) -> None:
432435
with utils.local_persistent_storage("database_backups") as cache:
433436
if cache.get("latest_backup_timestamp"):
434-
latest_backup_at = to_datetime(cache["latest_backup_timestamp"])
437+
latest_backup_at = to_datetime(cast(str, cache["latest_backup_timestamp"]))
435438

436439
if (current_utc_datetime() - latest_backup_at).days > 30:
437440
self.logger.warning(

0 commit comments

Comments
 (0)