diff options
-rw-r--r-- | NEWS | 12 | ||||
-rw-r--r-- | paramiko/__init__.py | 2 | ||||
-rw-r--r-- | paramiko/channel.py | 20 | ||||
-rw-r--r-- | paramiko/client.py | 8 | ||||
-rw-r--r-- | paramiko/config.py | 2 | ||||
-rw-r--r-- | paramiko/file.py | 4 | ||||
-rw-r--r-- | setup.py | 2 |
7 files changed, 41 insertions, 9 deletions
@@ -12,6 +12,18 @@ Issues noted as "Fabric #NN" can be found at https://github.com/fabric/fabric/. Releases ======== +v1.10.0 (DD MM YYYY) +-------------------- + +* #113: Add `timeout` parameter to `SSHClient.exec_command` for easier setting + of the command's internal channel object's timeout. Thanks to Cernov Vladimir + for the patch. +* #94: Remove duplication of SSH port constant. Thanks to Olle Lundberg for the + catch. +* #80: Expose the internal "is closed" property of the file transfer class + `BufferedFile` as `.closed`, better conforming to Python's file interface. + Thanks to `@smunaut` and James Hiscock for catch & patch. + v1.9.0 (6th Nov 2012) --------------------- diff --git a/paramiko/__init__.py b/paramiko/__init__.py index 29e470a6..7d7dcbf4 100644 --- a/paramiko/__init__.py +++ b/paramiko/__init__.py @@ -55,7 +55,7 @@ if sys.version_info < (2, 2): __author__ = "Jeff Forcier <jeff@bitprophet.org>" -__version__ = "1.9.0" +__version__ = "1.10.0" __license__ = "GNU Lesser General Public License (LGPL)" diff --git a/paramiko/channel.py b/paramiko/channel.py index 534f8d7c..9a1bb874 100644 --- a/paramiko/channel.py +++ b/paramiko/channel.py @@ -25,6 +25,7 @@ import sys import time import threading import socket +import errno import os from paramiko.common import * @@ -605,6 +606,10 @@ class Channel (object): @raise socket.timeout: if no data is ready before the timeout set by L{settimeout}. """ + if self.closed: + # this doesn't seem useful, but it is the documented behavior of Socket + raise socket.error(errno.EBADF, 'Socket is closed') + try: out = self.in_buffer.read(nbytes, self.timeout) except PipeTimeout, e: @@ -655,6 +660,10 @@ class Channel (object): @since: 1.1 """ + if self.closed: + # this doesn't seem useful, but it is the documented behavior of Socket + raise socket.error(errno.EBADF, 'Socket is closed') + try: out = self.in_stderr_buffer.read(nbytes, self.timeout) except PipeTimeout, e: @@ -708,6 +717,10 @@ class Channel (object): @raise socket.timeout: if no data could be sent before the timeout set by L{settimeout}. """ + if self.closed: + # this doesn't seem useful, but it is the documented behavior of Socket + raise socket.error(errno.EBADF, 'Socket is closed') + size = len(s) self.lock.acquire() try: @@ -745,6 +758,10 @@ class Channel (object): @since: 1.1 """ + if self.closed: + # this doesn't seem useful, but it is the documented behavior of Socket + raise socket.error(errno.EBADF, 'Socket is closed') + size = len(s) self.lock.acquire() try: @@ -783,9 +800,6 @@ class Channel (object): This is irritating, but identically follows python's API. """ while s: - if self.closed: - # this doesn't seem useful, but it is the documented behavior of Socket - raise socket.error('Socket is closed') sent = self.send(s) s = s[sent:] return None diff --git a/paramiko/client.py b/paramiko/client.py index 07560a39..a777b45b 100644 --- a/paramiko/client.py +++ b/paramiko/client.py @@ -28,6 +28,7 @@ import warnings from paramiko.agent import Agent from paramiko.common import * +from paramiko.config import SSH_PORT from paramiko.dsskey import DSSKey from paramiko.hostkeys import HostKeys from paramiko.resource import ResourceManager @@ -37,8 +38,6 @@ from paramiko.transport import Transport from paramiko.util import retry_on_signal -SSH_PORT = 22 - class MissingHostKeyPolicy (object): """ Interface for defining the policy that L{SSHClient} should use when the @@ -350,7 +349,7 @@ class SSHClient (object): self._agent.close() self._agent = None - def exec_command(self, command, bufsize=-1): + def exec_command(self, command, bufsize=-1, timeout=None): """ Execute a command on the SSH server. A new L{Channel} is opened and the requested command is executed. The command's input and output @@ -361,12 +360,15 @@ class SSHClient (object): @type command: str @param bufsize: interpreted the same way as by the built-in C{file()} function in python @type bufsize: int + @param timeout: set command's channel timeout. See L{Channel.settimeout}.settimeout + @type timeout: int @return: the stdin, stdout, and stderr of the executing command @rtype: tuple(L{ChannelFile}, L{ChannelFile}, L{ChannelFile}) @raise SSHException: if the server fails to execute the command """ chan = self._transport.open_session() + chan.settimeout(timeout) chan.exec_command(command) stdin = chan.makefile('wb', bufsize) stdout = chan.makefile('rb', bufsize) diff --git a/paramiko/config.py b/paramiko/config.py index 2828d903..d1ce9490 100644 --- a/paramiko/config.py +++ b/paramiko/config.py @@ -25,7 +25,7 @@ import os import re import socket -SSH_PORT=22 +SSH_PORT = 22 proxy_re = re.compile(r"^(proxycommand)\s*=*\s*(.*)", re.I) diff --git a/paramiko/file.py b/paramiko/file.py index d4aec8e3..7e2904e1 100644 --- a/paramiko/file.py +++ b/paramiko/file.py @@ -354,6 +354,10 @@ class BufferedFile (object): """ return self + @property + def closed(self): + return self._closed + ### overrides... @@ -52,7 +52,7 @@ if sys.platform == 'darwin': setup(name = "paramiko", - version = "1.9.0", + version = "1.10.0", description = "SSH2 protocol library", author = "Jeff Forcier", author_email = "jeff@bitprophet.org", |