Skip to content

Commit 8264e80

Browse files
committed
Fix a billion type checking issues
1 parent 9d4829d commit 8264e80

31 files changed

+151
-125
lines changed

codegen/lco/generator.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@
33
import json
44
import sys
55
from pathlib import Path
6+
from typing import Any
67

78
import textcase
89
from jinja2 import Environment, FileSystemLoader
910

1011
VALID_FACILITIES = ["SOAR", "LCO", "SAAO", "BLANCO"]
1112

1213

13-
def get_modes(ins: dict, type: str) -> list[str]:
14+
def get_modes(ins: dict[str, Any], type: str) -> list[str]:
1415
try:
1516
return [m["code"] for m in ins["modes"][type]["modes"]]
1617
except Exception:
@@ -38,7 +39,7 @@ def generate_instrument_configs(ins_s: str, facility: str) -> str:
3839
)
3940
template = j_env.get_template("instruments.jinja")
4041
ins_data = json.loads(ins_s)
41-
instruments = []
42+
instruments: list[dict[str, Any]] = []
4243
if facility == "SOAR":
4344
# Soar instruments look like SoarGhtsBluecam, already prefixed, so no need to add a prefix.
4445
prefix = ""
@@ -95,7 +96,9 @@ def generate_instrument_configs(ins_s: str, facility: str) -> str:
9596
# Accepts input from stdin or a file argument
9697
with fileinput.input() as f:
9798
ins_json = "".join(list(f))
98-
sys.stdout.write(generate_instrument_configs(ins_json, facility=facility))
99+
_ = sys.stdout.write(
100+
generate_instrument_configs(ins_json, facility=facility)
101+
)
99102
except IndexError:
100-
sys.stdout.write("Usage: python generator.py <facility>")
103+
_ = sys.stdout.write("Usage: python generator.py <facility>")
101104
exit(1)

codegen/lco/templates/instruments.jinja

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
# pyright: reportUnannotatedClassAttribute=false
12
# This file is generated automatically and should not be edited by hand.
23

3-
from typing import Any, Annotated, Literal, Union
4+
from typing import Any, Annotated, Literal
45

56
from annotated_types import Le
67
from pydantic import BaseModel, ConfigDict
@@ -72,8 +73,4 @@ class {{ ctx.class_name }}(BaseModel):
7273

7374
{% endfor %}
7475
# Export a type that encompasses all instruments
75-
{{ facility }}_INSTRUMENTS = Union[
76-
{% for ctx in instruments %}
77-
{{ ctx.class_name }},
78-
{% endfor %}
79-
]
76+
{{ facility }}_INSTRUMENTS = {% for ctx in instruments %}{{ ctx.class_name }}{% if not loop.last%} | {% endif %}{% endfor %}

pyproject.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,8 @@ exclude = [
4949
"*.ipynb",
5050
"src/aeonlib/ocs/*/instruments.py",
5151
]
52+
53+
[tool.pyright]
54+
reportExplicitAny = false
55+
reportAny = false
56+
reportMissingTypeStubs = false

src/aeonlib/conf.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
from typing import ClassVar
2+
13
from pydantic_settings import BaseSettings, SettingsConfigDict
24

35

46
class Settings(BaseSettings):
5-
model_config = SettingsConfigDict(env_prefix="AEON_", env_file=".env")
7+
model_config: ClassVar[SettingsConfigDict] = SettingsConfigDict(
8+
env_prefix="AEON_", env_file=".env"
9+
)
610

711
# Las Cumbres Observatory
812
lco_token: str = ""

src/aeonlib/eso/__init__.py

Whitespace-only changes.

src/aeonlib/eso/facility.py

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
# pyright: reportUnknownMemberType=false
2+
# pyright: reportUnannotatedClassAttribute=false
13
import logging
24
import tempfile
3-
from typing import BinaryIO
5+
from typing import Any, BinaryIO
46

