`linux.copy()` decides two paths are "on the same host" purely by
class inheritance:
https://github.com/Rahix/tbot/blob/master/tbot/machine/linux/copy.py#L118
if isinstance(p1.host, p2.host.__class__) or isinstance(p2.host, p1.host.__class__):
# Both paths are on the same host
...
This only matches when one machine's class is literally a subclass of
the other's. If a project defines two separate machine classes that
both connect via `connector.SubprocessConnector` (i.e. both actually
run on localhost) but don't inherit from each other, `copy()` doesn't
recognize them as the same host. It then falls through every
SSH/Paramiko-specific branch and hits:
raise NotImplementedError(f"Can't copy from {p1.host} to {p2.host}!")
even though both machines run commands on the same filesystem and a
plain `cp` would work.
Repro
class LabHost(connector.SubprocessConnector, linux.Bash):
...
class LocalHost(connector.SubprocessConnector, linux.Bash):
...
with tbot.ctx.request(tbot.role.LocalHost) as local, \
tbot.ctx.request(tbot.role.LabHost) as lab:
linux.copy(local.workdir / "foo", lab.workdir / "foo")
# NotImplementedError: Can't copy from <LabHost ...> to <LocalHost ...>!
Suggested fix
Detect "same host" by checking that both machines are
`SubprocessConnector` instances (i.e. both run locally), rather than
requiring one machine's class to be a subclass of the other's:
if isinstance(p1.host, connector.SubprocessConnector) and isinstance(p2.host, connector.SubprocessConnector):
...
Currently working around this downstream by special-casing this
combination and calling `local.exec0("cp", ...)` directly instead of
`linux.copy()`/`utils.copy_to_dir()`.
`linux.copy()` decides two paths are "on the same host" purely by
class inheritance:
https://github.com/Rahix/tbot/blob/master/tbot/machine/linux/copy.py#L118
This only matches when one machine's class is literally a subclass of
the other's. If a project defines two separate machine classes that
both connect via `connector.SubprocessConnector` (i.e. both actually
run on localhost) but don't inherit from each other, `copy()` doesn't
recognize them as the same host. It then falls through every
SSH/Paramiko-specific branch and hits:
even though both machines run commands on the same filesystem and a
plain `cp` would work.
Repro
Suggested fix
Detect "same host" by checking that both machines are
`SubprocessConnector` instances (i.e. both run locally), rather than
requiring one machine's class to be a subclass of the other's:
Currently working around this downstream by special-casing this
combination and calling `local.exec0("cp", ...)` directly instead of
`linux.copy()`/`utils.copy_to_dir()`.