Skip to content

Commit cea687f

Browse files
author
Dan
committed
Added flake8 configuration. Added flake8 test to travis config. Added documentation generation test to travis config. Updates for PEP8 compatibility
1 parent 8e96755 commit cea687f

File tree

8 files changed

+232
-202
lines changed

8 files changed

+232
-202
lines changed

.travis.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ before_install:
1414
- pip install -U pip setuptools
1515
install:
1616
- pip install -r requirements.txt
17-
- pip install coveralls
17+
- pip install coveralls flake8 sphinx
1818
script:
19-
- python setup.py nosetests --with-coverage --cover-package=pssh
19+
- nosetests --with-coverage --cover-package=pssh
20+
- flake8 pssh
21+
- cd doc; make html
2022
after_success:
2123
- coveralls
2224
deploy:

pssh/__init__.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,18 @@
1919

2020
"""Asynchronous parallel SSH client library.
2121
22-
Run SSH commands over many - hundreds/hundreds of thousands - number of servers asynchronously and with minimal system load on the client host.
22+
Run SSH commands over many - hundreds/hundreds of thousands - number of servers
23+
asynchronously and with minimal system load on the client host.
2324
24-
New users should start with :py:func:`pssh.pssh_client.ParallelSSHClient.run_command`
25+
New users should start with
26+
:py:func:`pssh.pssh_client.ParallelSSHClient.run_command`
2527
26-
See also :py:class:`pssh.ParallelSSHClient` and :py:class:mod:`pssh.SSHClient` for class documentation.
28+
See also :py:class:`pssh.ParallelSSHClient` and :py:class:mod:`pssh.SSHClient`
29+
for class documentation.
2730
"""
2831

32+
# flake8: noqa: E402, F401, F402
33+
2934
import logging
3035
from ._version import get_versions
3136
__version__ = get_versions()['version']

pssh/agent.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import paramiko.agent
2121

22+
2223
class SSHAgent(paramiko.agent.AgentSSH):
2324
""":py:class:`paramiko.agent.Agent` compatible class for programmatically
2425
supplying an SSH agent"""

pssh/output.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
class HostOutput(dict):
2727
"""Class to hold host output"""
2828

29-
__slots__ = ('host', 'cmd', 'channel', 'stdout', 'stderr', 'stdin', 'exit_code', 'exception')
29+
__slots__ = ('host', 'cmd', 'channel', 'stdout', 'stderr', 'stdin',
30+
'exit_code', 'exception')
3031

3132
def __init__(self, host, cmd, channel, stdout, stderr, stdin,
3233
exit_code=None, exception=None):
@@ -73,10 +74,11 @@ def update(self, update_dict):
7374

7475
def __repr__(self):
7576
return "{linesep}\thost={host}{linesep}" \
76-
"\texit_code={exit_code}{linesep}" \
77-
"\tcmd={cmd}{linesep}\tchannel={channel}{linesep}" \
78-
"\tstdout={stdout}{linesep}\tstderr={stderr}{linesep}\tstdin={stdin}{linesep}\
79-
\texception={exception}{linesep}".format(
80-
host=self.host, cmd=self.cmd, channel=self.channel, stdout=self.stdout,
81-
stdin=self.stdin, stderr=self.stderr, exception=self.exception,
82-
linesep=linesep, exit_code=self.exit_code)
77+
"\texit_code={exit_code}{linesep}" \
78+
"\tcmd={cmd}{linesep}\tchannel={channel}{linesep}" \
79+
"\tstdout={stdout}{linesep}\tstderr={stderr}{linesep}\tstdin={stdin}{linesep}\
80+
\texception={exception}{linesep}".format(
81+
host=self.host, cmd=self.cmd, channel=self.channel,
82+
stdout=self.stdout, stdin=self.stdin, stderr=self.stderr,
83+
exception=self.exception, linesep=linesep,
84+
exit_code=self.exit_code)

pssh/pssh_client.py

Lines changed: 108 additions & 106 deletions
Large diffs are not rendered by default.

pssh/ssh_client.py

Lines changed: 88 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,10 @@
3737

3838
class SSHClient(object):
3939
"""Wrapper class over paramiko.SSHClient with sane defaults
40-
Honours ~/.ssh/config and /etc/ssh/ssh_config entries for host username \
41-
overrides"""
42-
40+
Honours ``~/.ssh/config`` and ``/etc/ssh/ssh_config`` host entries
41+
for host username overrides
42+
"""
43+
4344
def __init__(self, host,
4445
user=None, password=None, port=None,
4546
pkey=None, forward_ssh_agent=True,
@@ -48,52 +49,51 @@ def __init__(self, host,
4849
proxy_port=22, proxy_user=None, proxy_password=None,
4950
proxy_pkey=None, channel_timeout=None,
5051
_openssh_config_file=None):
51-
"""Connect to host honouring any user set configuration in ~/.ssh/config \
52-
or /etc/ssh/ssh_config
53-
52+
"""
5453
:param host: Hostname to connect to
5554
:type host: str
56-
:param user: (Optional) User to login as. Defaults to logged in user or \
57-
user from ~/.ssh/config if set
55+
:param user: (Optional) User to login as. Defaults to logged in user or
56+
user from ~/.ssh/config if set
5857
:type user: str
59-
:param password: (Optional) Password to use for login. Defaults to\
60-
no password
58+
:param password: (Optional) Password to use for login. Defaults to
59+
no password
6160
:type password: str
62-
:param port: (Optional) Port number to use for SSH connection. Defaults\
63-
to None which uses SSH default
61+
:param port: (Optional) Port number to use for SSH connection. Defaults
62+
to ``None`` which uses SSH default
6463
:type port: int
6564
:param pkey: (Optional) Client's private key to be used to connect with
6665
:type pkey: :py:class:`paramiko.pkey.PKey`
67-
:param num_retries: (Optional) Number of retries for connection attempts\
68-
before the client gives up. Defaults to 3.
66+
:param num_retries: (Optional) Number of retries for connection attempts
67+
before the client gives up. Defaults to 3.
6968
:type num_retries: int
70-
:param timeout: (Optional) Number of seconds to timeout connection attempts\
71-
before the client gives up. Defaults to 10.
69+
:param timeout: (Optional) Number of seconds to timeout connection
70+
attempts before the client gives up
7271
:type timeout: int
73-
:param forward_ssh_agent: (Optional) Turn on SSH agent forwarding - \
74-
equivalent to `ssh -A` from the `ssh` command line utility. \
75-
Defaults to True if not set.
72+
:param forward_ssh_agent: (Optional) Turn on SSH agent forwarding -
73+
equivalent to `ssh -A` from the `ssh` command line utility.
74+
Defaults to True if not set.
7675
:type forward_ssh_agent: bool
77-
:param agent: (Optional) Override SSH agent object with the provided. \
78-
This allows for overriding of the default paramiko behaviour of \
79-
connecting to local SSH agent to lookup keys with our own SSH agent \
80-
object.
76+
:param agent: (Optional) Override SSH agent object with the provided.
77+
This allows for overriding of the default paramiko behaviour of
78+
connecting to local SSH agent to lookup keys with our own SSH agent
79+
object.
8180
:type agent: :py:class:`paramiko.agent.Agent`
82-
:param forward_ssh_agent: (Optional) Turn on SSH agent forwarding - \
83-
equivalent to `ssh -A` from the `ssh` command line utility. \
84-
Defaults to True if not set.
81+
:param forward_ssh_agent: (Optional) Turn on SSH agent forwarding -
82+
equivalent to `ssh -A` from the `ssh` command line utility.
83+
Defaults to True if not set.
8584
:type forward_ssh_agent: bool
86-
:param proxy_host: (Optional) SSH host to tunnel connection through \
87-
so that SSH clients connects to self.host via client -> proxy_host -> host
85+
:param proxy_host: (Optional) SSH host to tunnel connection through
86+
so that SSH clients connects to self.host via
87+
client -> proxy_host -> host
8888
:type proxy_host: str
89-
:param proxy_port: (Optional) SSH port to use to login to proxy host if \
90-
set. Defaults to 22.
89+
:param proxy_port: (Optional) SSH port to use to login to proxy host if
90+
set. Defaults to 22.
9191
:type proxy_port: int
92-
:param channel_timeout: (Optional) Time in seconds before an SSH operation \
93-
times out.
92+
:param channel_timeout: (Optional) Time in seconds before an SSH
93+
operation times out.
9494
:type channel_timeout: int
95-
:param allow_agent: (Optional) set to False to disable connecting to \
96-
the SSH agent
95+
:param allow_agent: (Optional) set to False to disable connecting to
96+
the SSH agent
9797
:type allow_agent: bool
9898
"""
9999
try:
@@ -117,27 +117,29 @@ def __init__(self, host,
117117
self.num_retries = num_retries
118118
self.timeout = timeout
119119
self.channel_timeout = channel_timeout
120-
self.proxy_host, self.proxy_port, self.proxy_user, self.proxy_password, \
121-
self.proxy_pkey = proxy_host, proxy_port, proxy_user, \
122-
proxy_password, proxy_pkey
120+
self.proxy_host, self.proxy_port, self.proxy_user, \
121+
self.proxy_password, self.proxy_pkey = proxy_host, proxy_port, \
122+
proxy_user, proxy_password, proxy_pkey
123123
self.proxy_client = None
124124
if self.proxy_host and self.proxy_port:
125-
logger.debug("Proxy configured for destination host %s - Proxy host: %s:%s",
126-
self.host, self.proxy_host, self.proxy_port,)
125+
logger.debug(
126+
"Proxy configured for destination host %s - Proxy host: %s:%s",
127+
self.host, self.proxy_host, self.proxy_port,)
127128
self._connect_tunnel()
128129
else:
129130
self._connect(self.client, self.host, self.port)
130131

131132
def _connect_tunnel(self):
132133
"""Connects to SSH server via an intermediate SSH tunnel server.
133-
client (me) -> tunnel (ssh server to proxy through) -> \
134-
destination (ssh server to run command)
134+
client (me) -> tunnel (ssh server to proxy through) ->
135+
``self.host`` (ssh server to run command)
135136
136137
:rtype: :py:class:`paramiko.SSHClient` Client to remote SSH destination
137138
via intermediate SSH tunnel server.
138139
"""
139140
self.proxy_client = paramiko.SSHClient()
140-
self.proxy_client.set_missing_host_key_policy(paramiko.MissingHostKeyPolicy())
141+
self.proxy_client.set_missing_host_key_policy(
142+
paramiko.MissingHostKeyPolicy())
141143
self._connect(self.proxy_client, self.proxy_host, self.proxy_port,
142144
user=self.proxy_user, password=self.proxy_password,
143145
pkey=self.proxy_pkey)
@@ -148,21 +150,26 @@ def _connect_tunnel(self):
148150
'direct-tcpip', (self.host, self.port,), ('127.0.0.1', 0),
149151
timeout=self.timeout)
150152
sleep(0)
151-
return self._connect(self.client, self.host, self.port, sock=proxy_channel)
153+
return self._connect(self.client, self.host, self.port,
154+
sock=proxy_channel)
152155
except (ChannelException, paramiko.SSHException) as ex:
153156
error_type = ex.args[1] if len(ex.args) > 1 else ex.args[0]
154-
raise ConnectionErrorException("Error connecting to host '%s:%s' - %s",
155-
self.host, self.port,
156-
str(error_type))
157+
raise ConnectionErrorException(
158+
"Error connecting to host '%s:%s' - %s",
159+
self.host, self.port, str(error_type))
157160