7+
from aeonlib.conf import Settings
58
from aeonlib.conf import settings as default_settings
69
from aeonlib.exceptions import ServiceNetworkError
710

@@ -28,7 +31,7 @@ class ESONetworkError(ServiceNetworkError):
2831

2932

3033
class EsoFacility:
31-
def __init__(self, settings=default_settings):
34+
def __init__(self, settings: Settings = default_settings):
3235
self.api = p2api.ApiConnection(
3336
settings.eso_environment,
3437
settings.eso_username,
@@ -58,7 +61,7 @@ def get_container(self, container_id: int) -> Container:
5861

5962
def delete_container(self, container: Container) -> None:
6063
try:
61-
self.api.deleteContainer(container.container_id, container.version)
64+
_ = self.api.deleteContainer(container.container_id, container.version)
6265
except Exception as e:
6366
raise ESONetworkError("Failed to delete ESO container") from e
6467

@@ -96,7 +99,7 @@ def save_ob(self, ob: ObservationBlock) -> ObservationBlock:
9699

97100
def delete_ob(self, ob: ObservationBlock) -> None:
98101
try:
99-
self.api.deleteOB(ob.ob_id, ob.version)
102+
_ = self.api.deleteOB(ob.ob_id, ob.version)
100103
except Exception as e:
101104
raise ESONetworkError("Failed to delete ESO observation block") from e
102105

@@ -112,7 +115,9 @@ def create_template(self, ob: ObservationBlock, name: str) -> Template:
112115

113116
def delete_template(self, ob: ObservationBlock, template: Template) -> None:
114117
try:
115-
self.api.deleteTemplate(ob.ob_id, template.template_id, template.version)
118+
_ = self.api.deleteTemplate(
119+
ob.ob_id, template.template_id, template.version
120+
)
116121
except Exception as e:
117122
raise ESONetworkError("Failed to delete ESO template") from e
118123

@@ -127,7 +132,7 @@ def get_template(self, ob: ObservationBlock, template_id: str) -> Template:
127132
return Template.model_validate({**template_dict, "version": version})
128133

129134
def update_template_params(
130-
self, ob: ObservationBlock, template: Template, params: dict
135+
self, ob: ObservationBlock, template: Template, params: dict[Any, Any]
131136
) -> Template:
132137
"""
133138
This method simply updates the parameter dictionary in the template object and saves it.
@@ -252,11 +257,11 @@ def save_ephemeris(self, ob: ObservationBlock, ephemeris: Ephemeris):
252257
# This is a new ephemeris file so we need to request a version
253258
ephemeris.version = self.get_ephemeris(ob).version
254259
with tempfile.NamedTemporaryFile() as temp_file:
255-
temp_file.write(ephemeris.text.encode())
260+
_ = temp_file.write(ephemeris.text.encode())
256261
temp_file.flush()
257262
logger.debug("Saved ephemeris file to %s", temp_file.name)
258263
try:
259-
_, version = self.api.saveEphemerisFile(
264+
_, version = self.api.saveEphemerisFile( # pyright: ignore[reportUnknownVariableType]
260265
ob.ob_id, temp_file.name, ephemeris.version
261266
)
262267
assert version
@@ -276,17 +281,19 @@ def delete_ephemeris(self, ob: ObservationBlock, ephemeris: Ephemeris) -> None:
276281
raise ESONetworkError("Failed to delete ESO ephemeris file") from e
277282
logger.debug("<- %s", version)
278283

279-
def add_finding_chart(self, ob: ObservationBlock, chart: BinaryIO, name="") -> None:
284+
def add_finding_chart(
285+
self, ob: ObservationBlock, chart: BinaryIO, name: str = ""
286+
) -> None:
280287
"""Add a finding chart and return a list of all charts"""
281288
prefix = "aeon_fc"
282289
if name:
283290
prefix += f"_{name}_"
284291
with tempfile.NamedTemporaryFile(delete=False, prefix=prefix) as temp_file:
285-
temp_file.write(chart.read())
292+
_ = temp_file.write(chart.read())
286293
temp_file.flush()
287294
logger.debug("Saved finding chart to %s", temp_file.name)
288295
try:
289-
self.api.addFindingChart(ob.ob_id, temp_file.name)
296+
_ = self.api.addFindingChart(ob.ob_id, temp_file.name) # pyright: ignore[reportUnknownVariableType]
290297
except Exception as e:
291298
raise ESONetworkError("Failed to add ESO finding chart") from e
292299

@@ -304,7 +311,7 @@ def get_finding_chart_names(self, ob: ObservationBlock) -> list[str]:
304311
def delete_finding_chart(self, ob: ObservationBlock, index: int) -> None:
305312
"""Delete a finding chart from the ESO api."""
306313
try:
307-
self.api.deleteFindingChart(ob.ob_id, index)
314+
_ = self.api.deleteFindingChart(ob.ob_id, index)
308315
except Exception as e:
309316
raise ESONetworkError("Failed to delete ESO finding chart") from e
310317

src/aeonlib/eso/models.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from datetime import datetime, time
2-
from typing import Any, Self
2+
from typing import Any, ClassVar, Self
33

44
from astropy.coordinates import Angle
55
from pydantic import BaseModel, ConfigDict, Field
@@ -9,7 +9,7 @@
99

1010

1111
class EsoModel(BaseModel):
12-
model_config = ConfigDict(
12+
model_config: ClassVar[ConfigDict] = ConfigDict(
1313
alias_generator=to_camel, validate_by_name=True, serialize_by_alias=True
1414
)
1515

@@ -49,8 +49,8 @@ def construct_from(self, st: SiderealTarget) -> None:
4949
# Format angles the way ESO wants them.
5050
assert isinstance(st.ra, Angle)
5151
assert isinstance(st.dec, Angle)
52-
self.ra = st.ra.to_string(sep=":", precision=3)
53-
self.dec = st.dec.to_string(sep=":", precision=3)
52+
self.ra = st.ra.to_string(sep=":", precision=3) # pyright: ignore[reportUnknownMemberType]
53+
self.dec = st.dec.to_string(sep=":", precision=3) # pyright: ignore[reportUnknownMemberType]
5454
self.epoch = st.epoch
5555
self.name = st.name
5656
self.proper_motion_dec = st.proper_motion_dec

src/aeonlib/lt/__init__.py

Whitespace-only changes.

src/aeonlib/lt/facility.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# pyright: reportPrivateUsage=false
12
import time
23
from logging import getLogger
34

@@ -31,7 +32,7 @@ def __init__(self):
3132
url = "{0}://{1}:{2}/node_agent2/node_agent?wsdl".format(
3233
"http", settings.lt_host, settings.lt_port
3334
)
34-
self.client = Client(url, headers=headers)
35+
self.client: Client = Client(url, headers=headers)
3536

3637
def submit_observation(
3738
self, cfg: LTConfig, ins: LT_INSTRUMENTS, target: SiderealTarget, window: Window
@@ -118,7 +119,7 @@ def _build_project(self, project_id: str) -> etree._Element:
118119
contact = etree.SubElement(project, "Contact")
119120
etree.SubElement(contact, "Username").text = settings.lt_username
120121
etree.SubElement(contact, "Name").text = ""
121-
etree.SubElement(contact, "Communication")
122+
_ = etree.SubElement(contact, "Communication")
122123

123124
return project
124125

@@ -167,9 +168,9 @@ def _build_constraints(
167168
etree.SubElement(photom_const, "Clouds").text = lt_observation.photometric
168169
date_const = etree.Element("DateTimeConstraint", type="include")
169170
assert window.start
170-
start = window.start.strftime("%Y-%m-%dT%H:%M:00+00:00")
171-
end = window.end.strftime("%Y-%m-%dT%H:%M:00+00:00")
172-
etree.SubElement(date_const, "DateTimeStart", system="UT", value=str(start))
173-
etree.SubElement(date_const, "DateTimeEnd", system="UT", value=str(end))
171+
start = window.start.strftime("%Y-%m-%dT%H:%M:00+00:00") # pyright: ignore[reportUnknownVariableType, reportUnknownMemberType]
172+
end = window.end.strftime("%Y-%m-%dT%H:%M:00+00:00") # pyright: ignore[reportUnknownVariableType, reportUnknownMemberType]
173+
_ = etree.SubElement(date_const, "DateTimeStart", system="UT", value=str(start)) # pyright: ignore[reportUnknownArgumentType]
174+
_ = etree.SubElement(date_const, "DateTimeEnd", system="UT", value=str(end)) # pyright: ignore[reportUnknownArgumentType]
174175

175176
return [airmass_const, sky_const, seeing_const, photom_const, date_const]

src/aeonlib/lt/models.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from typing import Annotated, Literal, Tuple, Union
1+
# pyright: reportPrivateUsage=false
2+
from typing import Annotated, Literal
23

34
from annotated_types import Ge, Le
45
from lxml import etree
@@ -16,7 +17,7 @@ class LTConfig(BaseModel):
1617
photometric: Literal["clear", "light"] = "clear"
1718

1819

19-
IooFilterTimeCnt = Tuple[Annotated[float, Ge(0.0)], Annotated[int, Ge(1)]]
20+
IooFilterTimeCnt = tuple[Annotated[float, Ge(0.0)], Annotated[int, Ge(1)]]
2021
"""Tuple of exposure time, exposure count"""
2122

2223

@@ -45,7 +46,7 @@ def build_schedule(self, filter: str, cfg: IooFilterTimeCnt) -> etree._Element:
4546
device = etree.SubElement(schedule, "Device", name="IO:O", type="camera")
4647
etree.SubElement(device, "SpectralRegion").text = "optical"
4748
setup = etree.SubElement(device, "Setup")
48-
etree.SubElement(setup, "Filter", type=filter)
49+
_ = etree.SubElement(setup, "Filter", type=filter)
4950
detector = etree.SubElement(setup, "Detector")
5051
binning = etree.SubElement(detector, "Binning")
5152
etree.SubElement(binning, "X", units="pixels").text = self.binning.split("x")[0]
@@ -66,7 +67,7 @@ def build_inst_schedule(self) -> list[etree._Element]:
6667
device = etree.SubElement(schedule, "Device", name="Sprat", type="spectrograph")
6768
etree.SubElement(device, "SpectralRegion").text = "optical"
6869
setup = etree.SubElement(device, "Setup")
69-
etree.SubElement(setup, "Grating", name=self.grating)
70+
_ = etree.SubElement(setup, "Grating", name=self.grating)
7071
detector = etree.SubElement(setup, "Detector")
7172
binning = etree.SubElement(detector, "Binning")
7273
etree.SubElement(binning, "X", units="pixels").text = "1"
@@ -104,15 +105,11 @@ def build_schedule(
104105
)
105106
etree.SubElement(device, "SpectralRegion").text = "optical"
106107
setup = etree.SubElement(device, "Setup")
107-
etree.SubElement(setup, "Grating", name=grating)
108+
_ = etree.SubElement(setup, "Grating", name=grating)
108109
exposure = etree.SubElement(schedule, "Exposure", count=str(exp_count))
109110
etree.SubElement(exposure, "Value", units="seconds").text = str(exp_time)
110111

111112
return schedule
112113

113114

114-
LT_INSTRUMENTS = Union[
115-
Ioo,
116-
Frodo,
117-
Sprat,
118-
]
115+
LT_INSTRUMENTS = Ioo | Frodo | Sprat

0 commit comments

Comments
 (0)