Skip to content

Commit

Permalink
619 move to pyright (#632)
Browse files Browse the repository at this point in the history
  • Loading branch information
stan-dot authored Nov 21, 2024
1 parent a4e881d commit 86c5905
Show file tree
Hide file tree
Showing 25 changed files with 102 additions and 92 deletions.
2 changes: 1 addition & 1 deletion .copier-answers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ github_org: DiamondLightSource
package_name: blueapi
pypi: true
repo_name: blueapi
type_checker: mypy
type_checker: pyright
1 change: 1 addition & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"redhat.vscode-yaml",
"ryanluker.vscode-coverage-gutters",
"charliermarsh.ruff",
"ms-pyright.pyright",
"ms-azuretools.vscode-docker"
]
}
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ nosetests.xml
coverage.xml
cov.xml
.pytest_cache/
.mypy_cache/

# Translations
*.mo
Expand Down
16 changes: 7 additions & 9 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ dependencies = [
"event-model==1.22.1", # https://github.com/DiamondLightSource/blueapi/issues/684
"opentelemetry-distro>=0.48b0",
"opentelemetry-instrumentation-fastapi>=0.48b0",
"observability-utils>=0.1.4"
"observability-utils>=0.1.4",
]
dynamic = ["version"]
license.file = "LICENSE"
Expand All @@ -49,8 +49,8 @@ dev = [
"pipdeptree",
"pre-commit>=3.8.0",
"pydata-sphinx-theme>=0.15.4",
"mypy",
"pytest",
"pyright",
"pytest-cov",
"pytest-asyncio",
"responses",
Expand Down Expand Up @@ -82,11 +82,9 @@ name = "Callum Forrester"
[tool.setuptools_scm]
version_file = "src/blueapi/_version.py"

[tool.mypy]
ignore_missing_imports = true # Ignore missing stubs in imported modules

# necessary for tracing sdk to work with mypy, set false once migraion to pyright complete
namespace_packages = true
[tool.pyright]
typeCheckingMode = "standard"
reportMissingImports = false # Ignore missing stubs in imported modules

[tool.pytest.ini_options]
# Run pytest with all our checkers, and don't spam us with massive tracebacks on error
Expand Down Expand Up @@ -122,12 +120,12 @@ passenv = *
allowlist_externals =
pytest
pre-commit
mypy
pyright
sphinx-build
sphinx-autobuild
commands =
pre-commit: pre-commit run --all-files --show-diff-on-failure {posargs}
type-checking: mypy src tests {posargs}
type-checking: pyright src tests {posargs}
tests: pytest --cov=blueapi --cov-report term --cov-report xml:cov.xml tests/unit_tests {posargs}
docs: sphinx-{posargs:build -EW --keep-going} -T docs build/html
system-test: pytest tests/system_tests {posargs}
Expand Down
19 changes: 8 additions & 11 deletions src/blueapi/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,19 +163,16 @@ def get_devices(obj: dict) -> None:
def listen_to_events(obj: dict) -> None:
"""Listen to events output by blueapi"""
config: ApplicationConfig = obj["config"]
if config.stomp is not None:
event_bus_client = EventBusClient(
StompClient.for_broker(
broker=Broker(
host=config.stomp.host,
port=config.stomp.port,
auth=config.stomp.auth,
)
assert config.stomp is not None, "Message bus needs to be configured"
event_bus_client = EventBusClient(
StompClient.for_broker(
broker=Broker(
host=config.stomp.host,
port=config.stomp.port,
auth=config.stomp.auth,
)
)
else:
raise RuntimeError("Message bus needs to be configured")

)
fmt = obj["fmt"]

def on_event(
Expand Down
19 changes: 9 additions & 10 deletions src/blueapi/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,16 @@ def __init__(
@classmethod
def from_config(cls, config: ApplicationConfig) -> "BlueapiClient":
rest = BlueapiRestClient(config.api)
if config.stomp is not None:
stomp_client = StompClient.for_broker(
broker=Broker(
host=config.stomp.host,
port=config.stomp.port,
auth=config.stomp.auth,
)
if config.stomp is None:
return cls(rest)
client = StompClient.for_broker(
broker=Broker(
host=config.stomp.host,
port=config.stomp.port,
auth=config.stomp.auth,
)
events = EventBusClient(stomp_client)
else:
events = None
)
events = EventBusClient(client)
return cls(rest, events)

@start_as_current_span(TRACER)
Expand Down
6 changes: 3 additions & 3 deletions src/blueapi/core/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,10 @@ def my_plan(a: int, b: str):
if not is_bluesky_plan_generator(plan):
raise TypeError(f"{plan} is not a valid plan generator function")

model = create_model( # type: ignore
model = create_model(
plan.__name__,
__config__=BlueapiPlanModelConfig,
**self._type_spec_for_function(plan),
**self._type_spec_for_function(plan), # type: ignore
)
self.plans[plan.__name__] = Plan(
name=plan.__name__, model=model, description=plan.__doc__
Expand Down Expand Up @@ -284,7 +284,7 @@ def _convert_type(self, typ: type | Any) -> type:
root = get_origin(typ)
if root == UnionType:
root = Union
return root[new_types] if root else typ
return root[new_types] if root else typ # type: ignore
return typ


Expand Down
7 changes: 2 additions & 5 deletions src/blueapi/core/device_lookup.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
from typing import Any, TypeVar
from typing import Any

from .bluesky_types import Device, is_bluesky_compatible_device

#: Device obeying Bluesky protocols
D = TypeVar("D", bound=Device)


def find_component(obj: Any, addr: list[str]) -> D | None:
def find_component(obj: Any, addr: list[str]) -> Device | None:
"""
Best effort function to locate a child device, either in a dictionary of
devices or a device with child attributes.
Expand Down
14 changes: 8 additions & 6 deletions src/blueapi/service/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from bluesky_stomp.messaging import StompClient
from bluesky_stomp.models import Broker, DestinationBase, MessageTopic

from blueapi.config import ApplicationConfig
from blueapi.config import ApplicationConfig, StompConfig
from blueapi.core.context import BlueskyContext
from blueapi.core.event import EventStream
from blueapi.service.model import DeviceModel, PlanModel, WorkerTask
Expand Down Expand Up @@ -50,11 +50,13 @@ def worker() -> TaskWorker:

@cache
def stomp_client() -> StompClient | None:
stomp_config = config().stomp
stomp_config: StompConfig | None = config().stomp
if stomp_config is not None:
stomp_client = StompClient.for_broker(
client = StompClient.for_broker(
broker=Broker(
host=stomp_config.host, port=stomp_config.port, auth=stomp_config.auth
host=stomp_config.host,
port=stomp_config.port,
auth=stomp_config.auth, # type: ignore
)
)

Expand All @@ -68,8 +70,8 @@ def stomp_client() -> StompClient | None:
task_worker.data_events: event_topic,
}
)
stomp_client.connect()
return stomp_client
client.connect()
return client
else:
return None

Expand Down
6 changes: 3 additions & 3 deletions src/blueapi/service/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def get_app():
TRACER = get_tracer("interface")


async def on_key_error_404(_: Request, __: KeyError):
async def on_key_error_404(_: Request, __: Exception):
return JSONResponse(
status_code=status.HTTP_404_NOT_FOUND,
content={"detail": "Item not found"},
Expand Down Expand Up @@ -181,8 +181,8 @@ def submit_task(
runner: WorkerDispatcher = Depends(_runner),
):
"""Submit a task to the worker."""
plan_model = runner.run(interface.get_plan, task.name)
try:
plan_model = runner.run(interface.get_plan, task.name)
task_id: str = runner.run(interface.submit_task, task)
response.headers["Location"] = f"{request.url}/{task_id}"
return TaskResponse(task_id=task_id)
Expand All @@ -193,7 +193,7 @@ def submit_task(
)
error_detail_response = f"""
Input validation failed: {formatted_errors},
suppplied params {task.params},
supplied params {task.params},
do not match the expected params: {plan_model.parameter_schema}
"""
raise HTTPException(
Expand Down
4 changes: 2 additions & 2 deletions src/blueapi/service/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def reload(self):
@start_as_current_span(TRACER)
def start(self):
add_span_attributes(
{"_use_subprocess": self._use_subprocess, "_config": self._config}
{"_use_subprocess": self._use_subprocess, "_config": str(self._config)}
)
try:
if self._use_subprocess:
Expand Down Expand Up @@ -176,7 +176,7 @@ def _rpc(
ctx = get_global_textmap().extract(carrier)
attach(ctx)
mod = import_module(module_name)
func: Callable[P, T] = _validate_function(
func: Callable[..., T] = _validate_function(
mod.__dict__.get(function_name, None), function_name
)
value = func(*args, **kwargs)
Expand Down
11 changes: 7 additions & 4 deletions src/blueapi/startup/example_plans.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@

from blueapi.core import MsgGenerator

TEMP: Movable = inject("sample_temperature")
PRESS: Movable = inject("sample_pressure")


def stp_snapshot(
detectors: list[Readable],
temperature: Movable = inject("sample_temperature"),
pressure: Movable = inject("sample_pressure"),
temperature: Movable = TEMP,
pressure: Movable = PRESS,
) -> MsgGenerator:
"""
Moves devices for pressure and temperature (defaults fetched from the context)
Expand All @@ -26,5 +29,5 @@ def stp_snapshot(
Yields:
Iterator[MsgGenerator]: Bluesky messages
"""
yield from move({temperature: 0, pressure: 10**5})
yield from count(detectors, 1)
yield from move({temperature: 0, pressure: 10**5}) # type: ignore
yield from count(set(detectors), 1)
12 changes: 6 additions & 6 deletions src/blueapi/startup/simmotor.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from collections.abc import Callable

from ophyd.sim import SynAxis
from ophyd.status import MoveStatus, Status
from ophyd.status import MoveStatus


class SynAxisWithMotionEvents(SynAxis):
Expand All @@ -27,8 +27,8 @@ def __init__(
super().__init__(
name=name,
readback_func=readback_func,
value=value,
delay=delay,
value=value, # type: ignore
delay=delay, # type: ignore
precision=precision,
parent=parent,
labels=labels,
Expand All @@ -38,7 +38,7 @@ def __init__(
self._events_per_move = events_per_move
self.egu = egu

def set(self, value: float) -> None:
def set(self, value: float) -> MoveStatus:
old_setpoint = self.sim_state["setpoint"]
distance = value - old_setpoint
self.sim_state["setpoint"] = value
Expand Down Expand Up @@ -90,5 +90,5 @@ def __init__(self, *, timeout: float, **kwargs) -> None:
super().__init__(**kwargs)
self._timeout = timeout

def set(self, value: float) -> Status:
return Status(timeout=self._timeout)
def set(self, value: float) -> MoveStatus:
return MoveStatus(positioner=self, target=value, timeout=self._timeout)
1 change: 0 additions & 1 deletion src/blueapi/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
__all__ = [
"handle_all_exceptions",
"load_module_all",
"ConfigLoader",
"serialize",
"BlueapiBaseModel",
"BlueapiModelConfig",
Expand Down
1 change: 0 additions & 1 deletion src/blueapi/worker/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
__all__ = [
"TaskWorker",
"Task",
"Worker",
"WorkerEvent",
"WorkerState",
"StatusView",
Expand Down
3 changes: 2 additions & 1 deletion src/blueapi/worker/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
from blueapi.utils import BlueapiBaseModel

# The RunEngine can return any of these three types as its state
RawRunEngineState = type[PropertyMachine | ProxyString | str]
# RawRunEngineState = type[PropertyMachine | ProxyString | str]
RawRunEngineState = PropertyMachine | ProxyString | str


# NOTE this is interim until refactor
Expand Down
Loading

0 comments on commit 86c5905

Please sign in to comment.