158161
def _connect(self, client, host, port, sock=None, retries=1,
159162
user=None, password=None, pkey=None):
160163
"""Connect to host
161164
162-
:raises: :py:class:`pssh.exceptions.AuthenticationException` on authentication error
163-
:raises: :py:class:`pssh.exceptions.UnknownHostException` on DNS resolution error
164-
:raises: :py:class:`pssh.exceptions.ConnectionErrorException` on error connecting
165-
:raises: :py:class:`pssh.exceptions.SSHException` on other undefined SSH errors
165+
:raises: :py:class:`pssh.exceptions.AuthenticationException`
166+
on authentication error
167+
:raises: :py:class:`pssh.exceptions.UnknownHostException`
168+
on DNS resolution error
169+
:raises: :py:class:`pssh.exceptions.ConnectionErrorException`
170+
on error connecting
171+
:raises: :py:class:`pssh.exceptions.SSHException` on other undefined
172+
SSH errors
166173
"""
167174
try:
168175
client.connect(host, username=user if user else self.user,
@@ -188,9 +195,10 @@ def _connect(self, client, host, port, sock=None, retries=1,
188195
return self._connect(client, host, port, sock=sock,
189196
retries=retries+1)
190197
error_type = ex.args[1] if len(ex.args) > 1 else ex.args[0]
191-
raise ConnectionErrorException("Error connecting to host '%s:%s' - %s - retry %s/%s",
192-
self.host, self.port,
193-
str(error_type), retries, self.num_retries,)
198+
raise ConnectionErrorException(
199+
"Error connecting to host '%s:%s' - %s - retry %s/%s",
200+
self.host, self.port, str(error_type), retries,
201+
self.num_retries,)
194202
except paramiko.AuthenticationException as ex:
195203
msg = "Authentication error while connecting to %s:%s."
196204
raise AuthenticationException(msg, host, port)
@@ -206,43 +214,45 @@ def exec_command(self, command, sudo=False, user=None,
206214
use_shell=True, use_pty=True):
207215
"""Wrapper to :py:func:`paramiko.SSHClient.exec_command`
208216
209-
Opens a new SSH session with a new pty and runs command before yielding
217+
Opens a new SSH session with a new pty and runs command before yielding
210218
the main gevent loop to allow other greenlets to execute.
211219
212220
:param command: Command to execute
213221
:type command: str
214222
:param sudo: (Optional) Run with sudo. Defaults to False
215223
:type sudo: bool
216-
:param user: (Optional) User to switch to via sudo to run command as. \
217-
Defaults to user running the python process
224+
:param user: (Optional) User to switch to via sudo to run command as.
225+
Defaults to user running the python process
218226
:type user: str
219-
:param shell: (Optional) Shell override to use instead of user login \
220-
configured shell. For example ``shell='bash -c'``
221-
:param use_shell: (Optional) Force use of shell on/off. \
222-
Defaults to `True` for on
227+
:param shell: (Optional) Shell override to use instead of user login
228+
configured shell. For example ``shell='bash -c'``
229+
:param use_shell: (Optional) Force use of shell on/off.
230+
Defaults to `True` for on
223231
:type use_shell: bool
224-
:param use_pty: (Optional) Enable/Disable use of pseudo terminal \
225-
emulation. This is required in vast majority of cases, exception \
226-
being where a shell is not used and/or stdout/stderr/stdin buffers \
227-
are not required. Defaults to ``True``
232+
:param use_pty: (Optional) Enable/Disable use of pseudo terminal
233+
emulation. This is required in vast majority of cases, exception
234+
being where a shell is not used and/or stdout/stderr/stdin buffers
235+
are not required. Defaults to ``True``
228236
:type use_pty: bool
229-
:param kwargs: (Optional) Keyword arguments to be passed to remote \
230-
command
237+
:param kwargs: (Optional) Keyword arguments to be passed to remote
238+
command
231239
:type kwargs: dict
232-
:rtype: Tuple of `(channel, hostname, stdout, stderr, stdin)`. \
233-
Channel is the remote SSH channel, needed to ensure all of stdout has \
234-
been got, hostname is remote hostname the copy is to, stdout and \
235-
stderr are buffers containing command output.
240+
:rtype: Tuple of `(channel, hostname, stdout, stderr, stdin)`.
241+
Channel is the remote SSH channel, needed to ensure all of stdout has
242+
been got, hostname is remote hostname the copy is to, stdout and
243+
stderr are buffers containing command output and stdin is standard
244+
input channel
236245
"""
237246
channel = self.client.get_transport().open_session()
238247
if self.forward_ssh_agent:
239-
agent_handler = paramiko.agent.AgentRequestHandler(channel)
248+
agent_handler = paramiko.agent.AgentRequestHandler( # noqa: F841
249+
channel)
240250
if use_pty:
241251
channel.get_pty()
242252
if self.channel_timeout:
243253
channel.settimeout(self.channel_timeout)
244254
stdout, stderr, stdin = channel.makefile('rb'), \
245-
channel.makefile_stderr('rb'), channel.makefile('wb')
255+
channel.makefile_stderr('rb'), channel.makefile('wb')
246256
for _char in ['\\', '"', '$', '`']:
247257
command = command.replace(_char, r'\%s' % (_char,))
248258
shell = '$SHELL -c' if not shell else shell
@@ -353,7 +363,7 @@ def copy_file(self, local_file, remote_file, recurse=False,
353363
sftp=None):
354364
"""Copy local file to host via SFTP/SCP
355365
356-
Copy is done natively using SFTP/SCP version 2 protocol, no scp command \
366+
Copy is done natively using SFTP/SCP version 2 protocol, no scp command
357367
is used or required.
358368
359369
:param local_file: Local filepath to copy to remote host
@@ -363,8 +373,8 @@ def copy_file(self, local_file, remote_file, recurse=False,
363373
:param recurse: Whether or not to descend into directories recursively.
364374
:type recurse: bool
365375
366-
:raises: :py:class:`ValueError` when a directory is supplied to ``local_file`` \
367-
and ``recurse`` is not set
376+
:raises: :py:class:`ValueError` when a directory is supplied to
377+
``local_file`` and ``recurse`` is not set
368378
:raises: :py:class:`IOError` on I/O errors writing files
369379
:raises: :py:class:`OSError` on OS errors like permission denied
370380
"""
@@ -394,7 +404,7 @@ def copy_remote_file(self, remote_file, local_file, recurse=False,
394404
sftp=None):
395405
"""Copy remote file to local host via SFTP/SCP
396406
397-
Copy is done natively using SFTP/SCP version 2, no scp command \
407+
Copy is done natively using SFTP/SCP version 2, no scp command
398408
is used or required.
399409
400410
:param remote_file: Remote filepath to copy from
@@ -404,8 +414,8 @@ def copy_remote_file(self, remote_file, local_file, recurse=False,
404414
:param recurse: Whether or not to recursively copy directories
405415
:type recurse: bool
406416
407-
:raises: :py:class:`ValueError` when a directory is supplied to remote_file \
408-
and recurse is not set
417+
:raises: :py:class:`ValueError` when a directory is supplied to
418+
``local_file`` and ``recurse`` is not set
409419
:raises: :py:class:`IOError` on I/O errors creating directories or file
410420
:raises: :py:class:`OSError` on OS errors like permission denied
411421
"""

0 commit comments

Comments
 (0)