Fix `beam cp` on Windows: join volume paths with "/"
beam cp fails on Windows for every download, and for uploads whose destination doesn't end in /:
> beam cp C:\data\dataset.tar beam://my-volume/uploads
Failed: Unable to stat path: path='my-volume\\uploads' message='... sql: no rows in result set'
Cause. RemotePath.path and RemotePath.__truediv__ join with os.path, which is ntpath on Windows. The CLI then sends my-volume\uploads to StatPath / ListPath, and the gateway can't find a volume with that name. Uploads to beam://my-volume/uploads/ work because that branch skips is_dir() and sends volume_name and volume_path separately. Downloads always call is_dir() first, so they always fail.
Fix. Volume paths always use /, so RemotePath now joins them with posixpath. Nothing changes on Linux or macOS, where os.path already is posixpath.
Tests. The new tests in sdk/tests/test_multipart.py simulate Windows by monkeypatching os.path with ntpath, so they run on the Linux CI. They check RemotePath.path, name, / joins, and the path that Beta9Handler.is_dir() sends to stat_path.
Verification
- Against a real volume, using beam-client 0.2.233 on macOS with
ntpathin place ofos.path: the upload without a trailing/failed with the error above, and the one with/succeeded. A Windows user can confirm the same error. - Same assertions as the new tests, run on the two classes taken from
multipart.py: 5 of 8 fail onmain(for examplemy-volume\uploads/data.tar) and 8 of 8 pass with this change. ruff checkpasses on both files. I couldn't run the full SDK suite locally, so CI is the first full run.
Related. Downloads to a directory outside the current one fail on every OS for a separate reason, fixed in #2079.