pyobs-fli 2.0.0.dev9__tar.gz → 2.0.0.dev10__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/.github/dependabot.yml +5 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/.github/workflows/pypi.yml +1 -1
- pyobs_fli-2.0.0.dev10/.github/workflows/pyrefly.yml +26 -0
- pyobs_fli-2.0.0.dev10/.github/workflows/pytest.yml +28 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/PKG-INFO +1 -1
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/pyobs_fli/flicamera.py +1 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/pyproject.toml +6 -1
- pyobs_fli-2.0.0.dev10/tests/test_flicamera.py +91 -0
- pyobs_fli-2.0.0.dev10/tests/test_flifilterwheel.py +79 -0
- pyobs_fli-2.0.0.dev10/tests/test_import.py +29 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/uv.lock +61 -1
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/.github/workflows/ruff.yml +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/.pre-commit-config.yaml +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/.readthedocs.yml +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/CHANGELOG.rst +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/CMakeLists.txt +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/LICENSE +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/README.md +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/docs/Makefile +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/docs/make.bat +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/docs/requirements.txt +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/docs/source/_static/pyobs.gif +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/docs/source/conf.py +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/docs/source/index.rst +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/Makefile +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/docxx.sty +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/libfli-camera-parport.c +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/libfli-camera-parport.h +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/libfli-camera-usb.c +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/libfli-camera-usb.h +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/libfli-camera.c +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/libfli-camera.h +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/libfli-debug.h +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/libfli-filter-focuser.c +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/libfli-filter-focuser.h +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/libfli-libfli.h +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/libfli-mem.c +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/libfli-mem.h +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/libfli-raw.c +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/libfli-raw.h +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/libfli.c +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/libfli.dxx +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/libfli.h +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/unix/bsd/libfli-usb-sys.c +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/unix/libfli-debug.c +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/unix/libfli-parport.h +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/unix/libfli-serial.c +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/unix/libfli-serial.h +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/unix/libfli-sys.c +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/unix/libfli-sys.h +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/unix/libfli-usb.c +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/unix/libfli-usb.h +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/unix/linux/fli_ioctl.h +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/unix/linux/fliusb_ioctl.h +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/unix/linux/libfli-parport.c +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/unix/linux/libfli-usb-sys.c +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/unix/osx/libfli-usb-sys.c +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/unix/osx/libfli-usb-sys.h +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/windows/libfli-debug.c +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/windows/libfli-parport.h +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/windows/libfli-serial.c +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/windows/libfli-serial.h +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/windows/libfli-sys.h +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/windows/libfli-usb.c +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/windows/libfli-usb.h +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/windows/libfli-windows-parport.c +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/windows/libfli-windows.c +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/windows/libfli.def +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/windows/libfli.rc +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/windows/libfli.sln +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/windows/libfli.vcproj +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/windows/libfli64.def +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/lib/windows/resource.h +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/poetry.lock +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/pyobs_fli/__init__.py +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/pyobs_fli/flibase.py +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/pyobs_fli/flidriver.pyx +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/pyobs_fli/flifilterwheel.py +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/pyobs_fli/libfli.pxd +0 -0
- {pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/specs/plans/2026-08-16-nogil-fli-driver-calls.md +0 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: pyrefly
|
|
2
|
+
on: push
|
|
3
|
+
|
|
4
|
+
jobs:
|
|
5
|
+
pyrefly:
|
|
6
|
+
runs-on: ubuntu-latest
|
|
7
|
+
timeout-minutes: 10
|
|
8
|
+
|
|
9
|
+
steps:
|
|
10
|
+
- name: Check out repository code
|
|
11
|
+
uses: actions/checkout@v4
|
|
12
|
+
|
|
13
|
+
- name: Set up Python
|
|
14
|
+
uses: astral-sh/setup-uv@v5
|
|
15
|
+
with:
|
|
16
|
+
enable-cache: true
|
|
17
|
+
python-version: "3.13"
|
|
18
|
+
|
|
19
|
+
- name: Install system dependencies
|
|
20
|
+
run: sudo apt-get install -y libcfitsio-dev
|
|
21
|
+
|
|
22
|
+
- name: Install packages
|
|
23
|
+
run: uv sync --all-extras --dev
|
|
24
|
+
|
|
25
|
+
- name: Run pyrefly
|
|
26
|
+
run: uv run pyrefly check
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: PyTest
|
|
2
|
+
on: push
|
|
3
|
+
|
|
4
|
+
jobs:
|
|
5
|
+
test:
|
|
6
|
+
runs-on: ubuntu-latest
|
|
7
|
+
timeout-minutes: 10
|
|
8
|
+
|
|
9
|
+
steps:
|
|
10
|
+
- name: Check out repository code
|
|
11
|
+
uses: actions/checkout@v4
|
|
12
|
+
|
|
13
|
+
- name: Set up Python
|
|
14
|
+
uses: astral-sh/setup-uv@v5
|
|
15
|
+
with:
|
|
16
|
+
enable-cache: true
|
|
17
|
+
python-version: "3.13"
|
|
18
|
+
|
|
19
|
+
- name: Install system dependencies
|
|
20
|
+
run: sudo apt-get install -y libcfitsio-dev
|
|
21
|
+
|
|
22
|
+
- name: Install packages
|
|
23
|
+
run: uv sync --all-extras --dev
|
|
24
|
+
|
|
25
|
+
- name: Run tests
|
|
26
|
+
run: uv run pytest tests
|
|
27
|
+
env:
|
|
28
|
+
CI: true
|
|
@@ -92,6 +92,7 @@ class FliCamera(FliBaseMixin, BaseCamera, ICamera, IWindow, IBinning, ICooling,
|
|
|
92
92
|
),
|
|
93
93
|
)
|
|
94
94
|
await self.comm.set_state(IBinning, BinningState(x=self._binning[0], y=self._binning[1]))
|
|
95
|
+
await self.comm.set_state(ITemperatures, TemperaturesState())
|
|
95
96
|
|
|
96
97
|
async def close(self) -> None:
|
|
97
98
|
"""Close the module."""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "pyobs-fli"
|
|
3
|
-
version = "2.0.0.
|
|
3
|
+
version = "2.0.0.dev10"
|
|
4
4
|
description = "pyobs module for FLI cameras"
|
|
5
5
|
authors = [{ name = "Tim-Oliver Husser", email = "thusser@uni-goettingen.de" }]
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -17,6 +17,8 @@ dev = [
|
|
|
17
17
|
"pre-commit>=4.2.0,<5",
|
|
18
18
|
"ruff>=0.9.0",
|
|
19
19
|
"pyrefly>=1.1.1",
|
|
20
|
+
"pytest>=8.0.0",
|
|
21
|
+
"pytest-asyncio>=0.24.0",
|
|
20
22
|
]
|
|
21
23
|
|
|
22
24
|
[tool.scikit-build]
|
|
@@ -49,3 +51,6 @@ select = ["E", "F", "W", "I", "UP", "G"]
|
|
|
49
51
|
[tool.pyrefly]
|
|
50
52
|
python-version = "3.11"
|
|
51
53
|
ignore-missing-imports = []
|
|
54
|
+
|
|
55
|
+
[tool.pytest.ini_options]
|
|
56
|
+
asyncio_mode = "strict"
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""Unit tests for the non-hardware logic in FliCamera: constructor defaults, the
|
|
2
|
+
window/binning setters, and the _run_blocking/_run_blocking_or_raise thread wrappers.
|
|
3
|
+
|
|
4
|
+
Hardware I/O (opening, exposing, reading out) is out of scope here.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import threading
|
|
9
|
+
from unittest.mock import AsyncMock
|
|
10
|
+
|
|
11
|
+
import pytest
|
|
12
|
+
from pyobs.interfaces import IBinning, IWindow
|
|
13
|
+
|
|
14
|
+
from pyobs_fli import FliCamera
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def test_constructor_defaults() -> None:
|
|
18
|
+
camera = FliCamera()
|
|
19
|
+
assert camera._temp_setpoint == -20.0
|
|
20
|
+
assert camera._cooling_enabled is False
|
|
21
|
+
assert camera._window == (0, 0, 0, 0)
|
|
22
|
+
assert camera._binning == (1, 1)
|
|
23
|
+
assert camera._driver is None
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@pytest.mark.asyncio
|
|
27
|
+
async def test_set_window() -> None:
|
|
28
|
+
camera = FliCamera()
|
|
29
|
+
camera.comm.set_state = AsyncMock() # type: ignore[method-assign]
|
|
30
|
+
|
|
31
|
+
await camera.set_window(10, 20, 100, 200)
|
|
32
|
+
|
|
33
|
+
assert camera._window == (10, 20, 100, 200)
|
|
34
|
+
assert camera.comm.set_state.await_args is not None
|
|
35
|
+
interface, state = camera.comm.set_state.await_args.args
|
|
36
|
+
assert interface is IWindow
|
|
37
|
+
assert (state.x, state.y, state.width, state.height) == (10, 20, 100, 200)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@pytest.mark.asyncio
|
|
41
|
+
async def test_set_binning() -> None:
|
|
42
|
+
camera = FliCamera()
|
|
43
|
+
camera.comm.set_state = AsyncMock() # type: ignore[method-assign]
|
|
44
|
+
|
|
45
|
+
await camera.set_binning(2, 3)
|
|
46
|
+
|
|
47
|
+
assert camera._binning == (2, 3)
|
|
48
|
+
assert camera.comm.set_state.await_args is not None
|
|
49
|
+
interface, state = camera.comm.set_state.await_args.args
|
|
50
|
+
assert interface is IBinning
|
|
51
|
+
assert (state.x, state.y) == (2, 3)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@pytest.mark.asyncio
|
|
55
|
+
async def test_run_blocking_runs_func_and_returns_true() -> None:
|
|
56
|
+
ran: list[bool] = []
|
|
57
|
+
|
|
58
|
+
def fast() -> None:
|
|
59
|
+
ran.append(True)
|
|
60
|
+
|
|
61
|
+
assert await FliCamera._run_blocking(fast) is True
|
|
62
|
+
assert ran == [True]
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@pytest.mark.asyncio
|
|
66
|
+
async def test_run_blocking_times_out() -> None:
|
|
67
|
+
done = threading.Event()
|
|
68
|
+
|
|
69
|
+
def slow() -> None:
|
|
70
|
+
done.wait()
|
|
71
|
+
|
|
72
|
+
assert await FliCamera._run_blocking(slow, timeout=0.01) is False
|
|
73
|
+
done.set()
|
|
74
|
+
await asyncio.sleep(0.05)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@pytest.mark.asyncio
|
|
78
|
+
async def test_run_blocking_or_raise_returns_value() -> None:
|
|
79
|
+
camera = FliCamera()
|
|
80
|
+
assert await camera._run_blocking_or_raise(lambda: 42) == 42
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@pytest.mark.asyncio
|
|
84
|
+
async def test_run_blocking_or_raise_reraises() -> None:
|
|
85
|
+
camera = FliCamera()
|
|
86
|
+
|
|
87
|
+
def boom() -> int:
|
|
88
|
+
raise ValueError("boom")
|
|
89
|
+
|
|
90
|
+
with pytest.raises(ValueError):
|
|
91
|
+
await camera._run_blocking_or_raise(boom)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""Unit tests for the non-hardware logic in FliFilterWheel: filter-name normalization,
|
|
2
|
+
position <-> name mapping, and set_filter position computation.
|
|
3
|
+
|
|
4
|
+
Hardware I/O (moving the wheel) is mocked out.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from unittest.mock import MagicMock
|
|
8
|
+
|
|
9
|
+
import pytest
|
|
10
|
+
from pyobs.utils import exceptions as exc
|
|
11
|
+
|
|
12
|
+
from pyobs_fli import FliFilterWheel
|
|
13
|
+
|
|
14
|
+
_TWO_WHEELS = [["A", "B", "C", "D", "E", "F", "G"], ["H", "I", "J"]]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def test_constructor_single_wheel() -> None:
|
|
18
|
+
wheel = FliFilterWheel(filter_names=["A", "B", "C"])
|
|
19
|
+
assert wheel._filter_names == [["A", "B", "C"]]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_constructor_two_wheels() -> None:
|
|
23
|
+
wheel = FliFilterWheel(filter_names=_TWO_WHEELS)
|
|
24
|
+
assert wheel._filter_names == _TWO_WHEELS
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@pytest.mark.parametrize(
|
|
28
|
+
("pos", "expected"),
|
|
29
|
+
[
|
|
30
|
+
(0, "A"),
|
|
31
|
+
(1, "G"),
|
|
32
|
+
(6, "B"),
|
|
33
|
+
(7, "H"),
|
|
34
|
+
(8, "G"),
|
|
35
|
+
(14, "I"),
|
|
36
|
+
],
|
|
37
|
+
)
|
|
38
|
+
def test_resolve_filter_name(pos: int, expected: str) -> None:
|
|
39
|
+
wheel = FliFilterWheel(filter_names=_TWO_WHEELS)
|
|
40
|
+
assert wheel._resolve_filter_name(pos) == expected
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@pytest.mark.asyncio
|
|
44
|
+
async def test_set_filter_first_wheel() -> None:
|
|
45
|
+
wheel = FliFilterWheel(filter_names=_TWO_WHEELS)
|
|
46
|
+
wheel._driver = MagicMock()
|
|
47
|
+
wheel._driver.set_filter_pos = MagicMock()
|
|
48
|
+
|
|
49
|
+
async def fake_run(func, timeout: float = 5.0) -> None:
|
|
50
|
+
func()
|
|
51
|
+
|
|
52
|
+
wheel._run_blocking_or_raise = fake_run # type: ignore[method-assign]
|
|
53
|
+
|
|
54
|
+
await wheel.set_filter("A")
|
|
55
|
+
wheel._driver.set_filter_pos.assert_called_once_with(0)
|
|
56
|
+
assert wheel._current_filter == "A"
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@pytest.mark.asyncio
|
|
60
|
+
async def test_set_filter_second_wheel() -> None:
|
|
61
|
+
wheel = FliFilterWheel(filter_names=_TWO_WHEELS)
|
|
62
|
+
wheel._driver = MagicMock()
|
|
63
|
+
wheel._driver.set_filter_pos = MagicMock()
|
|
64
|
+
|
|
65
|
+
async def fake_run(func, timeout: float = 5.0) -> None:
|
|
66
|
+
func()
|
|
67
|
+
|
|
68
|
+
wheel._run_blocking_or_raise = fake_run # type: ignore[method-assign]
|
|
69
|
+
|
|
70
|
+
await wheel.set_filter("H")
|
|
71
|
+
wheel._driver.set_filter_pos.assert_called_once_with(7)
|
|
72
|
+
assert wheel._current_filter == "H"
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@pytest.mark.asyncio
|
|
76
|
+
async def test_set_filter_unknown_filter() -> None:
|
|
77
|
+
wheel = FliFilterWheel(filter_names=_TWO_WHEELS)
|
|
78
|
+
with pytest.raises(exc.ModuleError):
|
|
79
|
+
await wheel.set_filter("nope")
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Smoke tests: import the drivers and instantiate them without hardware, asserting
|
|
2
|
+
the interfaces they claim.
|
|
3
|
+
|
|
4
|
+
The Cython extension (flidriver) is compiled from the vendored libfli C source during
|
|
5
|
+
install, but device enumeration/opening only happens inside open(), so instantiation
|
|
6
|
+
is safe with no FLI hardware attached.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from pyobs.interfaces import IAbortable, IBinning, ICamera, ICooling, IFilters, ITemperatures, IWindow
|
|
10
|
+
from pyobs.modules import Module
|
|
11
|
+
|
|
12
|
+
from pyobs_fli import FliCamera, FliFilterWheel
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_instantiate_camera() -> None:
|
|
16
|
+
camera = FliCamera()
|
|
17
|
+
assert isinstance(camera, Module)
|
|
18
|
+
assert isinstance(camera, ICamera)
|
|
19
|
+
assert isinstance(camera, IWindow)
|
|
20
|
+
assert isinstance(camera, IBinning)
|
|
21
|
+
assert isinstance(camera, ICooling)
|
|
22
|
+
assert isinstance(camera, ITemperatures)
|
|
23
|
+
assert isinstance(camera, IAbortable)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_instantiate_filter_wheel() -> None:
|
|
27
|
+
wheel = FliFilterWheel(filter_names=["A", "B", "C"])
|
|
28
|
+
assert isinstance(wheel, Module)
|
|
29
|
+
assert isinstance(wheel, IFilters)
|
|
@@ -865,6 +865,15 @@ wheels = [
|
|
|
865
865
|
{ url = "https://files.pythonhosted.org/packages/7f/ec/6b120b4a86f6fadc7ddb1d7c7cdcb15bcfb332deb022ab60df51bcd4494c/influxdb_client-1.50.0-py3-none-any.whl", hash = "sha256:f172975cf7f0c95bfe74f288b31273393b164d2c58a948de55497d9956ab49be", size = 746289, upload-time = "2026-01-23T09:39:37.377Z" },
|
|
866
866
|
]
|
|
867
867
|
|
|
868
|
+
[[package]]
|
|
869
|
+
name = "iniconfig"
|
|
870
|
+
version = "2.3.0"
|
|
871
|
+
source = { registry = "https://pypi.org/simple" }
|
|
872
|
+
sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
|
|
873
|
+
wheels = [
|
|
874
|
+
{ url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
|
|
875
|
+
]
|
|
876
|
+
|
|
868
877
|
[[package]]
|
|
869
878
|
name = "invoke"
|
|
870
879
|
version = "3.0.3"
|
|
@@ -1437,6 +1446,15 @@ wheels = [
|
|
|
1437
1446
|
{ url = "https://files.pythonhosted.org/packages/49/e2/4e6eee633809c376c024821b91ade709cbfd040ec53939ffbcc292aa7eee/platformdirs-4.11.2-py3-none-any.whl", hash = "sha256:7f89089b6ea71bda7962953edcf784b2e2d9d285b40ad88be2bb75c6e9d82ab4", size = 23361, upload-time = "2026-08-10T15:48:04.855Z" },
|
|
1438
1447
|
]
|
|
1439
1448
|
|
|
1449
|
+
[[package]]
|
|
1450
|
+
name = "pluggy"
|
|
1451
|
+
version = "1.6.0"
|
|
1452
|
+
source = { registry = "https://pypi.org/simple" }
|
|
1453
|
+
sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
|
|
1454
|
+
wheels = [
|
|
1455
|
+
{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
|
|
1456
|
+
]
|
|
1457
|
+
|
|
1440
1458
|
[[package]]
|
|
1441
1459
|
name = "pre-commit"
|
|
1442
1460
|
version = "4.6.2"
|
|
@@ -1838,6 +1856,15 @@ wheels = [
|
|
|
1838
1856
|
{ url = "https://files.pythonhosted.org/packages/b4/11/97233cf23ad5411ac6f13b1d6ee3888f90ace4f974d9bf9db887aa428912/pyerfa-2.0.1.5-cp39-abi3-win_amd64.whl", hash = "sha256:66292d437dcf75925b694977aa06eb697126e7b86553e620371ed3e48b5e0ad0", size = 349410, upload-time = "2024-11-11T15:22:24.817Z" },
|
|
1839
1857
|
]
|
|
1840
1858
|
|
|
1859
|
+
[[package]]
|
|
1860
|
+
name = "pygments"
|
|
1861
|
+
version = "2.20.0"
|
|
1862
|
+
source = { registry = "https://pypi.org/simple" }
|
|
1863
|
+
sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
|
|
1864
|
+
wheels = [
|
|
1865
|
+
{ url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
|
|
1866
|
+
]
|
|
1867
|
+
|
|
1841
1868
|
[[package]]
|
|
1842
1869
|
name = "pynacl"
|
|
1843
1870
|
version = "1.6.2"
|
|
@@ -1914,7 +1941,7 @@ wheels = [
|
|
|
1914
1941
|
|
|
1915
1942
|
[[package]]
|
|
1916
1943
|
name = "pyobs-fli"
|
|
1917
|
-
version = "2.0.0.
|
|
1944
|
+
version = "2.0.0.dev10"
|
|
1918
1945
|
source = { editable = "." }
|
|
1919
1946
|
dependencies = [
|
|
1920
1947
|
{ name = "astropy" },
|
|
@@ -1928,6 +1955,8 @@ dev = [
|
|
|
1928
1955
|
{ name = "black" },
|
|
1929
1956
|
{ name = "pre-commit" },
|
|
1930
1957
|
{ name = "pyrefly" },
|
|
1958
|
+
{ name = "pytest" },
|
|
1959
|
+
{ name = "pytest-asyncio" },
|
|
1931
1960
|
{ name = "ruff" },
|
|
1932
1961
|
]
|
|
1933
1962
|
|
|
@@ -1943,6 +1972,8 @@ dev = [
|
|
|
1943
1972
|
{ name = "black", specifier = ">=25.1.0,<27" },
|
|
1944
1973
|
{ name = "pre-commit", specifier = ">=4.2.0,<5" },
|
|
1945
1974
|
{ name = "pyrefly", specifier = ">=1.1.1" },
|
|
1975
|
+
{ name = "pytest", specifier = ">=8.0.0" },
|
|
1976
|
+
{ name = "pytest-asyncio", specifier = ">=0.24.0" },
|
|
1946
1977
|
{ name = "ruff", specifier = ">=0.9.0" },
|
|
1947
1978
|
]
|
|
1948
1979
|
|
|
@@ -1965,6 +1996,35 @@ wheels = [
|
|
|
1965
1996
|
{ url = "https://files.pythonhosted.org/packages/1b/1c/df3cb0a2e5591660ded7a1836cd2f29dc48c91adb1c0a3a700a96f6d09e1/pyrefly-1.2.0-py3-none-win_arm64.whl", hash = "sha256:3a90bb8df39dfbac74b1f3b2e9d7c526b8f80568884c3944d955023a73ebf61e", size = 13430873, upload-time = "2026-08-01T02:56:25.425Z" },
|
|
1966
1997
|
]
|
|
1967
1998
|
|
|
1999
|
+
[[package]]
|
|
2000
|
+
name = "pytest"
|
|
2001
|
+
version = "9.1.1"
|
|
2002
|
+
source = { registry = "https://pypi.org/simple" }
|
|
2003
|
+
dependencies = [
|
|
2004
|
+
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
|
2005
|
+
{ name = "iniconfig" },
|
|
2006
|
+
{ name = "packaging" },
|
|
2007
|
+
{ name = "pluggy" },
|
|
2008
|
+
{ name = "pygments" },
|
|
2009
|
+
]
|
|
2010
|
+
sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" }
|
|
2011
|
+
wheels = [
|
|
2012
|
+
{ url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" },
|
|
2013
|
+
]
|
|
2014
|
+
|
|
2015
|
+
[[package]]
|
|
2016
|
+
name = "pytest-asyncio"
|
|
2017
|
+
version = "1.4.0"
|
|
2018
|
+
source = { registry = "https://pypi.org/simple" }
|
|
2019
|
+
dependencies = [
|
|
2020
|
+
{ name = "pytest" },
|
|
2021
|
+
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
|
2022
|
+
]
|
|
2023
|
+
sdist = { url = "https://files.pythonhosted.org/packages/43/7c/d36d04db312ecf4298932ef77e6e4a9e8ad017906e24e34f0b0c361a2473/pytest_asyncio-1.4.0.tar.gz", hash = "sha256:c6c0d2259945122819f171a32ecea2c349ead889ee28176caaf492143424be42", size = 58514, upload-time = "2026-05-26T09:56:04.083Z" }
|
|
2024
|
+
wheels = [
|
|
2025
|
+
{ url = "https://files.pythonhosted.org/packages/03/e2/08a497ef684b88559c9cc5f4ad53a37e7b99e727094a86d6ea32536d5d3c/pytest_asyncio-1.4.0-py3-none-any.whl", hash = "sha256:933ca923a23075a87fb7070c0ec272a6848489824d887c85c812670932835aa1", size = 16930, upload-time = "2026-05-26T09:56:02.576Z" },
|
|
2026
|
+
]
|
|
2027
|
+
|
|
1968
2028
|
[[package]]
|
|
1969
2029
|
name = "python-dateutil"
|
|
1970
2030
|
version = "2.9.0.post0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyobs_fli-2.0.0.dev9 → pyobs_fli-2.0.0.dev10}/specs/plans/2026-08-16-nogil-fli-driver-calls.md
RENAMED
|
File without changes
|