Skip to content

Commit

Permalink
Merge branch 'main' into 42_rename_and_add_motor_fields
Browse files Browse the repository at this point in the history
  • Loading branch information
coretl authored Apr 15, 2024
2 parents 861fcf4 + 1924fd9 commit 87b7ea7
Show file tree
Hide file tree
Showing 45 changed files with 1,702 additions and 422 deletions.
4 changes: 2 additions & 2 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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.9 as build
FROM python:3.10 as build

ARG PIP_OPTIONS

Expand All @@ -24,7 +24,7 @@ WORKDIR /context
# install python package into /venv
RUN pip install ${PIP_OPTIONS}

FROM python:3.9-slim as runtime
FROM python:3.10-slim as runtime

# Add apt-get system dependecies for runtime here if needed

Expand Down
85 changes: 41 additions & 44 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,47 +1,44 @@
// For format details, see https://containers.dev/implementors/json_reference/
{
"name": "Python 3 Developer Container",
"build": {
"dockerfile": "Dockerfile",
"target": "build",
// Only upgrade pip, we will install the project below
"args": {
"PIP_OPTIONS": "--upgrade pip"
},
},
"remoteEnv": {
"DISPLAY": "${localEnv:DISPLAY}"
},
// Set *default* container specific settings.json values on container create.
"settings": {
"python.defaultInterpreterPath": "/venv/bin/python"
},
"customizations": {
"vscode": {
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"ms-python.python",
"tamasfe.even-better-toml",
"redhat.vscode-yaml",
"ryanluker.vscode-coverage-gutters"
]
}
},
// Make sure the files we are mapping into the container exist on the host
"initializeCommand": "bash -c 'for i in $HOME/.inputrc; do [ -f $i ] || touch $i; done'",
"runArgs": [
"--net=host",
"--security-opt=label=type:container_runtime_t"
],
"mounts": [
"source=${localEnv:HOME}/.ssh,target=/root/.ssh,type=bind",
"source=${localEnv:HOME}/.inputrc,target=/root/.inputrc,type=bind",
// map in home directory - not strictly necessary but useful
"source=${localEnv:HOME},target=${localEnv:HOME},type=bind,consistency=cached"
],
// make the workspace folder the same inside and outside of the container
"workspaceMount": "source=${localWorkspaceFolder},target=${localWorkspaceFolder},type=bind",
"workspaceFolder": "${localWorkspaceFolder}",
// After the container is created, install the python project in editable form
"postCreateCommand": "pip install -e .[dev] --config-settings editable_mode=compat"
"name": "Python 3 Developer Container",
"build": {
"dockerfile": "Dockerfile",
"target": "build",
// Only upgrade pip, we will install the project below
"args": {
"PIP_OPTIONS": "--upgrade pip"
}
},
"remoteEnv": {
"DISPLAY": "${localEnv:DISPLAY}"
},
"customizations": {
"vscode": {
// Set *default* container specific settings.json values on container create.
// "settings": {
// "python.defaultInterpreterPath": "/venv/bin/python"
// },
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"ms-python.python",
"tamasfe.even-better-toml",
"redhat.vscode-yaml",
"ryanluker.vscode-coverage-gutters"
]
}
},
// Make sure the files we are mapping into the container exist on the host
"initializeCommand": "bash -c 'for i in $HOME/.inputrc; do [ -f $i ] || touch $i; done'",
"runArgs": ["--net=host", "--security-opt=label=type:container_runtime_t"],
"mounts": [
"source=${localEnv:HOME}/.ssh,target=/root/.ssh,type=bind",
"source=${localEnv:HOME}/.inputrc,target=/root/.inputrc,type=bind",
// map in home directory - not strictly necessary but useful
"source=${localEnv:HOME},target=${localEnv:HOME},type=bind,consistency=cached"
],
// make the workspace folder the same inside and outside of the container
"workspaceMount": "source=${localWorkspaceFolder},target=${localWorkspaceFolder},type=bind",
"workspaceFolder": "${localWorkspaceFolder}",
// After the container is created, install the python project in editable form
"postCreateCommand": "pip install -e .[dev] --config-settings editable_mode=compat"
}
2 changes: 1 addition & 1 deletion .github/actions/install_requirements/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ inputs:
required: true
python_version:
description: Python version to install
default: "3.9"
default: "3.10"

