pyobs-zaber 2.0.0.dev7__tar.gz → 2.0.0.dev9__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.
Files changed (25) hide show
  1. pyobs_zaber-2.0.0.dev9/.github/dependabot.yml +15 -0
  2. pyobs_zaber-2.0.0.dev9/.github/workflows/dependabot-automerge.yml +24 -0
  3. pyobs_zaber-2.0.0.dev9/.github/workflows/pyrefly.yml +23 -0
  4. pyobs_zaber-2.0.0.dev9/.github/workflows/pytest.yml +25 -0
  5. {pyobs_zaber-2.0.0.dev7 → pyobs_zaber-2.0.0.dev9}/PKG-INFO +3 -3
  6. {pyobs_zaber-2.0.0.dev7 → pyobs_zaber-2.0.0.dev9}/pyproject.toml +8 -3
  7. pyobs_zaber-2.0.0.dev9/tests/test_import.py +24 -0
  8. pyobs_zaber-2.0.0.dev9/tests/test_zaberdriver.py +42 -0
  9. pyobs_zaber-2.0.0.dev9/tests/test_zabermodeselector.py +52 -0
  10. {pyobs_zaber-2.0.0.dev7 → pyobs_zaber-2.0.0.dev9}/uv.lock +970 -700
  11. {pyobs_zaber-2.0.0.dev7 → pyobs_zaber-2.0.0.dev9}/.github/workflows/pypi.yml +0 -0
  12. {pyobs_zaber-2.0.0.dev7 → pyobs_zaber-2.0.0.dev9}/.github/workflows/ruff.yml +0 -0
  13. {pyobs_zaber-2.0.0.dev7 → pyobs_zaber-2.0.0.dev9}/.pre-commit-config.yaml +0 -0
  14. {pyobs_zaber-2.0.0.dev7 → pyobs_zaber-2.0.0.dev9}/.readthedocs.yml +0 -0
  15. {pyobs_zaber-2.0.0.dev7 → pyobs_zaber-2.0.0.dev9}/LICENSE +0 -0
  16. {pyobs_zaber-2.0.0.dev7 → pyobs_zaber-2.0.0.dev9}/README.md +0 -0
  17. {pyobs_zaber-2.0.0.dev7 → pyobs_zaber-2.0.0.dev9}/docs/Makefile +0 -0
  18. {pyobs_zaber-2.0.0.dev7 → pyobs_zaber-2.0.0.dev9}/docs/make.bat +0 -0
  19. {pyobs_zaber-2.0.0.dev7 → pyobs_zaber-2.0.0.dev9}/docs/requirements.txt +0 -0
  20. {pyobs_zaber-2.0.0.dev7 → pyobs_zaber-2.0.0.dev9}/docs/source/_static/pyobs.gif +0 -0
  21. {pyobs_zaber-2.0.0.dev7 → pyobs_zaber-2.0.0.dev9}/docs/source/conf.py +0 -0
  22. {pyobs_zaber-2.0.0.dev7 → pyobs_zaber-2.0.0.dev9}/docs/source/index.rst +0 -0
  23. {pyobs_zaber-2.0.0.dev7 → pyobs_zaber-2.0.0.dev9}/pyobs_zaber/__init__.py +0 -0
  24. {pyobs_zaber-2.0.0.dev7 → pyobs_zaber-2.0.0.dev9}/pyobs_zaber/zaberdriver.py +0 -0
  25. {pyobs_zaber-2.0.0.dev7 → pyobs_zaber-2.0.0.dev9}/pyobs_zaber/zabermodeselector.py +0 -0
@@ -0,0 +1,15 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "uv"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+ day: "tuesday"
8
+ target-branch: "develop"
9
+ groups:
10
+ patch-and-minor:
11
+ update-types:
12
+ - "minor"
13
+ - "patch"
14
+ labels:
15
+ - "dependencies"
@@ -0,0 +1,24 @@
1
+ name: Dependabot auto-merge
2
+
3
+ on: pull_request
4
+
5
+ permissions:
6
+ contents: write
7
+ pull-requests: write
8
+
9
+ jobs:
10
+ dependabot:
11
+ runs-on: ubuntu-latest
12
+ if: ${{ github.event.pull_request.user.login == 'dependabot[bot]' }}
13
+ steps:
14
+ - name: Fetch Dependabot metadata
15
+ id: metadata
16
+ uses: dependabot/fetch-metadata@v2
17
+ with:
18
+ compat-lookup: true
19
+ - name: Enable auto-merge for patch and minor updates
20
+ if: ${{ steps.metadata.outputs.update-type == 'version-update:semver-patch' || steps.metadata.outputs.update-type == 'version-update:semver-minor' }}
21
+ run: gh pr merge --auto --merge "$PR_URL"
22
+ env:
23
+ PR_URL: ${{ github.event.pull_request.html_url }}
24
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,23 @@
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 packages
20
+ run: uv sync --all-extras --dev
21
+
22
+ - name: Run pyrefly
23
+ run: uv run pyrefly check
@@ -0,0 +1,25 @@
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 packages
20
+ run: uv sync --all-extras --dev
21
+
22
+ - name: Run tests
23
+ run: uv run pytest tests
24
+ env:
25
+ CI: true
@@ -1,10 +1,10 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: pyobs-zaber
3
- Version: 2.0.0.dev7
3
+ Version: 2.0.0.dev9
4
4
  Summary: pyobs model for Zaber motors
5
5
  Author-email: Leon Meerwart <leon.meerwart@uni-goettingen.de>
6
6
  License-Expression: MIT
7
7
  License-File: LICENSE
8
8
  Requires-Python: >=3.11
9
- Requires-Dist: pyobs-core<3,>=2.0.0.dev6
9
+ Requires-Dist: pyobs-core<3,>=2.0.0.dev48
10
10
  Requires-Dist: zaber-motion<5,>=4.7.0
@@ -1,21 +1,23 @@
1
1
  [project]
2
2
  name = "pyobs-zaber"
3
- version = "2.0.0.dev7"
3
+ version = "2.0.0.dev9"
4
4
  description = "pyobs model for Zaber motors"
5
5
  authors = [{ name = "Leon Meerwart", email = "leon.meerwart@uni-goettingen.de" }]
6
6
  requires-python = ">=3.11"
7
7
  license = "MIT"
8
8
  dependencies = [
9
9
  "zaber-motion>=4.7.0,<5",
10
- "pyobs-core>=2.0.0.dev6,<3",
10
+ "pyobs-core>=2.0.0.dev48,<3",
11
11
  ]
12
12
 
13
13
  [dependency-groups]
14
14
  dev = [
15
- "black>=25.1.0,<26",
15
+ "black>=25.1.0,<27",
16
16
  "ruff>=0.9.0",
17
17
  "pyrefly>=1.1.1",
18
18
  "pre-commit>=4.2.0,<5",
19
+ "pytest>=8.0.0",
20
+ "pytest-asyncio>=0.24.0",
19
21
  ]
20
22
 
21
23
  [build-system]
@@ -35,3 +37,6 @@ select = ["E", "F", "W", "I", "UP", "G"]
35
37
 
36
38
  [tool.pyrefly]
37
39
  python-version = "3.11"
