Skip to content

Optional deps should be optional#941

Merged
rickwierenga merged 13 commits intoPyLabRobot:mainfrom
burnpanck:bugifx/optional-deps-should-be-optional
Mar 18, 2026
Merged

Optional deps should be optional#941
rickwierenga merged 13 commits intoPyLabRobot:mainfrom
burnpanck:bugifx/optional-deps-should-be-optional

Conversation

@burnpanck
Copy link
Contributor

On current main, pylabrobot is not importable when installed with just the mandatory dependencies. This PR

  1. Adds GitHub Action tests for installation configurations other than all
  2. Fixes these tests by a) skipping tests with unmet dependencies and b) allow backend imports from frontend __init__.py files to fail
  3. (also updates GHA steps to avoid some deprecations)

Copy link
Member

@rickwierenga rickwierenga left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the PR!

Comment on lines +1 to +4
try:
from pylabrobot.visualizer.visualizer import Visualizer
except ImportError:
pass
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if importing the visualizer leads to errors, we should catch them in visualizer.py rather than here

Comment on lines +3 to +15
from .cytomat import CytomatBackend
try:
from .cytomat import CytomatBackend
except ImportError:
pass
from .incubator import Incubator
from .inheco.scila import SCILABackend
from .liconic import ExperimentalLiconicBackend
try:
from .inheco.scila import SCILABackend
except ImportError:
pass
try:
from .liconic import ExperimentalLiconicBackend
except ImportError:
pass
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similar to visualizer: if these files cannot be imported, that should be fixed in those files rather than the init

Copy link
Contributor Author

@burnpanck burnpanck Mar 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I'll give it a try. I guess there are three different levels of support for "unavailable" backends (i.e. with missing dependencies):

  1. Cannot even be imported (Current state of this PR).
  2. Can be imported but not instantiated.
  3. Can be imported and instantiated, but .setup fails.

The main implication of not going with 1) above would be that we cannot generally import types from optional dependencies for type annotations, at least not without some sort of fallback.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be imported but not instantiated.

this is the best I think

for typing we can use TYPE_CHECKING

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see above

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why split it like this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't want to test the full product combination of all python versions and all dependency configurations of interest, because the number of tests quickly explodes. Options that I considered:

Would you prefer the last option?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, makes sense!

rickwierenga and others added 6 commits March 18, 2026 11:53
…mports

Optional deps (serial, pylibftdi, hid, usb, websockets, pymodbus) are now
wrapped in try/except at module level so imports always succeed. The runtime
check raises in __init__() instead of setup(), giving an immediate clear error
when the class is instantiated. Reverts the try/except band-aids in __init__.py
re-export files since they are no longer needed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Wrap serial import in keyence_backend, heraeus_cytomat_backend,
  a4s_backend, xpeel_backend with try/except + __init__ check
- Fix import sorting in 6 test files
- Guard agrowdosepump_tests.py and pico backend_tests.py with
  unittest.SkipTest when optional deps missing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The HID, USB, and Serial check-on-init broke tests that construct IO
objects without calling setup() (e.g. Hamilton STAR tests, Byonoy
resource tests). These checks must stay in setup() — the backend
__init__ checks are sufficient for user-facing error messages.

Also add type: ignore for numpy import in pico backend_tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@rickwierenga rickwierenga force-pushed the bugifx/optional-deps-should-be-optional branch 2 times, most recently from 62d8dc6 to 59f128d Compare March 18, 2026 21:27
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@rickwierenga rickwierenga merged commit b888ccd into PyLabRobot:main Mar 18, 2026
21 checks passed
@rickwierenga
Copy link
Member

thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants