Laut transfer.put() docs sollte ich entweder den lokalen Pfad zu einer Datei (als String) oder ein dateiähnliches Objekt angeben können.
Bei Verwendung des ersteren (String) kann ich im Pfad remote
nur das Zielverzeichnis angeben. Dies wird in einigen Beispielen verwendet :
c.put('myfiles.tgz', '/opt/mydata')
Aber wenn ich versuche, das gleiche zu tun ( c.put('file.txt', '/home/me/dir')
, IOError: Failure
, weil es sich tatsächlich so verhält, als ob der Pfad local
ein dateiähnliches Objekt wäre und keine Schnur.
Es schlägt speziell bei paramiko.transport.sftp.sftp._log: [chan 0] open('/home/me/dir', 'wb')
fehl
Die Lösung besteht darin, immer den vollständigen Pfad anzugeben, z
c.put('file.txt', '/home/me/dir/file.txt')
Aber das stimmt nicht mit den Dokumenten und Beispielen überein.
Schließlich ist es nicht ideal, den vollständigen Pfad zu $HOME
angeben zu müssen, aber dafür scheint es bereits ein Problem zu geben #1653
Irgendwelche Updates dazu? Connection.put
mit remote
als Verzeichnispfad-String erhöht derzeit IOError
.
(Danke auch für die ganze Arbeit an Fabric et al!)
Stoff 2.1.3
Paramiko 2.4.1
1.0.0 aufrufen
Klingt nach einem legitimen Bug, werde später nachschauen. Patches (und Tests! seit unserem bestanden alle :( was bedeutet, dass wir einige vermissen...) willkommen.
Wenn ich mir das jetzt anschaue, bin ich mir nicht sicher, ob das Problem in der Annahme von FLO liegt. Ich denke, es ist stattdessen einfach ein Mangel an der Implementierung des korrekten Remote-Pfad-Mungings - mit anderen Worten, wir bitten den SFTP-Server, das Verzeichnis als zu öffnen eine Datei zum Schreiben, anstatt den Basisnamen der lokalen Datei an den Remote-Verzeichnispfad anzuheften.
Teilweises Debug-Protokoll von Fabrics Ende:
invoke.transfer.put: Massaged relative local path 'setup.py' into '/Users/jforcier/Code/oss/fabric/setup.py'
invoke.transfer.put: Uploading '/Users/jforcier/Code/oss/fabric/setup.py' to '/Users/jforcier/tmp/'
paramiko.transport.sftp.sftp._log: [chan 2] open(b'/Users/jforcier/tmp/', 'wb')
Dann zeigt ein Teil des Tracebacks, dass wir diesen Verzeichnispfad in CMD_OPEN in sftp_client.py
werfen:
t, msg = self._request(CMD_OPEN, filename, imode, attrblock)
Was schließlich die Fehlerbehandlung derselben Datei / Klasse um das herum trifft, was der SFTP-Server mit der IO-Operation als falsch bezeichnet hat (weshalb es nur "Fehler" ist, weil es natürlich ... AFAIK ist, dass OpenSSH schuld ist.)
Wie auch immer, es ist an der Zeit, einige Tests zu schreiben, um dies zu beweisen, und dann herauszufinden, ob es ein logisches Ups ist (ich dachte, wir konstruieren irgendwann einen angehängten Pfad) oder ein tatsächlich fehlendes Stück Funktionalität.
OK, nein, das ganze Munging dreht sich um leere oder relative Remote-Pfade, es gibt keine Überprüfung des is-Verzeichnisses.
Während ich hier bin, frage ich mich, wie auch mit FLOs umgegangen werden soll, wenn der Remote-Pfad ein Verzeichnis ist.
In v1 haben wir uns das .name
Attribut von FLOs angesehen, da es
Wie auch immer, hier in v2 haben wir die Möglichkeit, das wirklich anzugehen oder einfach eine explizite Ausnahme auszulösen, die besagt, dass "whoa hey, Sie müssen einen Nicht-Verzeichnis-Remote-Dateipfad für diese angeben". Wahrscheinlich beides, da sowieso nicht alle FLOs unbedingt das name-Attribut haben.
OK, das ist alles behoben, wird im nächsten Bugfix-Release veröffentlicht 🎉