40
+
41
+ [tool.pytest.ini_options]
42
+ asyncio_mode = "strict"
@@ -0,0 +1,24 @@
1
+ """Smoke tests: import every public module and instantiate the driver class without
2
+ hardware, asserting it advertises the interfaces it claims.
3
+
4
+ No motor is involved: ZaberDriver only stores configuration, and the serial connection
5
+ is opened lazily inside each operation.
6
+ """
7
+
8
+ from pyobs.interfaces import IMode, IMotion
9
+ from pyobs.modules import Module
10
+
11
+ from pyobs_zaber import ZaberModeSelector
12
+
13
+
14
+ def test_import_driver_module() -> None:
15
+ from pyobs_zaber import zaberdriver # noqa: F401
16
+
17
+ assert zaberdriver.ZaberDriver is not None
18
+
19
+
20
+ def test_instantiate_mode_selector() -> None:
21
+ selector = ZaberModeSelector(modes={"spec": 100.0, "phot": 200.0})
22
+ assert isinstance(selector, Module)
23
+ assert isinstance(selector, IMode)
24
+ assert isinstance(selector, IMotion)
@@ -0,0 +1,42 @@
1
+ """Unit tests for the non-hardware logic in ZaberDriver."""
2
+
3
+ from contextlib import asynccontextmanager
4
+ from unittest.mock import AsyncMock, MagicMock
5
+
6
+ import pytest
7
+ from zaber_motion import Units
8
+
9
+ from pyobs_zaber.zaberdriver import ZaberDriver
10
+
11
+
12
+ def test_constructor_defaults() -> None:
13
+ driver = ZaberDriver()
14
+ assert driver.port == "/dev/ttyUSB1"
15
+ assert driver.speed == 10000
16
+ assert driver.acceleration == 800
17
+ assert driver.length_unit is Units.ANGLE_DEGREES
18
+ assert driver.system_led is False
19
+
20
+
21
+ @pytest.mark.asyncio
22
+ async def test_move_by_defaults_to_configured_speed(monkeypatch: pytest.MonkeyPatch) -> None:
23
+ axis = MagicMock()
24
+ axis.move_relative_async = AsyncMock()
25
+
26
+ @asynccontextmanager
27
+ async def fake_axis(port):
28
+ yield axis
29
+
30
+ monkeypatch.setattr("pyobs_zaber.zaberdriver.zaber_axis", fake_axis)
31
+
32
+ driver = ZaberDriver(speed=12345)
33
+ await driver.move_by(1.0)
34
+
35
+ axis.move_relative_async.assert_awaited_once_with(
36
+ 1.0,
37
+ driver.length_unit,
38
+ velocity=12345,
39
+ velocity_unit=driver.speed_unit,
40
+ acceleration=driver.acceleration,
41
+ acceleration_unit=driver.acceleration_unit,
42
+ )
@@ -0,0 +1,52 @@
1
+ """Unit tests for the mode-selection state logic in ZaberModeSelector.
2
+
3
+ Movement itself is hardware I/O and is mocked out; these cover mode validation,
4
+ short-circuiting, and position mapping.
5
+ """
6
+
7
+ from unittest.mock import AsyncMock
8
+
9
+ import pytest
10
+
11
+ from pyobs_zaber import ZaberModeSelector
12
+
13
+ _MODES = {"spec": 100.0, "phot": 200.0}
14
+
15
+
16
+ def _make_selector() -> tuple[ZaberModeSelector, AsyncMock]:
17
+ selector = ZaberModeSelector(modes=_MODES)
18
+ move_to = AsyncMock()
19
+ selector.driver.move_to = move_to # type: ignore[method-assign]
20
+ return selector, move_to
21
+
22
+
23
+ def test_constructor_stores_modes_and_driver() -> None:
24
+ selector = ZaberModeSelector(modes=_MODES)
25
+ assert selector.modes == _MODES
26
+ assert selector.current_mode == "undefined"
27
+
28
+
29
+ @pytest.mark.asyncio
30
+ async def test_set_mode_moves_to_position() -> None:
31
+ selector, move_to = _make_selector()
32
+ await selector.set_mode("phot")
33
+ move_to.assert_awaited_once_with(200.0)
34
+ assert selector.current_mode == "phot"
35
+
36
+
37
+ @pytest.mark.asyncio
38
+ async def test_set_mode_unknown_mode_is_ignored() -> None:
39
+ selector, move_to = _make_selector()
40
+ await selector.set_mode("nope")
41
+ move_to.assert_not_awaited()
42
+ assert selector.current_mode == "undefined"
43
+
44
+
45
+ @pytest.mark.asyncio
46
+ async def test_set_mode_same_mode_is_noop() -> None:
47
+ selector, move_to = _make_selector()
48
+ await selector.set_mode("spec")
49
+ move_to.reset_mock()
50
+ await selector.set_mode("spec")
51
+ move_to.assert_not_awaited()
52
+ assert selector.current_mode == "spec"