Skip to content

Fix pixi environment solving on macOS (osx-arm64) #306

Merged
knipknap merged 4 commits into
barebaric:mainfrom
vyvcodd:fix/macos-osx-arm64-pixi-support
Jul 12, 2026
Merged

Fix pixi environment solving on macOS (osx-arm64) #306
knipknap merged 4 commits into
barebaric:mainfrom
vyvcodd:fix/macos-osx-arm64-pixi-support

Conversation

@vyvcodd

@vyvcodd vyvcodd commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Adds osx-arm64 to Pixi's supported platforms and fixes dependency solving so all four environments solve and pixi run rayforge runs on Apple Silicon. Running the test suite on macOS for the first time also surfaced two minor macOS-only bugs, now fixed.

Changes

  • Scope libglvnd (X11-only) to linux-64; it has no osx-arm64 build and was blocking every environment from solving
  • Pin scipy/numpy to match requirements.txt and the existing linux-64 lock
  • Move libvips into the shared deps; pyvips needs it on every platform
  • Fix SerialServerTransport closing its PTY slave fd immediately, which raises EIO on macOS once no process holds the slave open
  • Fix TelnetTransport.disconnect() double-firing DISCONNECTED, since cancelling the connection task doesn't raise CancelledError through it
  • Fix telnet integration tests asserting server-side state right after connect() returns, which isn't guaranteed across event loop backends
  • Correct the install guide and developer setup docs, which said Pixi was Linux-only

Checks

  • pixi run test (5563 passed, 174 deselected)
  • pixi run lint
  • pixi install (all four environments solve on osx-arm64)
  • pixi run rayforge (launches on osx-arm64)

@knipknap

Copy link
Copy Markdown
Contributor

Thanks for the PR! Fantastic that pixi can now be used for MacOS, this is awesome.

It seems though the serial server changes cause a regression - the backend tests appear to be stuck on all platforms except MacOS.

@knipknap

Copy link
Copy Markdown
Contributor

It works when I replace disconnect() by this on my Linux machine:

    async def disconnect(self) -> None:
        logger.info(
            f"Disconnecting from telnet server at {self.host}:{self.port}..."
        )
        self._running = False
        if self._connection_task:
            self._connection_task.cancel()
            try:
                await self._connection_task
            except asyncio.CancelledError:
                pass  # Expected
            # _manage_connection's finally block should have closed the writer
            # and sent DISCONNECTED, but if the task hadn't started yet when
            # cancelled, the finally block was never entered. Check whether
            # cleanup actually happened and do it ourselves if not.
            if self.writer is not None:
                self.writer.close()
                try:
                    await self.writer.wait_closed()
                except (ConnectionResetError, OSError):
                    pass
                self.writer = None
                self.reader = None
                self.status_changed.send(
                    self, status=TransportStatus.DISCONNECTED
                )
            self._connection_task = None
            return
        if self.writer:
            self.writer.close()
            try:
                await self.writer.wait_closed()
            except (ConnectionResetError, OSError):
                pass  # The other end might have already closed it.
        self.writer = None
        self.reader = None
        self.status_changed.send(self, status=TransportStatus.DISCONNECTED)
        logger.info(f"Disconnected from {self.host}:{self.port}.")

Perhaps that also works for MacOS...

@vyvcodd

vyvcodd commented Jul 12, 2026

Copy link
Copy Markdown
Contributor Author

ooh I'll try that! I'm currently fighting my Colima install, but nearly there I think

@vyvcodd

vyvcodd commented Jul 12, 2026

Copy link
Copy Markdown
Contributor Author

Ok I have a fix I think...
connect()'s background task can be cancelled before it ever gets its first scheduling slot, so _manage_connection's finally never runs. I've added a guard clauseto the disconnect in test_telnet_transport, if self.writer is None: return, before doing cleanup, instead of unconditionally returning after cancelling the task. So it closes the connection and fires DISCONNECTED exactly once whether _manage_connection's own cleanup already ran, or never got the chance to.

CORRECTION the guard clause is in telnet.py not test_telnet_transport.py, copied the wrong filename :/

vyvcodd added 4 commits July 12, 2026 16:13
- Scope libglvnd (X11-only) to linux-64; it has no osx-arm64 build
  and was blocking every environment from solving
- Pin scipy/numpy to match requirements.txt and the linux-64 lock
- Move libvips into the shared deps; pyvips needs it on every platform
Running tests via pixi on osx-arm64 for the first time surfaced bugs
Linux CI never exercised:

- SerialServerTransport closed its PTY slave fd immediately; macOS's
  PTY driver raises EIO on the master once no process holds the
  slave open, so keep our own fd open for the transport's lifetime
- TelnetTransport.disconnect() double-fired DISCONNECTED, since
  cancelling the connection task doesn't raise CancelledError
  through it (the loop swallows it and exits normally)
- Telnet integration tests asserted server-side state right after
  connect() returned; that ordering isn't guaranteed across event
  loop backends, so poll for it instead
- Correct the install guide's "Linux Only" admonition, which was
  false as of the previous commits in this branch
- Add a macOS section to the developer setup guide, mirroring the
  existing Linux one
- The connection task can be cancelled before its first scheduling
  slot, so _manage_connection's finally block never runs and the
  writer is never closed - guard on self.writer instead of returning
  unconditionally, so cleanup happens exactly once either way
- Catch OSError alongside ConnectionResetError on wait_closed()
- Clear self._connection_task after handling it
@vyvcodd
vyvcodd force-pushed the fix/macos-osx-arm64-pixi-support branch from 249c908 to 22f3431 Compare July 12, 2026 15:25
@knipknap
knipknap merged commit 8c46b75 into barebaric:main Jul 12, 2026
29 checks passed
@knipknap

Copy link
Copy Markdown
Contributor

Yep, your approach is much cleaner than the disconnect() fallback. Thanks!

@vyvcodd
vyvcodd deleted the fix/macos-osx-arm64-pixi-support branch July 15, 2026 19:14
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