runs:
using: composite
Expand Down
16 changes: 9 additions & 7 deletions .github/workflows/code.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Install python packages
uses: ./.github/actions/install_requirements
Expand All @@ -29,12 +29,12 @@ jobs:
fail-fast: false
matrix:
os: ["ubuntu-latest"] # can add windows-latest, macos-latest
python: ["3.10", "3.11"]
python: ["3.10","3.11"] # 3.12 should be added when p4p is updated
install: ["-e .[dev]"]
# Make one version be non-editable to test both paths of version code
include:
- os: "ubuntu-latest"
python: "3.9"
python: "3.10"
install: ".[dev]"

runs-on: ${{ matrix.os }}
Expand All @@ -44,7 +44,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
# Need this to get version number from last tag
fetch-depth: 0
Expand All @@ -63,18 +63,20 @@ jobs:
run: tox -e pytest

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v4
with:
name: ${{ matrix.python }}/${{ matrix.os }}
files: cov.xml
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

dist:
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository
runs-on: "ubuntu-latest"

steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
# Need this to get version number from last tag
fetch-depth: 0
Expand Down Expand Up @@ -125,7 +127,7 @@ jobs:
- name: Github Release
# 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: softprops/action-gh-release@1e07f4398721186383de40550babbdf2b84acfc5 # v0.1.14
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v0.1.15
with:
prerelease: ${{ contains(github.ref_name, 'a') || contains(github.ref_name, 'b') || contains(github.ref_name, 'rc') }}
files: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
run: sleep 60

- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
# Need this to get version number from last tag
fetch-depth: 0
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docs_clean.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
ref: gh-pages

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/linkcheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Install python packages
uses: ./.github/actions/install_requirements
Expand Down
2 changes: 1 addition & 1 deletion docs/developer/how-to/pin-requirements.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.9.txt`` in this example.
i.e. ``requirements-test-ubuntu-latest-3.10.txt`` in this example.

Applying the lock file
----------------------
Expand Down
2 changes: 1 addition & 1 deletion docs/developer/tutorials/dev-install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Install dependencies
--------------------

You can choose to either develop on the host machine using a `venv` (which
requires python 3.9 or later) or to run in a container under `VSCode
requires python 3.10 or later) or to run in a container under `VSCode
<https://code.visualstudio.com/>`_

.. tab-set::
Expand Down
2 changes: 1 addition & 1 deletion docs/user/tutorials/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Installation
Check your version of python
----------------------------

You will need python 3.9 or later. You can check your version of python by
You will need python 3.10 or later. You can check your version of python by
typing into a terminal::

$ python3 --version
Expand Down
8 changes: 3 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ name = "ophyd-async"
classifiers = [
"Development Status :: 3 - Alpha",
"License :: OSI Approved :: BSD License",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
]
Expand All @@ -19,15 +18,15 @@ dependencies = [
"packaging",
"pint",
"bluesky>=1.13.0a3",
"event-model",
"event-model<1.21.0",
"p4p",
"pyyaml",
]

dynamic = ["version"]
license.file = "LICENSE"
readme = "README.rst"
requires-python = ">=3.9"
requires-python = ">=3.10"

[project.optional-dependencies]
ca = ["aioca>=1.6"]
Expand All @@ -53,8 +52,7 @@ dev = [
"pre-commit",
"pydata-sphinx-theme>=0.12",
"pyepics>=3.4.2",
"pyside6",
"pyside6-stubs",
"pyside6==6.6.2",
"pytest",
"pytest-asyncio",
"pytest-cov",
Expand Down
10 changes: 8 additions & 2 deletions src/ophyd_async/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@
StaticDirectoryProvider,
)
from .async_status import AsyncStatus
from .detector import DetectorControl, DetectorTrigger, DetectorWriter, StandardDetector
from .detector import (
DetectorControl,
DetectorTrigger,
DetectorWriter,
StandardDetector,
TriggerInfo,
)
from .device import Device, DeviceCollector, DeviceVector
from .device_save_loader import (
get_signal_values,
Expand All @@ -17,7 +23,7 @@
set_signal_values,
walk_rw_signals,
)
from .flyer import HardwareTriggeredFlyable, TriggerInfo, TriggerLogic
from .flyer import HardwareTriggeredFlyable, TriggerLogic
from .signal import (
Signal,
SignalR,
Expand Down
29 changes: 10 additions & 19 deletions src/ophyd_async/core/flyer.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
from abc import ABC, abstractmethod
from typing import Dict, Generic, Optional, Sequence, TypeVar
from typing import Dict, Generic, Sequence, TypeVar

from bluesky.protocols import Descriptor, Flyable, Preparable, Reading, Stageable

from .async_status import AsyncStatus
from .detector import TriggerInfo
from .device import Device
from .signal import SignalR
from .utils import merge_gathered_dicts
Expand All @@ -13,18 +12,18 @@


class TriggerLogic(ABC, Generic[T]):
@abstractmethod
def trigger_info(self, value: T) -> TriggerInfo:
"""Return info about triggers that will be produced for a given value"""

@abstractmethod
async def prepare(self, value: T):
"""Move to the start of the flyscan"""

@abstractmethod
async def start(self):
async def kickoff(self):
"""Start the flyscan"""

@abstractmethod
async def complete(self):
"""Block until the flyscan is done"""

@abstractmethod
async def stop(self):
"""Stop flying and wait everything to be stopped"""
Expand All @@ -45,19 +44,12 @@ def __init__(
):
self._trigger_logic = trigger_logic
self._configuration_signals = tuple(configuration_signals)
self._describe: Dict[str, Descriptor] = {}
self._fly_status: Optional[AsyncStatus] = None
self._trigger_info: Optional[TriggerInfo] = None
super().__init__(name=name)

@property
def trigger_logic(self) -> TriggerLogic[T]:
return self._trigger_logic

@property
def trigger_info(self) -> Optional[TriggerInfo]:
return self._trigger_info

@AsyncStatus.wrap
async def stage(self) -> None:
await self.unstage()
Expand All @@ -71,17 +63,16 @@ def prepare(self, value: T) -> AsyncStatus:
return AsyncStatus(self._prepare(value))

async def _prepare(self, value: T) -> None:
self._trigger_info = self._trigger_logic.trigger_info(value)
# Move to start and setup the flyscan
await self._trigger_logic.prepare(value)

@AsyncStatus.wrap
async def kickoff(self) -> None:
self._fly_status = AsyncStatus(self._trigger_logic.start())
await self._trigger_logic.kickoff()

def complete(self) -> AsyncStatus:
assert self._fly_status, "Kickoff not run"
return self._fly_status
@AsyncStatus.wrap
async def complete(self) -> None:
await self._trigger_logic.complete()

async def describe_configuration(self) -> Dict[str, Descriptor]:
return await merge_gathered_dicts(
Expand Down
17 changes: 17 additions & 0 deletions src/ophyd_async/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,20 @@ async def merge_gathered_dicts(

async def gather_list(coros: Iterable[Awaitable[T]]) -> List[T]:
return await asyncio.gather(*coros)


def in_micros(t: float) -> int:
"""
Converts between a positive number of seconds and an equivalent
number of microseconds.
Args:
t (float): A time in seconds
Raises:
ValueError: if t < 0
Returns:
t (int): A time in microseconds, rounded up to the nearest whole microsecond,
"""
if t < 0:
raise ValueError(f"Expected a positive time in seconds, got {t!r}")
return int(np.ceil(t * 1e6))
Loading

0 comments on commit 87b7ea7

Please sign in to comment.