summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJeff Forcier <jeff@bitprophet.org>2015-11-03 12:47:27 -0800
committerJeff Forcier <jeff@bitprophet.org>2015-11-03 12:47:27 -0800
commit7108289226d460411cf7dabcd065b603be480113 (patch)
tree51b50b9ff6a46256f7c4d27ad8bf440f3ccdeef4
parente7808e11de87127451f25e5cd45f8f764cbcb590 (diff)
parent0a57d0337778d99066688e310c81d449c64c9bb6 (diff)
Merge branch '1.13' into 525-int
-rw-r--r--.travis.yml7
-rw-r--r--dev-requirements.txt4
-rw-r--r--paramiko/_version.py2
-rw-r--r--paramiko/buffered_pipe.py4
-rw-r--r--paramiko/channel.py4
-rw-r--r--paramiko/config.py4
-rw-r--r--paramiko/pkey.py24
-rw-r--r--paramiko/sftp_attr.py5
-rw-r--r--paramiko/sftp_client.py2
-rw-r--r--paramiko/util.py2
-rw-r--r--setup.py2
-rw-r--r--sites/www/changelog.rst12
-rw-r--r--tasks.py17
-rwxr-xr-xtest.py5
-rwxr-xr-xtests/test_sftp.py5
15 files changed, 63 insertions, 36 deletions
diff --git a/.travis.yml b/.travis.yml
index 64f64e60..f841a71e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,8 +3,9 @@ sudo: false
python:
- "2.6"
- "2.7"
- - "3.2"
- "3.3"
+ - "3.4"
+ - "3.5"
install:
# Self-install for setup.py-driven deps
- pip install -e .
@@ -18,9 +19,7 @@ script:
# Run 'docs' first since its objects.inv is referred to by 'www'.
# Also force warnings to be errors since most of them tend to be actual
# problems.
- # Finally, skip them under Python 3.2 due to sphinx shenanigans
- - "[[ $TRAVIS_PYTHON_VERSION != 3.2 ]] && invoke docs -o -W || true"
- - "[[ $TRAVIS_PYTHON_VERSION != 3.2 ]] && invoke www -o -W || true"
+ - invoke docs -o -W www -o -W
notifications:
irc:
channels: "irc.freenode.org#paramiko"
diff --git a/dev-requirements.txt b/dev-requirements.txt
index 059572cf..90cfd477 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -1,8 +1,8 @@
# Older junk
tox>=1.4,<1.5
# For newer tasks like building Sphinx docs.
-invoke>=0.10
-invocations>=0.9.2
+invoke>=0.11.1
+invocations>=0.11.0
sphinx>=1.1.3
alabaster>=0.6.1
releases>=0.5.2
diff --git a/paramiko/_version.py b/paramiko/_version.py
index 0402fcf2..63bba727 100644
--- a/paramiko/_version.py
+++ b/paramiko/_version.py
@@ -1,2 +1,2 @@
-__version_info__ = (1, 13, 3)
+__version_info__ = (1, 13, 4)
__version__ = '.'.join(map(str, __version_info__))
diff --git a/paramiko/buffered_pipe.py b/paramiko/buffered_pipe.py
index ac35b3e1..d5fe164e 100644
--- a/paramiko/buffered_pipe.py
+++ b/paramiko/buffered_pipe.py
@@ -81,7 +81,7 @@ class BufferedPipe (object):
Feed new data into this pipe. This method is assumed to be called
from a separate thread, so synchronization is done.
- :param data: the data to add, as a `str`
+ :param data: the data to add, as a `str` or `bytes`
"""
self._lock.acquire()
try:
@@ -125,7 +125,7 @@ class BufferedPipe (object):
:param int nbytes: maximum number of bytes to read
:param float timeout:
maximum seconds to wait (or ``None``, the default, to wait forever)
- :return: the read data, as a `str`
+ :return: the read data, as a `bytes`
:raises PipeTimeout:
if a timeout was specified and no data was ready before that
diff --git a/paramiko/channel.py b/paramiko/channel.py
index 23323650..a36c70f4 100644
--- a/paramiko/channel.py
+++ b/paramiko/channel.py
@@ -574,8 +574,8 @@ class Channel (object):
is returned, the channel stream has closed.
:param int nbytes: maximum number of bytes to read.
- :return: received data, as a `str`
-
+ :return: received data, as a `bytes`
+
:raises socket.timeout:
if no data is ready before the timeout set by `settimeout`.
"""
diff --git a/paramiko/config.py b/paramiko/config.py
index c21de936..5c2efdcc 100644
--- a/paramiko/config.py
+++ b/paramiko/config.py
@@ -51,7 +51,7 @@ class SSHConfig (object):
"""
Read an OpenSSH config from the given file object.
- :param file file_obj: a file-like object to read the config file from
+ :param file_obj: a file-like object to read the config file from
"""
host = {"host": ['*'], "config": {}}
for line in file_obj:
@@ -99,7 +99,7 @@ class SSHConfig (object):
The host-matching rules of OpenSSH's ``ssh_config`` man page are used:
For each parameter, the first obtained value will be used. The
- configuration files contain sections separated by ``Host''
+ configuration files contain sections separated by ``Host``
specifications, and that section is only applied for hosts that match
one of the patterns given in the specification.
diff --git a/paramiko/pkey.py b/paramiko/pkey.py
index c8f84e0a..472c1287 100644
--- a/paramiko/pkey.py
+++ b/paramiko/pkey.py
@@ -171,8 +171,9 @@ class PKey (object):
is useless on the abstract PKey class.
:param str filename: name of the file to read
- :param str password: an optional password to use to decrypt the key file,
- if it's encrypted
+ :param str password:
+ an optional password to use to decrypt the key file, if it's
+ encrypted
:return: a new `.PKey` based on the given private key
:raises IOError: if there was an error reading the file
@@ -187,18 +188,18 @@ class PKey (object):
def from_private_key(cls, file_obj, password=None):
"""
Create a key object by reading a private key from a file (or file-like)
- object. If the private key is encrypted and ``password`` is not ``None``,
- the given password will be used to decrypt the key (otherwise
+ object. If the private key is encrypted and ``password`` is not
+ ``None``, the given password will be used to decrypt the key (otherwise
`.PasswordRequiredException` is thrown).
- :param file file_obj: the file to read from
+ :param file_obj: the file-like object to read from
:param str password:
an optional password to use to decrypt the key, if it's encrypted
:return: a new `.PKey` based on the given private key
:raises IOError: if there was an error reading the key
- :raises PasswordRequiredException: if the private key file is encrypted,
- and ``password`` is ``None``
+ :raises PasswordRequiredException:
+ if the private key file is encrypted, and ``password`` is ``None``
:raises SSHException: if the key file is invalid
"""
key = cls(file_obj=file_obj, password=password)
@@ -224,7 +225,7 @@ class PKey (object):
Write private key contents into a file (or file-like) object. If the
password is not ``None``, the key is encrypted before writing.
- :param file file_obj: the file object to write into
+ :param file_obj: the file-like object to write into
:param str password: an optional password to use to encrypt the key
:raises IOError: if there was an error writing to the file
@@ -274,7 +275,7 @@ class PKey (object):
start += 1
# find end
end = start
- while (lines[end].strip() != '-----END ' + tag + ' PRIVATE KEY-----') and (end < len(lines)):
+ while end < len(lines) and lines[end].strip() != '-----END ' + tag + ' PRIVATE KEY-----':
end += 1
# if we trudged to the end of the file, just try to cope.
try:
@@ -310,8 +311,9 @@ class PKey (object):
a trivially-encoded format (base64) which is completely insecure. If
a password is given, DES-EDE3-CBC is used.
- :param str tag: ``"RSA"`` or ``"DSA"``, the tag used to mark the data block.
- :param file filename: name of the file to write.
+ :param str tag:
+ ``"RSA"`` or ``"DSA"``, the tag used to mark the data block.
+ :param filename: name of the file to write.
:param str data: data blob that makes up the private key.
:param str password: an optional password to use to encrypt the file.
diff --git a/paramiko/sftp_attr.py b/paramiko/sftp_attr.py
index d12eff8d..708afc5a 100644
--- a/paramiko/sftp_attr.py
+++ b/paramiko/sftp_attr.py
@@ -210,12 +210,15 @@ class SFTPAttributes (object):
# not all servers support uid/gid
uid = self.st_uid
gid = self.st_gid
+ size = self.st_size
if uid is None:
uid = 0
if gid is None:
gid = 0
+ if size is None:
+ size = 0
- return '%s 1 %-8d %-8d %8d %-12s %s' % (ks, uid, gid, self.st_size, datestr, filename)
+ return '%s 1 %-8d %-8d %8d %-12s %s' % (ks, uid, gid, size, datestr, filename)
def asbytes(self):
return b(str(self))
diff --git a/paramiko/sftp_client.py b/paramiko/sftp_client.py
index 99a29e36..9a3e04b7 100644
--- a/paramiko/sftp_client.py
+++ b/paramiko/sftp_client.py
@@ -517,7 +517,7 @@ class SFTPClient(BaseSFTP):
The SFTP operations use pipelining for speed.
- :param file fl: opened file or file-like object to copy
+ :param fl: opened file or file-like object to copy
:param str remotepath: the destination path on the SFTP server
:param int file_size:
optional size parameter passed to callback. If none is specified,
diff --git a/paramiko/util.py b/paramiko/util.py
index 46278a69..0d8ce32a 100644
--- a/paramiko/util.py
+++ b/paramiko/util.py
@@ -118,7 +118,7 @@ def safe_string(s):
def bit_length(n):
try:
- return n.bitlength()
+ return n.bit_length()
except AttributeError:
norm = deflate_long(n, False)
hbyte = byte_ord(norm[0])
diff --git a/setup.py b/setup.py
index 235fd0e3..9e08323d 100644
--- a/setup.py
+++ b/setup.py
@@ -86,6 +86,8 @@ setup(
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
+ 'Programming Language :: Python :: 3.4',
+ 'Programming Language :: Python :: 3.5',
],
**kw
)
diff --git a/sites/www/changelog.rst b/sites/www/changelog.rst
index 9ce2eded..e435c65e 100644
--- a/sites/www/changelog.rst
+++ b/sites/www/changelog.rst
@@ -2,6 +2,18 @@
Changelog
=========
+* :release:`1.13.4 <2015-11-02>`
+* :bug:`366` Fix `~paramiko.sftp_attributes.SFTPAttributes` so its string
+ representation doesn't raise exceptions on empty/initialized instances. Patch
+ by Ulrich Petri.
+* :bug:`359` Use correct attribute name when trying to use Python 3's
+ ``int.bit_length`` method; prior to fix, the Python 2 custom fallback
+ implementation was always used, even on Python 3. Thanks to Alex Gaynor.
+* :support:`594 backported` Correct some post-Python3-port docstrings to
+ specify ``bytes`` type instead of ``str``. Credit to ``@redixin``.
+* :bug:`565` Don't explode with ``IndexError`` when reading private key files
+ lacking an ``-----END <type> PRIVATE KEY-----`` footer. Patch courtesy of
+ Prasanna Santhanam.
* :release:`1.13.3 <2014-12-19>`
* :bug:`413` (also :issue:`414`, :issue:`420`, :issue:`454`) Be significantly
smarter about polling & timing behavior when running proxy commands, to avoid
diff --git a/tasks.py b/tasks.py
index 20ded03d..3d55a778 100644
--- a/tasks.py
+++ b/tasks.py
@@ -3,14 +3,20 @@ from os.path import join
from shutil import rmtree, copytree
from invoke import Collection, ctask as task
-from invocations.docs import docs, www
+from invocations.docs import docs, www, sites
from invocations.packaging import publish
# Until we move to spec-based testing
@task
-def test(ctx):
- ctx.run("python test.py --verbose", pty=True)
+def test(ctx, coverage=False, flags=""):
+ if "--verbose" not in flags.split():
+ flags += " --verbose"
+ runner = "python"
+ if coverage:
+ runner = "coverage run --source=paramiko"
+ ctx.run("{0} test.py {1}".format(runner, flags), pty=True)
+
@task
def coverage(ctx):
@@ -25,11 +31,12 @@ def release(ctx):
# Move the built docs into where Epydocs used to live
target = 'docs'
rmtree(target, ignore_errors=True)
- copytree(docs_build, target)
+ # TODO: make it easier to yank out this config val from the docs coll
+ copytree('sites/docs/_build', target)
# Publish
publish(ctx)
# Remind
print("\n\nDon't forget to update RTD's versions page for new minor releases!")
-ns = Collection(test, coverage, release, docs, www)
+ns = Collection(test, coverage, release, docs, www, sites)
diff --git a/test.py b/test.py
index bd966d1e..6a2c9a8b 100755
--- a/test.py
+++ b/test.py
@@ -149,10 +149,7 @@ def main():
# TODO: make that not a problem, jeez
for thread in threading.enumerate():
if thread is not threading.currentThread():
- if PY2:
- thread._Thread__stop()
- else:
- thread._stop()
+ thread.join(timeout=1)
# Exit correctly
if not result.wasSuccessful():
sys.exit(1)
diff --git a/tests/test_sftp.py b/tests/test_sftp.py
index 2b6aa3b6..980e8367 100755
--- a/tests/test_sftp.py
+++ b/tests/test_sftp.py
@@ -776,6 +776,11 @@ class SFTPTest (unittest.TestCase):
sftp.remove('%s/nonutf8data' % FOLDER)
+ def test_sftp_attributes_empty_str(self):
+ sftp_attributes = SFTPAttributes()
+ self.assertEqual(str(sftp_attributes), "?--------- 1 0 0 0 (unknown date) ?")
+
+
if __name__ == '__main__':
SFTPTest.init_loopback()
# logging is required by test_N_file_with_percent