summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--paramiko/client.py6
-rw-r--r--tasks.py33
-rw-r--r--tests/test_auth.py18
3 files changed, 45 insertions, 12 deletions
diff --git a/paramiko/client.py b/paramiko/client.py
index 6f0cb847..de0a495e 100644
--- a/paramiko/client.py
+++ b/paramiko/client.py
@@ -463,6 +463,9 @@ class SSHClient (ClosingContextManager):
Python
:param int timeout:
set command's channel timeout. See `.Channel.settimeout`
+ :param bool get_pty:
+ Request a pseudo-terminal from the server (default ``False``).
+ See `.Channel.get_pty`
:param dict environment:
a dict of shell environment variables, to be merged into the
default environment that the remote command executes within.
@@ -476,6 +479,9 @@ class SSHClient (ClosingContextManager):
3-tuple
:raises: `.SSHException` -- if the server fails to execute the command
+
+ .. versionchanged:: 1.10
+ Added the ``get_pty`` kwarg.
"""
chan = self._transport.open_session(timeout=timeout)
if get_pty:
diff --git a/tasks.py b/tasks.py
index 3b34818c..d5ed25b1 100644
--- a/tasks.py
+++ b/tasks.py
@@ -8,8 +8,21 @@ from invocations.packaging.release import ns as release_coll, publish
from invocations.testing import count_errors
+# TODO: this screams out for the invoke missing-feature of "I just wrap task X,
+# assume its signature by default" (even if that is just **kwargs support)
@task
-def test(ctx, verbose=True, coverage=False, include_slow=False, opts=""):
+def test(
+ ctx,
+ verbose=True,
+ color=True,
+ capture='sys',
+ module=None,
+ k=None,
+ x=False,
+ opts="",
+ coverage=False,
+ include_slow=False,
+):
"""
Run unit tests via pytest.
@@ -20,14 +33,28 @@ def test(ctx, verbose=True, coverage=False, include_slow=False, opts=""):
"""
if verbose and '--verbose' not in opts and '-v' not in opts:
opts += " --verbose"
+ # TODO: forget why invocations.pytest added this; is it to force color when
+ # running headless? Probably?
+ if color:
+ opts += " --color=yes"
+ opts += ' --capture={0}'.format(capture)
if '-m' not in opts and not include_slow:
opts += " -m 'not slow'"
+ if k is not None and not ('-k' in opts if opts else False):
+ opts += ' -k {}'.format(k)
+ if x and not ('-x' in opts if opts else False):
+ opts += ' -x'
+ modstr = ""
+ if module is not None:
+ # NOTE: implicit test_ prefix as we're not on pytest-relaxed yet
+ modstr = " tests/test_{}.py".format(module)
+ # Switch runner depending on coverage or no coverage.
+ # TODO: get pytest's coverage plugin working, IIRC it has issues?
runner = "pytest"
if coverage:
# Leverage how pytest can be run as 'python -m pytest', and then how
# coverage can be told to run things in that manner instead of
# expecting a literal .py file.
- # TODO: get pytest's coverage plugin working, IIRC it has issues?
runner = "coverage run --source=paramiko -m pytest"
# Strip SSH_AUTH_SOCK from parent env to avoid pollution by interactive
# users.
@@ -37,7 +64,7 @@ def test(ctx, verbose=True, coverage=False, include_slow=False, opts=""):
env = dict(os.environ)
if 'SSH_AUTH_SOCK' in env:
del env['SSH_AUTH_SOCK']
- cmd = "{} {}".format(runner, opts)
+ cmd = "{} {} {}".format(runner, opts, modstr)
# NOTE: we have a pytest.ini and tend to use that over PYTEST_ADDOPTS.
ctx.run(cmd, pty=True, env=env, replace_env=True)
diff --git a/tests/test_auth.py b/tests/test_auth.py
index 4eade610..dacdd654 100644
--- a/tests/test_auth.py
+++ b/tests/test_auth.py
@@ -133,7 +133,7 @@ class AuthTest (unittest.TestCase):
self.assertTrue(self.event.is_set())
self.assertTrue(self.ts.is_active())
- def test_1_bad_auth_type(self):
+ def test_bad_auth_type(self):
"""
verify that we get the right exception when an unsupported auth
type is requested.
@@ -148,7 +148,7 @@ class AuthTest (unittest.TestCase):
self.assertEqual(BadAuthenticationType, etype)
self.assertEqual(['publickey'], evalue.allowed_types)
- def test_2_bad_password(self):
+ def test_bad_password(self):
"""
verify that a bad password gets the right exception, and that a retry
with the right password works.
@@ -164,7 +164,7 @@ class AuthTest (unittest.TestCase):
self.tc.auth_password(username='slowdive', password='pygmalion')
self.verify_finished()
- def test_3_multipart_auth(self):
+ def test_multipart_auth(self):
"""
verify that multipart auth works.
"""
@@ -177,7 +177,7 @@ class AuthTest (unittest.TestCase):
self.assertEqual([], remain)
self.verify_finished()
- def test_4_interactive_auth(self):
+ def test_interactive_auth(self):
"""
verify keyboard-interactive auth works.
"""
@@ -195,7 +195,7 @@ class AuthTest (unittest.TestCase):
self.assertEqual([], remain)
self.verify_finished()
- def test_5_interactive_auth_fallback(self):
+ def test_interactive_auth_fallback(self):
"""
verify that a password auth attempt will fallback to "interactive"
if password auth isn't supported but interactive is.
@@ -206,7 +206,7 @@ class AuthTest (unittest.TestCase):
self.assertEqual([], remain)
self.verify_finished()
- def test_6_auth_utf8(self):
+ def test_auth_utf8(self):
"""
verify that utf-8 encoding happens in authentication.
"""
@@ -216,7 +216,7 @@ class AuthTest (unittest.TestCase):
self.assertEqual([], remain)
self.verify_finished()
- def test_7_auth_non_utf8(self):
+ def test_auth_non_utf8(self):
"""
verify that non-utf-8 encoded passwords can be used for broken
servers.
@@ -227,7 +227,7 @@ class AuthTest (unittest.TestCase):
self.assertEqual([], remain)
self.verify_finished()
- def test_8_auth_gets_disconnected(self):
+ def test_auth_gets_disconnected(self):
"""
verify that we catch a server disconnecting during auth, and report
it as an auth failure.
@@ -241,7 +241,7 @@ class AuthTest (unittest.TestCase):
self.assertTrue(issubclass(etype, AuthenticationException))
@slow
- def test_9_auth_non_responsive(self):
+ def test_auth_non_responsive(self):
"""
verify that authentication times out if server takes to long to
respond (or never responds).