diff --git a/.codecov.yml b/.codecov.yml index 9a442b1b8c..68eb55579e 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -9,6 +9,6 @@ coverage: patch: default: target: auto - threshold: 0.1% + threshold: 1% github_checks: annotations: false diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 7b70d5bdc9..349a45cc6f 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -3,7 +3,7 @@ # The devcontainer should use the build target and run as root with podman # or docker with user namespaces. # -FROM python:3.8 as build +FROM python:3.9 as build ARG PIP_OPTIONS @@ -24,7 +24,7 @@ WORKDIR /context # install python package into /venv RUN pip install ${PIP_OPTIONS} -FROM python:3.8-slim as runtime +FROM python:3.9-slim as runtime # Add apt-get system dependecies for runtime here if needed diff --git a/.github/workflows/code.yml b/.github/workflows/code.yml index 33dd22da8c..77dd8f9132 100644 --- a/.github/workflows/code.yml +++ b/.github/workflows/code.yml @@ -29,12 +29,12 @@ jobs: fail-fast: false matrix: os: ["ubuntu-latest"] # can add windows-latest, macos-latest - python: ["3.9", "3.10", "3.11"] + python: ["3.10", "3.11"] install: ["-e .[dev]"] # Make one version be non-editable to test both paths of version code include: - os: "ubuntu-latest" - python: "3.8" + python: "3.9" install: ".[dev]" runs-on: ${{ matrix.os }} diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index c510d577a9..a501f7d030 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -46,7 +46,7 @@ jobs: if: github.event_name == 'push' && github.actor != 'dependabot[bot]' # We pin to the SHA, not the tag, for security reasons. # https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions - uses: peaceiris/actions-gh-pages@64b46b4226a4a12da2239ba3ea5aa73e3163c75b # v3.9.1 + uses: peaceiris/actions-gh-pages@373f7f263a76c20808c831209c920827a82a2847 # v3.9.3 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: .github/pages diff --git a/.gitignore b/.gitignore index 409a0717a5..1ce3f7a583 100644 --- a/.gitignore +++ b/.gitignore @@ -84,4 +84,4 @@ docs/*/generated docs/savefig # generated version number -ophyd/_version.py +ophyd_async/_version.py diff --git a/docs/conf.py b/docs/conf.py index 57f5366ead..7327ea2f72 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -4,6 +4,7 @@ # list see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html +import os import sys from pathlib import Path from subprocess import check_output @@ -13,9 +14,11 @@ import ophyd_async # -- General configuration ------------------------------------------------ +# Source code dir relative to this file +sys.path.insert(0, os.path.abspath("../../src")) # General information about the project. -project = "ophyd_async" +project = "ophyd-async" copyright = "2014, Brookhaven National Lab" # The full version, including alpha/beta/rc tags. @@ -208,14 +211,17 @@ # every member listed in __all__ and no others. Default is True autosummary_ignore_module_all = False +# Turn on sphinx.ext.autosummary +autosummary_generate = True + +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + # Look for signatures in the first line of the docstring (used for C functions) autodoc_docstring_signature = True # numpydoc config numpydoc_show_class_members = False -# Add any paths that contain templates here, relative to this directory. -templates_path = ["_templates"] - # Where to put Ipython savefigs ipython_savefig_dir = "../build/savefig" diff --git a/docs/developer/explanations/decisions/0002-switched-to-pip-skeleton.rst b/docs/developer/explanations/decisions/0002-switched-to-pip-skeleton.rst index a00833145a..d0cd738402 100644 --- a/docs/developer/explanations/decisions/0002-switched-to-pip-skeleton.rst +++ b/docs/developer/explanations/decisions/0002-switched-to-pip-skeleton.rst @@ -1,4 +1,4 @@ -2. Adopt ophyd_async for project structure +2. Adopt ophyd-async for project structure ========================================== Date: 2022-02-18 @@ -11,7 +11,7 @@ Accepted Context ------- -We should use the following `pip-skeleton `_. +We should use the following `pip-skeleton `_. The skeleton will ensure consistency in developer environments and package management. @@ -23,7 +23,7 @@ We have switched to using the skeleton. Consequences ------------ -This module will use a fixed set of tools as developed in ophyd_async +This module will use a fixed set of tools as developed in ophyd-async and can pull from this skeleton to update the packaging to the latest techniques. As such, the developer environment may have changed, the following could be diff --git a/docs/developer/explanations/decisions/0004-repository-structure.rst b/docs/developer/explanations/decisions/0004-repository-structure.rst index 69ac640400..411cf858d3 100644 --- a/docs/developer/explanations/decisions/0004-repository-structure.rst +++ b/docs/developer/explanations/decisions/0004-repository-structure.rst @@ -1,7 +1,13 @@ +.. role:: bash(code) + :language: bash + +.. role:: python(code) + :language: python + 4. Repository Structure ======================= -Date: 2023-08-30 +Date: 2023-09-07 Status ------ @@ -53,21 +59,22 @@ During this process, the folder structure should incrementally be changed to │ └── ophyd_async │ ├── core │ │ ├── __init__.py - │ │ ├── backends - │ │ │ ├── __init__.py - │ │ │ ├── signal_backend.py - │ │ │ └── sim.py - │ │ ├── devices + │ │ ├── _device │ │ │ ├── __init__.py + │ │ │ ├── _backend + │ │ │ │ ├── __init__.py + │ │ │ │ ├── signal_backend.py + │ │ │ │ └── sim.py + │ │ │ ├── _signal + │ │ │ │ ├── __init__.py + │ │ │ │ └── signal.py │ │ │ ├── device_collector.py + │ │ │ ├── device_vector.py │ │ │ └── ... - │ │ ├── epicsdemo - │ │ │ └── ... - │ │ ├── signal.py │ │ ├── async_status.py │ │ └── utils.py │ ├── epics - │ │ ├── backends + │ │ ├── _backend │ │ │ ├── __init__.py │ │ │ ├── _p4p.py │ │ │ └── _aioca.py @@ -77,9 +84,11 @@ During this process, the folder structure should incrementally be changed to │ │ │ └── ... │ │ ├── signal │ │ │ └── ... - │ │ └── motion - │ │ ├── __init__.py - │ │ └── motor.py + │ │ ├── motion + │ │ │ ├── __init__.py + │ │ │ └── motor.py + │ │ └── demo + │ │ └── ... │ └── panda │ └── ... ├── tests @@ -88,10 +97,10 @@ During this process, the folder structure should incrementally be changed to │ └── epics └── ... -The `__init__.py` files of each submodule (core, epics, panda and eventually tango) will +The :bash:`__init__.py` files of each submodule (core, epics, panda and eventually tango) will be modified such that end users experience little disruption to how they use Ophyd Async. -For such users, `from ophyd.v2.core import ...` can be replaced with -`from ophyd_async.core import ...`. +For such users, :python:`from ophyd.v2.core import ...` can be replaced with +:python:`from ophyd_async.core import ...`. Consequences diff --git a/docs/developer/how-to/pin-requirements.rst b/docs/developer/how-to/pin-requirements.rst index 97784060c4..e42226fbcf 100644 --- a/docs/developer/how-to/pin-requirements.rst +++ b/docs/developer/how-to/pin-requirements.rst @@ -46,7 +46,7 @@ of the dependencies and sub-dependencies with pinned versions. You can download any of these files by clicking on them. It is best to use the one that ran with the lowest Python version as this is more likely to be compatible with all the versions of Python in the test matrix. -i.e. ``requirements-test-ubuntu-latest-3.8.txt`` in this example. +i.e. ``requirements-test-ubuntu-latest-3.9.txt`` in this example. Applying the lock file ---------------------- diff --git a/docs/developer/tutorials/dev-install.rst b/docs/developer/tutorials/dev-install.rst index 13e029d5f4..59f16a919b 100644 --- a/docs/developer/tutorials/dev-install.rst +++ b/docs/developer/tutorials/dev-install.rst @@ -16,7 +16,7 @@ Install dependencies -------------------- You can choose to either develop on the host machine using a `venv` (which -requires python 3.8 or later) or to run in a container under `VSCode +requires python 3.9 or later) or to run in a container under `VSCode `_ .. tab-set:: diff --git a/docs/examples/ad_demo.py b/docs/examples/ad_demo.py index 6e75da96e6..c4f0a709dc 100644 --- a/docs/examples/ad_demo.py +++ b/docs/examples/ad_demo.py @@ -9,7 +9,7 @@ from bluesky.utils import ProgressBarManager, register_transform from ophyd.v2.core import DeviceCollector -from ophyd_async.epics.areadetector import areadetector +from ophyd_async.epics import areadetector # Create a run engine, with plotting, progressbar and transform RE = RunEngine({}, call_returns_result=True) @@ -25,9 +25,7 @@ # Create v2 devices with DeviceCollector(): - det1 = areadetector.MySingleTriggerSim(pv_prefix) - det2 = areadetector.MyHDFWritingSim(pv_prefix) - det3 = areadetector.MyHDFFlyerSim(pv_prefix) + det3 = areadetector.HDFStreamerDet(pv_prefix) # And a plan diff --git a/docs/index.rst b/docs/index.rst index 72b1c07974..054db2b377 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -14,13 +14,13 @@ The documentation is split into 2 sections: :link: user/index :link-type: doc - The User Guide contains documentation on how to install and use ophyd_async. + The User Guide contains documentation on how to install and use ophyd-async. .. grid-item-card:: :material-regular:`code;4em` :link: developer/index :link-type: doc - The Developer Guide contains documentation on how to develop and contribute changes back to ophyd_async. + The Developer Guide contains documentation on how to develop and contribute changes back to ophyd-async. .. toctree:: :hidden: diff --git a/docs/user/examples/epics_demo.py b/docs/user/examples/epics_demo.py index c96c2cb100..862377e73d 100644 --- a/docs/user/examples/epics_demo.py +++ b/docs/user/examples/epics_demo.py @@ -7,8 +7,8 @@ from bluesky.utils import ProgressBarManager, register_transform from ophyd import Component, Device, EpicsSignal, EpicsSignalRO -from ophyd_async.core import epicsdemo -from ophyd_async.core.devices.device_collector import DeviceCollector +from ophyd_async.core import DeviceCollector +from ophyd_async.epics import demo # Create a run engine, with plotting, progressbar and transform RE = RunEngine({}, call_returns_result=True) @@ -19,7 +19,7 @@ register_transform("RE", prefix="<") # Start IOC with demo pvs in subprocess -pv_prefix = epicsdemo.start_ioc_subprocess() +pv_prefix = demo.start_ioc_subprocess() # Create ophyd devices @@ -32,5 +32,5 @@ class OldSensor(Device): # Create ophyd-async devices with DeviceCollector(): - det = epicsdemo.Sensor(pv_prefix) - samp = epicsdemo.SampleStage(pv_prefix) + det = demo.Sensor(pv_prefix) + samp = demo.SampleStage(pv_prefix) diff --git a/docs/user/how-to/make-a-simple-device.rst b/docs/user/how-to/make-a-simple-device.rst index 4541eb6c75..86b112d307 100644 --- a/docs/user/how-to/make-a-simple-device.rst +++ b/docs/user/how-to/make-a-simple-device.rst @@ -6,14 +6,14 @@ Make a Simple Device ==================== -.. currentmodule:: ophyd_async.core.core +.. currentmodule:: ophyd_async.core To make a simple device, you need to subclass from the `StandardReadable` class, create some `Signal` instances, and optionally implement other suitable Bluesky `Protocols ` like :class:`~bluesky.protocols.Movable`. -The rest of this guide will show examples from ``src/ophyd_async/core/epicsdemo/__init__.py`` +The rest of this guide will show examples from ``src/ophyd_async/epics/demo/__init__.py`` Readable -------- @@ -22,7 +22,7 @@ For a simple :class:`~bluesky.protocols.Readable` object like a `Sensor`, you ne define some signals, then tell the superclass which signals should contribute to ``read()`` and ``read_configuration()``: -.. literalinclude:: ../../../src/ophyd_async/core/epicsdemo/__init__.py +.. literalinclude:: ../../../src/ophyd_async/epics/demo/__init__.py :pyobject: Sensor First some Signals are constructed and stored on the Device. Each one is passed @@ -53,7 +53,7 @@ Movable For a more complicated device like a `Mover`, you can still use `StandardReadable` and implement some addition protocols: -.. literalinclude:: ../../../src/ophyd_async/core/epicsdemo/__init__.py +.. literalinclude:: ../../../src/ophyd_async/epics/demo/__init__.py :pyobject: Mover The ``set()`` method implements :class:`~bluesky.protocols.Movable`. This @@ -70,7 +70,7 @@ Assembly Compound assemblies can be used to group Devices into larger logical Devices: -.. literalinclude:: ../../../src/ophyd_async/core/epicsdemo/__init__.py +.. literalinclude:: ../../../src/ophyd_async/epics/demo/__init__.py :pyobject: SampleStage This applies prefixes on construction: diff --git a/docs/user/reference/api.rst b/docs/user/reference/api.rst index d5a1bb90cf..362154c8d1 100644 --- a/docs/user/reference/api.rst +++ b/docs/user/reference/api.rst @@ -6,9 +6,9 @@ API === -.. automodule:: ophyd_async.core +.. automodule:: ophyd_async - ``ophyd_async.core`` + ``ophyd_async`` ----------------------------------- This is the internal API reference for ophyd_async @@ -24,9 +24,6 @@ This is the internal API reference for ophyd_async :template: custom-module-template.rst :recursive: - ophyd_async.core.backends - ophyd_async.core.devices - ophyd_async.core.epicsdemo - ophyd_async.core.signal - ophyd_async.core.async_status - ophyd_async.core.utils + core + epics + panda diff --git a/docs/user/tutorials/installation.rst b/docs/user/tutorials/installation.rst index beb9aa2677..9e310adbce 100644 --- a/docs/user/tutorials/installation.rst +++ b/docs/user/tutorials/installation.rst @@ -9,7 +9,7 @@ Installation Check your version of python ---------------------------- -You will need python 3.8 or later. You can check your version of python by +You will need python 3.9 or later. You can check your version of python by typing into a terminal:: $ python3 --version @@ -30,7 +30,7 @@ Installing the library You can now use ``pip`` to install the library and its dependencies:: - $ python3 -m pip install ophyd_async + $ python3 -m pip install ophyd-async If you require a feature that is not currently released you can also install from github:: @@ -40,4 +40,4 @@ from github:: The library should now be installed and the commandline interface on your path. You can check the version that has been installed by typing:: - $ ophyd_async --version + $ ophyd-async --version diff --git a/docs/user/tutorials/using-existing-devices.rst b/docs/user/tutorials/using-existing-devices.rst index db76e3d577..067d01ca99 100644 --- a/docs/user/tutorials/using-existing-devices.rst +++ b/docs/user/tutorials/using-existing-devices.rst @@ -41,7 +41,7 @@ that you can mix Ophyd and Ophyd Async devices in the same RunEngine: :start-after: # Create ophyd devices :end-before: # Create ophyd-async devices -Finally we create the Ophyd Async devices imported from the `epicsdemo` module: +Finally we create the Ophyd Async devices imported from the `epics.demo` module: .. literalinclude:: ../examples/epics_demo.py :language: python @@ -154,7 +154,7 @@ There is also an "energy mode" that can be changed to modify the ``det`` output. In [1]: =64", "setuptools_scm[toml]>=6.2", "wheel"] build-backend = "setuptools.build_meta" [project] -name = "ophyd_async" +name = "ophyd-async" classifiers = [ "Development Status :: 3 - Alpha", "License :: OSI Approved :: BSD License", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -27,7 +26,7 @@ dependencies = [ dynamic = ["version"] license.file = "LICENSE" readme = "README.rst" -requires-python = ">=3.8" +requires-python = ">=3.9" [project.optional-dependencies] ca = ["aioca>=1.6"] @@ -74,7 +73,7 @@ dev = [ ] [project.scripts] -ophyd_async = "ophyd_async.__main__:main" +ophyd-async = "ophyd_async.__main__:main" [project.urls] GitHub = "https://github.com/bluesky/ophyd-async" diff --git a/src/ophyd_async/__init__.py b/src/ophyd_async/__init__.py index 5171b1dcda..4100754a36 100644 --- a/src/ophyd_async/__init__.py +++ b/src/ophyd_async/__init__.py @@ -1,11 +1,6 @@ -import sys +from importlib.metadata import version # noqa -if sys.version_info < (3, 8): - from importlib_metadata import version # noqa -else: - from importlib.metadata import version # noqa - -__version__ = version("ophyd_async") +__version__ = version("ophyd-async") del version __all__ = ["__version__"] diff --git a/src/ophyd_async/core/__init__.py b/src/ophyd_async/core/__init__.py index 29c051d9f0..f74eba7692 100644 --- a/src/ophyd_async/core/__init__.py +++ b/src/ophyd_async/core/__init__.py @@ -1,15 +1,6 @@ -from .async_status import AsyncStatus -from .backends import SignalBackend, SimSignalBackend -from .devices import ( - Device, - DeviceCollector, - DeviceVector, - StandardReadable, - connect_children, - get_device_children, - name_children, -) -from .signal import ( +from ._device._backend.signal_backend import SignalBackend +from ._device._backend.sim_signal_backend import SimSignalBackend +from ._device._signal.signal import ( Signal, SignalR, SignalRW, @@ -22,6 +13,11 @@ set_sim_value, wait_for_value, ) +from ._device.device import Device, connect_children, get_device_children, name_children +from ._device.device_collector import DeviceCollector +from ._device.device_vector import DeviceVector +from ._device.standard_readable import StandardReadable +from .async_status import AsyncStatus from .utils import ( DEFAULT_TIMEOUT, Callback, @@ -35,16 +31,8 @@ ) __all__ = [ - "AsyncStatus", "SignalBackend", "SimSignalBackend", - "DeviceCollector", - "Device", - "DeviceVector", - "StandardReadable", - "connect_children", - "get_device_children", - "name_children", "Signal", "SignalR", "SignalW", @@ -56,6 +44,14 @@ "set_sim_put_proceeds", "set_sim_value", "wait_for_value", + "Device", + "connect_children", + "get_device_children", + "name_children", + "DeviceCollector", + "DeviceVector", + "StandardReadable", + "AsyncStatus", "DEFAULT_TIMEOUT", "Callback", "NotConnected", diff --git a/src/ophyd_async/epics/backends/__init__.py b/src/ophyd_async/core/_device/__init__.py similarity index 100% rename from src/ophyd_async/epics/backends/__init__.py rename to src/ophyd_async/core/_device/__init__.py diff --git a/src/ophyd_async/core/_device/_backend/__init__.py b/src/ophyd_async/core/_device/_backend/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/ophyd_async/core/backends/signal_backend.py b/src/ophyd_async/core/_device/_backend/signal_backend.py similarity index 96% rename from src/ophyd_async/core/backends/signal_backend.py rename to src/ophyd_async/core/_device/_backend/signal_backend.py index 4413d2debb..e0722ced77 100644 --- a/src/ophyd_async/core/backends/signal_backend.py +++ b/src/ophyd_async/core/_device/_backend/signal_backend.py @@ -3,7 +3,7 @@ from bluesky.protocols import Descriptor, Reading -from ..utils import ReadingValueCallback, T +from ...utils import ReadingValueCallback, T class SignalBackend(Generic[T]): diff --git a/src/ophyd_async/core/backends/sim.py b/src/ophyd_async/core/_device/_backend/sim_signal_backend.py similarity index 98% rename from src/ophyd_async/core/backends/sim.py rename to src/ophyd_async/core/_device/_backend/sim_signal_backend.py index 2454497b93..2d29363c29 100644 --- a/src/ophyd_async/core/backends/sim.py +++ b/src/ophyd_async/core/_device/_backend/sim_signal_backend.py @@ -11,7 +11,7 @@ from bluesky.protocols import Descriptor, Dtype, Reading -from ..utils import ReadingValueCallback, T, get_dtype +from ...utils import ReadingValueCallback, T, get_dtype from .signal_backend import SignalBackend primitive_dtypes: Dict[type, Dtype] = { diff --git a/src/ophyd_async/core/_device/_signal/__init__.py b/src/ophyd_async/core/_device/_signal/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/ophyd_async/core/signal.py b/src/ophyd_async/core/_device/_signal/signal.py similarity index 97% rename from src/ophyd_async/core/signal.py rename to src/ophyd_async/core/_device/_signal/signal.py index 1e0ff0d23c..1b5d4b03d3 100644 --- a/src/ophyd_async/core/signal.py +++ b/src/ophyd_async/core/_device/_signal/signal.py @@ -13,11 +13,11 @@ Subscribable, ) -from .async_status import AsyncStatus -from .backends.signal_backend import SignalBackend -from .backends.sim import SimSignalBackend -from .devices import Device -from .utils import DEFAULT_TIMEOUT, Callback, ReadingValueCallback, T +from ...async_status import AsyncStatus +from ...utils import DEFAULT_TIMEOUT, Callback, ReadingValueCallback, T +from .._backend.signal_backend import SignalBackend +from .._backend.sim_signal_backend import SimSignalBackend +from ..device import Device _sim_backends: Dict[Signal, SimSignalBackend] = {} diff --git a/src/ophyd_async/core/devices/device.py b/src/ophyd_async/core/_device/device.py similarity index 99% rename from src/ophyd_async/core/devices/device.py rename to src/ophyd_async/core/_device/device.py index e47f4c9bbc..0595a2e673 100644 --- a/src/ophyd_async/core/devices/device.py +++ b/src/ophyd_async/core/_device/device.py @@ -1,3 +1,5 @@ +"""Base device""" + from typing import Generator, Optional, Tuple from bluesky.protocols import HasName diff --git a/src/ophyd_async/core/devices/device_collector.py b/src/ophyd_async/core/_device/device_collector.py similarity index 98% rename from src/ophyd_async/core/devices/device_collector.py rename to src/ophyd_async/core/_device/device_collector.py index ffe286da48..736a21635e 100644 --- a/src/ophyd_async/core/devices/device_collector.py +++ b/src/ophyd_async/core/_device/device_collector.py @@ -1,3 +1,4 @@ +"""Interface for connecting and naming multiple devices""" import asyncio import logging import sys diff --git a/src/ophyd_async/core/devices/device_vector.py b/src/ophyd_async/core/_device/device_vector.py similarity index 87% rename from src/ophyd_async/core/devices/device_vector.py rename to src/ophyd_async/core/_device/device_vector.py index 027280a886..077e51d20f 100644 --- a/src/ophyd_async/core/devices/device_vector.py +++ b/src/ophyd_async/core/_device/device_vector.py @@ -1,3 +1,5 @@ +"""Dictionary which can contain mappings between integers and devices.""" + from typing import Dict, TypeVar from ..utils import wait_for_connection diff --git a/src/ophyd_async/core/devices/standard_readable.py b/src/ophyd_async/core/_device/standard_readable.py similarity index 90% rename from src/ophyd_async/core/devices/standard_readable.py rename to src/ophyd_async/core/_device/standard_readable.py index 2e64c4f71f..fe6a7a3fd6 100644 --- a/src/ophyd_async/core/devices/standard_readable.py +++ b/src/ophyd_async/core/_device/standard_readable.py @@ -3,8 +3,8 @@ from bluesky.protocols import Configurable, Descriptor, Readable, Reading, Stageable from ..async_status import AsyncStatus -from ..signal import SignalR from ..utils import merge_gathered_dicts +from ._signal.signal import SignalR from .device import Device @@ -30,11 +30,11 @@ def set_readable_signals( Parameters ---------- read: - Signals to make up `read()` + Signals to make up :meth:`~StandardReadable.read` conf: - Signals to make up `read_configuration()` + Signals to make up :meth:`~StandardReadable.read_configuration` read_uncached: - Signals to make up `read()` that won't be cached + Signals to make up :meth:`~StandardReadable.read` that won't be cached """ self._read_signals = tuple(read) self._configuration_signals = tuple(config) diff --git a/src/ophyd_async/core/async_status.py b/src/ophyd_async/core/async_status.py index 0905845cf9..96f9f717a9 100644 --- a/src/ophyd_async/core/async_status.py +++ b/src/ophyd_async/core/async_status.py @@ -1,3 +1,5 @@ +"""Equivalent of bluesky.protols.Status for asynchronous tasks.""" + import asyncio import functools from typing import Awaitable, Callable, Coroutine, List, Optional, cast diff --git a/src/ophyd_async/core/backends/__init__.py b/src/ophyd_async/core/backends/__init__.py deleted file mode 100644 index f88d17e64a..0000000000 --- a/src/ophyd_async/core/backends/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from .signal_backend import SignalBackend -from .sim import SimSignalBackend - -__all__ = ["SignalBackend", "SimSignalBackend"] diff --git a/src/ophyd_async/core/devices/__init__.py b/src/ophyd_async/core/devices/__init__.py deleted file mode 100644 index 6f88fe2d29..0000000000 --- a/src/ophyd_async/core/devices/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -from .device import Device, connect_children, get_device_children, name_children -from .device_collector import DeviceCollector -from .device_vector import DeviceVector -from .standard_readable import StandardReadable - -__all__ = [ - "Device", - "DeviceCollector", - "connect_children", - "get_device_children", - "name_children", - "DeviceVector", - "StandardReadable", -] diff --git a/src/ophyd_async/epics/_backend/__init__.py b/src/ophyd_async/epics/_backend/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/ophyd_async/epics/backends/_aioca.py b/src/ophyd_async/epics/_backend/_aioca.py similarity index 98% rename from src/ophyd_async/epics/backends/_aioca.py rename to src/ophyd_async/epics/_backend/_aioca.py index cc38db36e9..46bf491486 100644 --- a/src/ophyd_async/epics/backends/_aioca.py +++ b/src/ophyd_async/epics/_backend/_aioca.py @@ -17,10 +17,10 @@ from bluesky.protocols import Descriptor, Dtype, Reading from epicscorelibs.ca import dbr -from ophyd_async.core.signal import SignalBackend -from ophyd_async.core.utils import ( +from ophyd_async.core import ( NotConnected, ReadingValueCallback, + SignalBackend, T, get_dtype, get_unique, diff --git a/src/ophyd_async/epics/backends/_p4p.py b/src/ophyd_async/epics/_backend/_p4p.py similarity index 99% rename from src/ophyd_async/epics/backends/_p4p.py rename to src/ophyd_async/epics/_backend/_p4p.py index 8e1ac645c5..d92d36a604 100644 --- a/src/ophyd_async/epics/backends/_p4p.py +++ b/src/ophyd_async/epics/_backend/_p4p.py @@ -8,10 +8,10 @@ from bluesky.protocols import Descriptor, Dtype, Reading from p4p.client.asyncio import Context, Subscription -from ophyd_async.core.signal import SignalBackend -from ophyd_async.core.utils import ( +from ophyd_async.core import ( NotConnected, ReadingValueCallback, + SignalBackend, T, get_dtype, get_unique, diff --git a/src/ophyd_async/epics/areadetector/ad_driver.py b/src/ophyd_async/epics/areadetector/ad_driver.py index 5ec78b740f..7b95e53d6e 100644 --- a/src/ophyd_async/epics/areadetector/ad_driver.py +++ b/src/ophyd_async/epics/areadetector/ad_driver.py @@ -1,6 +1,6 @@ -from ophyd_async.core.devices import Device -from ophyd_async.epics.signal import epics_signal_rw +from ophyd_async.core import Device +from ..signal.signal import epics_signal_rw from .utils import ImageMode, ad_r, ad_rw diff --git a/src/ophyd_async/epics/areadetector/hdf_streamer_det.py b/src/ophyd_async/epics/areadetector/hdf_streamer_det.py index 070103a1b5..65870d7c91 100644 --- a/src/ophyd_async/epics/areadetector/hdf_streamer_det.py +++ b/src/ophyd_async/epics/areadetector/hdf_streamer_det.py @@ -13,10 +13,12 @@ from bluesky.utils import new_uid from event_model import compose_stream_resource -from ophyd_async.core.async_status import AsyncStatus -from ophyd_async.core.devices import StandardReadable -from ophyd_async.core.signal import set_and_wait_for_value -from ophyd_async.core.utils import DEFAULT_TIMEOUT +from ophyd_async.core import ( + DEFAULT_TIMEOUT, + AsyncStatus, + StandardReadable, + set_and_wait_for_value, +) from .ad_driver import ADDriver from .directory_provider import DirectoryProvider diff --git a/src/ophyd_async/epics/areadetector/nd_file_hdf.py b/src/ophyd_async/epics/areadetector/nd_file_hdf.py index 851538d52a..b8d6096fda 100644 --- a/src/ophyd_async/epics/areadetector/nd_file_hdf.py +++ b/src/ophyd_async/epics/areadetector/nd_file_hdf.py @@ -1,6 +1,6 @@ -from ophyd_async.core.devices import Device -from ophyd_async.epics.signal import epics_signal_rw +from ophyd_async.core import Device +from ..signal.signal import epics_signal_rw from .utils import FileWriteMode, ad_r, ad_rw diff --git a/src/ophyd_async/epics/areadetector/nd_plugin.py b/src/ophyd_async/epics/areadetector/nd_plugin.py index 89cdab5bd6..0128cade29 100644 --- a/src/ophyd_async/epics/areadetector/nd_plugin.py +++ b/src/ophyd_async/epics/areadetector/nd_plugin.py @@ -1,4 +1,4 @@ -from ophyd_async.core.devices import Device +from ophyd_async.core import Device from .utils import ad_r diff --git a/src/ophyd_async/epics/areadetector/single_trigger_det.py b/src/ophyd_async/epics/areadetector/single_trigger_det.py index b402983cf5..271890c321 100644 --- a/src/ophyd_async/epics/areadetector/single_trigger_det.py +++ b/src/ophyd_async/epics/areadetector/single_trigger_det.py @@ -3,9 +3,7 @@ from bluesky.protocols import Triggerable -from ophyd_async.core.async_status import AsyncStatus -from ophyd_async.core.devices import StandardReadable -from ophyd_async.core.signal import SignalR +from ophyd_async.core import AsyncStatus, SignalR, StandardReadable from .ad_driver import ADDriver from .nd_plugin import NDPlugin diff --git a/src/ophyd_async/epics/areadetector/utils.py b/src/ophyd_async/epics/areadetector/utils.py index 099f295ba7..25b283e017 100644 --- a/src/ophyd_async/epics/areadetector/utils.py +++ b/src/ophyd_async/epics/areadetector/utils.py @@ -1,9 +1,9 @@ from enum import Enum from typing import Type -from ophyd_async.core.signal import SignalR, SignalRW -from ophyd_async.core.utils import T -from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw +from ophyd_async.core import SignalR, SignalRW, T + +from ..signal.signal import epics_signal_r, epics_signal_rw def ad_rw(datatype: Type[T], prefix: str) -> SignalRW[T]: diff --git a/src/ophyd_async/core/epicsdemo/__init__.py b/src/ophyd_async/epics/demo/__init__.py similarity index 96% rename from src/ophyd_async/core/epicsdemo/__init__.py rename to src/ophyd_async/epics/demo/__init__.py index 72bea9de4d..da9a0947a5 100644 --- a/src/ophyd_async/core/epicsdemo/__init__.py +++ b/src/ophyd_async/epics/demo/__init__.py @@ -1,15 +1,22 @@ """Demo EPICS Devices for the tutorial""" import asyncio +import atexit +import random +import string +import subprocess +import sys import time from enum import Enum +from pathlib import Path from typing import Callable, List, Optional import numpy as np from bluesky.protocols import Movable, Stoppable from ophyd_async.core import AsyncStatus, Device, StandardReadable, observe_value -from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw, epics_signal_x + +from ..signal.signal import epics_signal_r, epics_signal_rw, epics_signal_x class EnergyMode(Enum): @@ -123,12 +130,6 @@ def start_ioc_subprocess() -> str: """Start an IOC subprocess with EPICS database for sample stage and sensor with the same pv prefix """ - import atexit - import random - import string - import subprocess - import sys - from pathlib import Path pv_prefix = "".join(random.choice(string.ascii_uppercase) for _ in range(12)) + ":" here = Path(__file__).absolute().parent diff --git a/src/ophyd_async/core/epicsdemo/mover.db b/src/ophyd_async/epics/demo/mover.db similarity index 100% rename from src/ophyd_async/core/epicsdemo/mover.db rename to src/ophyd_async/epics/demo/mover.db diff --git a/src/ophyd_async/core/epicsdemo/sensor.db b/src/ophyd_async/epics/demo/sensor.db similarity index 100% rename from src/ophyd_async/core/epicsdemo/sensor.db rename to src/ophyd_async/epics/demo/sensor.db diff --git a/src/ophyd_async/epics/motion/__init__.py b/src/ophyd_async/epics/motion/__init__.py index e69de29bb2..5effa7fb6e 100644 --- a/src/ophyd_async/epics/motion/__init__.py +++ b/src/ophyd_async/epics/motion/__init__.py @@ -0,0 +1,3 @@ +from .motor import Motor + +__all__ = ["Motor"] diff --git a/src/ophyd_async/epics/motion/motor.py b/src/ophyd_async/epics/motion/motor.py index 460515db79..9b0813705d 100644 --- a/src/ophyd_async/epics/motion/motor.py +++ b/src/ophyd_async/epics/motion/motor.py @@ -4,9 +4,9 @@ from bluesky.protocols import Movable, Stoppable -from ophyd_async.core.async_status import AsyncStatus -from ophyd_async.core.devices import StandardReadable -from ophyd_async.epics.signal import epics_signal_r, epics_signal_rw, epics_signal_x +from ophyd_async.core import AsyncStatus, StandardReadable + +from ..signal.signal import epics_signal_r, epics_signal_rw, epics_signal_x class Motor(StandardReadable, Movable, Stoppable): diff --git a/src/ophyd_async/epics/signal/__init__.py b/src/ophyd_async/epics/signal/__init__.py index b9b3d1a811..ca9cebd3fd 100644 --- a/src/ophyd_async/epics/signal/__init__.py +++ b/src/ophyd_async/epics/signal/__init__.py @@ -1,8 +1,8 @@ -from .epics_transport import EpicsTransport +from .pvi_get import pvi_get from .signal import epics_signal_r, epics_signal_rw, epics_signal_w, epics_signal_x __all__ = [ - "EpicsTransport", + "pvi_get", "epics_signal_r", "epics_signal_rw", "epics_signal_w", diff --git a/src/ophyd_async/epics/signal/epics_transport.py b/src/ophyd_async/epics/signal/_epics_transport.py similarity index 88% rename from src/ophyd_async/epics/signal/epics_transport.py rename to src/ophyd_async/epics/signal/_epics_transport.py index 393960c976..145af21622 100644 --- a/src/ophyd_async/epics/signal/epics_transport.py +++ b/src/ophyd_async/epics/signal/_epics_transport.py @@ -5,7 +5,7 @@ from enum import Enum try: - from ..backends._aioca import CaSignalBackend + from .._backend._aioca import CaSignalBackend except ImportError as ca_error: class CaSignalBackend: # type: ignore @@ -14,7 +14,7 @@ def __init__(*args, ca_error=ca_error, **kwargs): try: - from ..backends._p4p import PvaSignalBackend + from .._backend._p4p import PvaSignalBackend except ImportError as pva_error: class PvaSignalBackend: # type: ignore diff --git a/src/ophyd_async/epics/signal/pvi_get.py b/src/ophyd_async/epics/signal/pvi_get.py index c7d814178d..f31899448c 100644 --- a/src/ophyd_async/epics/signal/pvi_get.py +++ b/src/ophyd_async/epics/signal/pvi_get.py @@ -1,6 +1,6 @@ from typing import Dict, TypedDict -from p4p.client.thread import Context +from p4p.client.asyncio import Context class PVIEntry(TypedDict, total=False): diff --git a/src/ophyd_async/epics/signal/signal.py b/src/ophyd_async/epics/signal/signal.py index 7c22da3754..c02c436d82 100644 --- a/src/ophyd_async/epics/signal/signal.py +++ b/src/ophyd_async/epics/signal/signal.py @@ -4,10 +4,17 @@ from typing import Optional, Tuple, Type -from ophyd_async.core.signal import SignalBackend, SignalR, SignalRW, SignalW, SignalX -from ophyd_async.core.utils import T, get_unique - -from .epics_transport import EpicsTransport +from ophyd_async.core import ( + SignalBackend, + SignalR, + SignalRW, + SignalW, + SignalX, + T, + get_unique, +) + +from ._epics_transport import EpicsTransport _default_epics_transport = EpicsTransport.ca diff --git a/src/ophyd_async/panda/__init__.py b/src/ophyd_async/panda/__init__.py index e69de29bb2..8df8dcde1f 100644 --- a/src/ophyd_async/panda/__init__.py +++ b/src/ophyd_async/panda/__init__.py @@ -0,0 +1,21 @@ +from .panda import ( + PandA, + PcapBlock, + PulseBlock, + PVIEntry, + SeqBlock, + SeqTable, + SeqTrigger, + pvi, +) + +__all__ = [ + "PandA", + "PcapBlock", + "PulseBlock", + "PVIEntry", + "SeqBlock", + "SeqTable", + "SeqTrigger", + "pvi", +] diff --git a/src/ophyd_async/panda/panda.py b/src/ophyd_async/panda/panda.py index 05230ef039..bf130b532b 100644 --- a/src/ophyd_async/panda/panda.py +++ b/src/ophyd_async/panda/panda.py @@ -22,16 +22,23 @@ import numpy.typing as npt from p4p.client.thread import Context -from ophyd_async.core.backends import SignalBackend, SimSignalBackend -from ophyd_async.core.devices import Device, DeviceVector -from ophyd_async.core.signal import Signal, SignalR, SignalRW, SignalX +from ophyd_async.core import ( + Device, + DeviceVector, + Signal, + SignalBackend, + SignalR, + SignalRW, + SignalX, + SimSignalBackend, +) from ophyd_async.epics.signal import ( epics_signal_r, epics_signal_rw, epics_signal_w, epics_signal_x, + pvi_get, ) -from ophyd_async.epics.signal.pvi_get import pvi_get class PulseBlock(Device): @@ -91,7 +98,7 @@ class PVIEntry(TypedDict, total=False): x: str -def block_name_number(block_name: str) -> Tuple[str, Optional[int]]: +def _block_name_number(block_name: str) -> Tuple[str, Optional[int]]: """Maps a panda block name to a block and number. There are exceptions to this rule; some blocks like pcap do not contain numbers. @@ -292,7 +299,7 @@ async def connect(self, sim=False) -> None: if pvi_info: pvi_info = cast(Dict[str, PVIEntry], pvi_info) for block_name, block_pvi in pvi_info.items(): - name, num = block_name_number(block_name) + name, num = _block_name_number(block_name) if name in hints: block = await self._make_block(name, num, block_pvi["d"]) diff --git a/tests/conftest.py b/tests/conftest.py index 68c7a47484..ec496795fd 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -86,18 +86,3 @@ async def inner_coroutine(): raise ValueError() return inner_coroutine - - -class DocHolder: - def __init__(self): - self.names = [] - self.docs = [] - - def append(self, name, doc): - self.names.append(name) - self.docs.append(doc) - - -@pytest.fixture -def doc_holder() -> DocHolder: - return DocHolder() diff --git a/tests/core/backends/test_sim.py b/tests/core/_device/_backend/test_sim.py similarity index 96% rename from tests/core/backends/test_sim.py rename to tests/core/_device/_backend/test_sim.py index 708792f260..a7459b9429 100644 --- a/tests/core/backends/test_sim.py +++ b/tests/core/_device/_backend/test_sim.py @@ -8,9 +8,7 @@ import pytest from bluesky.protocols import Reading -from ophyd_async.core.backends import SignalBackend, SimSignalBackend -from ophyd_async.core.signal import Signal -from ophyd_async.core.utils import T +from ophyd_async.core import Signal, SignalBackend, SimSignalBackend, T class MyEnum(str, Enum): diff --git a/tests/core/signals/test_signal.py b/tests/core/_device/_signal/test_signal.py similarity index 97% rename from tests/core/signals/test_signal.py rename to tests/core/_device/_signal/test_signal.py index 21ded8fb2b..2309f2396d 100644 --- a/tests/core/signals/test_signal.py +++ b/tests/core/_device/_signal/test_signal.py @@ -4,10 +4,10 @@ import pytest -from ophyd_async.core.backends import SimSignalBackend -from ophyd_async.core.signal import ( +from ophyd_async.core import ( Signal, SignalRW, + SimSignalBackend, set_and_wait_for_value, set_sim_put_proceeds, set_sim_value, diff --git a/tests/core/devices/test_device.py b/tests/core/_device/test_device.py similarity index 93% rename from tests/core/devices/test_device.py rename to tests/core/_device/test_device.py index 2c3058bdc1..7e9c280d75 100644 --- a/tests/core/devices/test_device.py +++ b/tests/core/_device/test_device.py @@ -3,9 +3,13 @@ import pytest -from ophyd_async.core.devices import Device, DeviceVector, get_device_children -from ophyd_async.core.devices.device_collector import DeviceCollector -from ophyd_async.core.utils import wait_for_connection +from ophyd_async.core import ( + Device, + DeviceCollector, + DeviceVector, + get_device_children, + wait_for_connection, +) class DummyBaseDevice(Device): diff --git a/tests/core/_device/test_device_collector.py b/tests/core/_device/test_device_collector.py new file mode 100644 index 0000000000..65c1cf9997 --- /dev/null +++ b/tests/core/_device/test_device_collector.py @@ -0,0 +1,14 @@ +import pytest + +from ophyd_async.core import Device, DeviceCollector + + +class Dummy(Device): + def connect(self, sim: bool = False): + raise AttributeError() + + +def test_device_collector_propagates_error(RE): + with pytest.raises(AttributeError): + with DeviceCollector(): + _ = Dummy("somename") diff --git a/tests/core/test_async_status.py b/tests/core/test_async_status.py index cfd3c15707..35b074bb2c 100644 --- a/tests/core/test_async_status.py +++ b/tests/core/test_async_status.py @@ -7,8 +7,7 @@ from bluesky.protocols import Movable, Status from bluesky.utils import FailedStatus -from ophyd_async.core.async_status import AsyncStatus -from ophyd_async.core.devices import Device +from ophyd_async.core import AsyncStatus, Device async def test_async_status_success(): @@ -131,3 +130,9 @@ async def test_status_propogates_traceback_under_RE(RE) -> None: assert expected_call_stack == [ x.name for x in traceback.extract_tb(exception.__traceback__) ] + + +async def test_async_status_exception_timeout(): + st = AsyncStatus(asyncio.sleep(0.1)) + with pytest.raises(Exception): + st.exception(timeout=1.0) diff --git a/tests/epics/areadetector/test_hdf_streamer_det.py b/tests/epics/areadetector/test_hdf_streamer_det.py index 461754f9cc..70edde20fd 100644 --- a/tests/epics/areadetector/test_hdf_streamer_det.py +++ b/tests/epics/areadetector/test_hdf_streamer_det.py @@ -7,8 +7,7 @@ import bluesky.preprocessors as bpp import pytest -from ophyd_async.core.devices.device_collector import DeviceCollector -from ophyd_async.core.signal import set_sim_put_proceeds, set_sim_value +from ophyd_async.core import DeviceCollector, set_sim_put_proceeds, set_sim_value from ophyd_async.epics.areadetector import ( ADDriver, FileWriteMode, @@ -19,6 +18,21 @@ ) +class DocHolder: + def __init__(self): + self.names = [] + self.docs = [] + + def append(self, name, doc): + self.names.append(name) + self.docs.append(doc) + + +@pytest.fixture +def doc_holder(): + return DocHolder() + + @pytest.fixture async def hdf_streamer_dets(): dp = TmpDirectoryProvider() @@ -52,9 +66,9 @@ async def hdf_streamer_dets(): async def test_hdf_streamer_dets_step( - hdf_streamer_dets: List[HDFStreamerDet], RE, doc_holder + hdf_streamer_dets: List[HDFStreamerDet], RE, doc_holder: DocHolder ): - RE(bp.count(hdf_streamer_dets), doc_holder.append) # type: ignore + RE(bp.count(hdf_streamer_dets), doc_holder.append) drv = hdf_streamer_dets[0].drv assert 1 == await drv.acquire.get_value() @@ -67,7 +81,7 @@ async def test_hdf_streamer_dets_step( assert 0 == await hdf.num_capture.get_value() assert FileWriteMode.stream == await hdf.file_write_mode.get_value() - assert doc_holder.names == [ # type: ignore + assert doc_holder.names == [ "start", "descriptor", "stream_resource", @@ -77,7 +91,7 @@ async def test_hdf_streamer_dets_step( "event", "stop", ] - _, descriptor, sra, sda, srb, sdb, event, _ = doc_holder.docs # type: ignore + _, descriptor, sra, sda, srb, sdb, event, _ = doc_holder.docs assert descriptor["configuration"]["deta"]["data"]["deta-drv-acquire_time"] == 0.8 assert descriptor["configuration"]["detb"]["data"]["detb-drv-acquire_time"] == 1.8 assert descriptor["data_keys"]["deta"]["shape"] == [768, 1024] @@ -95,7 +109,7 @@ async def test_hdf_streamer_dets_step( # TODO: write test where they are in the same stream after # https://github.com/bluesky/bluesky/issues/1558 async def test_hdf_streamer_dets_fly_different_streams( - hdf_streamer_dets: List[HDFStreamerDet], RE, doc_holder + hdf_streamer_dets: List[HDFStreamerDet], RE, doc_holder: DocHolder ): deta, detb = hdf_streamer_dets @@ -122,10 +136,10 @@ def fly_det(num: int): yield from bps.collect(det, stream=True, return_payload=False) yield from bps.wait(group="complete") - RE(fly_det(5), doc_holder.append) # type: ignore + RE(fly_det(5), doc_holder.append) # TODO: stream_* will come after descriptor soon - assert doc_holder.names == [ # type: ignore + assert doc_holder.names == [ "start", "stream_resource", "stream_datum", @@ -147,7 +161,7 @@ def fly_det(num: int): assert 0 == await hdf.num_capture.get_value() assert FileWriteMode.stream == await hdf.file_write_mode.get_value() - _, sra, sda, descriptora, srb, sdb, descriptorb, _ = doc_holder.docs # type: ignore + _, sra, sda, descriptora, srb, sdb, descriptorb, _ = doc_holder.docs assert descriptora["configuration"]["deta"]["data"]["deta-drv-acquire_time"] == 0.8 assert descriptorb["configuration"]["detb"]["data"]["detb-drv-acquire_time"] == 1.8 diff --git a/tests/epics/areadetector/test_single_trigger_det.py b/tests/epics/areadetector/test_single_trigger_det.py index 85c8252042..2545a8e1d0 100644 --- a/tests/epics/areadetector/test_single_trigger_det.py +++ b/tests/epics/areadetector/test_single_trigger_det.py @@ -1,8 +1,7 @@ import bluesky.plans as bp import pytest -from ophyd_async.core.devices.device_collector import DeviceCollector -from ophyd_async.core.signal import set_sim_value +from ophyd_async.core import DeviceCollector, set_sim_value from ophyd_async.epics.areadetector import ( ADDriver, ImageMode, @@ -11,6 +10,21 @@ ) +class DocHolder: + def __init__(self): + self.names = [] + self.docs = [] + + def append(self, name, doc): + self.names.append(name) + self.docs.append(doc) + + +@pytest.fixture +def doc_holder(): + return DocHolder() + + @pytest.fixture async def single_trigger_det(): async with DeviceCollector(sim=True): @@ -31,16 +45,18 @@ async def single_trigger_det(): yield det -async def test_single_trigger_det(single_trigger_det: SingleTriggerDet, RE, doc_holder): - RE(bp.count([single_trigger_det]), doc_holder.append) # type: ignore +async def test_single_trigger_det( + single_trigger_det: SingleTriggerDet, RE, doc_holder: DocHolder +): + RE(bp.count([single_trigger_det]), doc_holder.append) drv = single_trigger_det.drv assert 1 == await drv.acquire.get_value() assert ImageMode.single == await drv.image_mode.get_value() assert True is await drv.wait_for_plugins.get_value() - assert doc_holder.names == ["start", "descriptor", "event", "stop"] # type: ignore - _, descriptor, event, _ = doc_holder.docs # type: ignore + assert doc_holder.names == ["start", "descriptor", "event", "stop"] + _, descriptor, event, _ = doc_holder.docs assert descriptor["configuration"]["det"]["data"]["det-drv-acquire_time"] == 0.5 assert ( descriptor["data_keys"]["det-stats-unique_id"]["source"] diff --git a/tests/epics/motion/test_motor.py b/tests/epics/motion/test_motor.py index a01c7a1a17..7706099295 100644 --- a/tests/epics/motion/test_motor.py +++ b/tests/epics/motion/test_motor.py @@ -5,8 +5,7 @@ import pytest from bluesky.protocols import Reading -from ophyd_async.core.devices.device_collector import DeviceCollector -from ophyd_async.core.signal import set_sim_put_proceeds, set_sim_value +from ophyd_async.core import DeviceCollector, set_sim_put_proceeds, set_sim_value from ophyd_async.epics.motion import motor # Long enough for multiple asyncio event loop cycles to run so diff --git a/tests/core/test_epicsdemo.py b/tests/epics/test_demo.py similarity index 86% rename from tests/core/test_epicsdemo.py rename to tests/epics/test_demo.py index 740d4c27f9..8914758798 100644 --- a/tests/core/test_epicsdemo.py +++ b/tests/epics/test_demo.py @@ -8,10 +8,10 @@ from ophyd_async.core import ( DeviceCollector, NotConnected, - epicsdemo, set_sim_callback, set_sim_value, ) +from ophyd_async.epics import demo # Long enough for multiple asyncio event loop cycles to run so # all the tasks have a chance to run @@ -21,7 +21,7 @@ @pytest.fixture async def sim_mover(): async with DeviceCollector(sim=True): - sim_mover = epicsdemo.Mover("BLxxI-MO-TABLE-01:X:") + sim_mover = demo.Mover("BLxxI-MO-TABLE-01:X:") # Signals connected here assert sim_mover.name == "sim_mover" @@ -34,14 +34,14 @@ async def sim_mover(): @pytest.fixture async def sim_sensor(): async with DeviceCollector(sim=True): - sim_sensor = epicsdemo.Sensor("SIM:SENSOR:") + sim_sensor = demo.Sensor("SIM:SENSOR:") # Signals connected here assert sim_sensor.name == "sim_sensor" yield sim_sensor -async def test_mover_moving_well(sim_mover: epicsdemo.Mover) -> None: +async def test_mover_moving_well(sim_mover: demo.Mover) -> None: s = sim_mover.set(0.55) watcher = Mock() s.watch(watcher) @@ -85,7 +85,7 @@ async def test_mover_moving_well(sim_mover: epicsdemo.Mover) -> None: done2.assert_called_once_with(s) -async def test_mover_stopped(sim_mover: epicsdemo.Mover): +async def test_mover_stopped(sim_mover: demo.Mover): callbacks = [] set_sim_callback(sim_mover.stop_, lambda r, v: callbacks.append(v)) @@ -94,7 +94,7 @@ async def test_mover_stopped(sim_mover: epicsdemo.Mover): assert callbacks == [None, None] -async def test_read_mover(sim_mover: epicsdemo.Mover): +async def test_read_mover(sim_mover: demo.Mover): await sim_mover.stage() assert (await sim_mover.read())["sim_mover"]["value"] == 0.0 assert (await sim_mover.describe())["sim_mover"][ @@ -111,7 +111,7 @@ async def test_read_mover(sim_mover: epicsdemo.Mover): assert await sim_mover.describe() -async def test_set_velocity(sim_mover: epicsdemo.Mover) -> None: +async def test_set_velocity(sim_mover: demo.Mover) -> None: v = sim_mover.velocity assert (await v.describe())["sim_mover-velocity"][ "source" @@ -130,15 +130,15 @@ async def test_set_velocity(sim_mover: epicsdemo.Mover) -> None: async def test_mover_disconncted(): with pytest.raises(NotConnected, match="Not all Devices connected"): async with DeviceCollector(timeout=0.1): - m = epicsdemo.Mover("ca://PRE:", name="mover") + m = demo.Mover("ca://PRE:", name="mover") assert m.name == "mover" async def test_sensor_disconnected(): - with patch("ophyd_async.core.devices.device_collector.logging") as mock_logging: + with patch("ophyd_async.core._device.device_collector.logging") as mock_logging: with pytest.raises(NotConnected, match="Not all Devices connected"): async with DeviceCollector(timeout=0.1): - s = epicsdemo.Sensor("ca://PRE:", name="sensor") + s = demo.Sensor("ca://PRE:", name="sensor") mock_logging.error.assert_called_once_with( """\ 1 Devices did not connect: @@ -149,7 +149,7 @@ async def test_sensor_disconnected(): assert s.name == "sensor" -async def test_read_sensor(sim_sensor: epicsdemo.Sensor): +async def test_read_sensor(sim_sensor: demo.Sensor): sim_sensor.stage() assert (await sim_sensor.read())["sim_sensor-value"]["value"] == 0 assert (await sim_sensor.describe())["sim_sensor-value"][ @@ -157,19 +157,19 @@ async def test_read_sensor(sim_sensor: epicsdemo.Sensor): ] == "sim://SIM:SENSOR:Value" assert (await sim_sensor.read_configuration())["sim_sensor-mode"][ "value" - ] == epicsdemo.EnergyMode.low + ] == demo.EnergyMode.low desc = (await sim_sensor.describe_configuration())["sim_sensor-mode"] assert desc["dtype"] == "string" assert desc["choices"] == ["Low Energy", "High Energy"] # type: ignore - set_sim_value(sim_sensor.mode, epicsdemo.EnergyMode.high) + set_sim_value(sim_sensor.mode, demo.EnergyMode.high) assert (await sim_sensor.read_configuration())["sim_sensor-mode"][ "value" - ] == epicsdemo.EnergyMode.high + ] == demo.EnergyMode.high await sim_sensor.unstage() async def test_assembly_renaming() -> None: - thing = epicsdemo.SampleStage("PRE") + thing = demo.SampleStage("PRE") await thing.connect(sim=True) assert thing.x.name == "" assert thing.x.velocity.name == "" @@ -182,7 +182,7 @@ async def test_assembly_renaming() -> None: assert thing.x.stop_.name == "foo-x-stop" -def test_mover_in_re(sim_mover: epicsdemo.Mover, RE) -> None: +def test_mover_in_re(sim_mover: demo.Mover, RE) -> None: sim_mover.move(0) def my_plan(): diff --git a/tests/core/signals/test_records.db b/tests/epics/test_records.db similarity index 100% rename from tests/core/signals/test_records.db rename to tests/epics/test_records.db diff --git a/tests/core/signals/test_epics.py b/tests/epics/test_signals.py similarity index 99% rename from tests/core/signals/test_epics.py rename to tests/epics/test_signals.py index add157b69c..fc61ac39f1 100644 --- a/tests/core/signals/test_epics.py +++ b/tests/epics/test_signals.py @@ -17,7 +17,7 @@ from bluesky.protocols import Reading from ophyd_async.core import NotConnected, SignalBackend, T, get_dtype -from ophyd_async.epics.signal.epics_transport import EpicsTransport +from ophyd_async.epics.signal._epics_transport import EpicsTransport from ophyd_async.epics.signal.signal import _make_backend RECORDS = str(Path(__file__).parent / "test_records.db") diff --git a/tests/panda/test_panda.py b/tests/panda/test_panda.py index 20b022dda5..630385dc83 100644 --- a/tests/panda/test_panda.py +++ b/tests/panda/test_panda.py @@ -5,8 +5,8 @@ import numpy as np import pytest -from ophyd_async.core.devices.device_collector import DeviceCollector -from ophyd_async.panda.panda import PandA, PVIEntry, SeqTable, SeqTrigger, pvi +from ophyd_async.core import DeviceCollector +from ophyd_async.panda import PandA, PVIEntry, SeqTable, SeqTrigger, pvi class DummyDict: