sshreader 6.2.0__py3-none-any.whl → 6.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
sshreader/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """A Python Package for parallelizing ssh connections via threading and multiprocessing.
2
2
  """
3
- # Copyright (C) 2015-2025 Jesse Almanrode
3
+ # Copyright (C) 2015-2026 Jesse Almanrode
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU Lesser General Public License as published by
sshreader/customtypes.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """ Typing module for sshreader
2
2
  """
3
- # Copyright (C) 2015-2025 Jesse Almanrode
3
+ # Copyright (C) 2015-2026 Jesse Almanrode
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU Lesser General Public License as published by
@@ -1,6 +1,6 @@
1
1
  """ Scripts portion of sshreader package
2
2
  """
3
- # Copyright (C) 2015-2025 Jesse Almanrode
3
+ # Copyright (C) 2015-2026 Jesse Almanrode
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU Lesser General Public License as published by
@@ -1,6 +1,6 @@
1
1
  """ A Pythonic implementation of pdsh powered by sshreader
2
2
  """
3
- # Copyright (C) 2015-2025 Jesse Almanrode
3
+ # Copyright (C) 2015-2026 Jesse Almanrode
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU Lesser General Public License as published by
@@ -162,10 +162,11 @@ def cli(**kwargs):
162
162
  if kwargs['file']:
163
163
  mkpath = click.Path(exists=True, dir_okay=False)
164
164
  script_path = mkpath(kwargs['cmd'])
165
- script_name = os.path.split(script_path)[1]
165
+ # Ensure script_path is a str for os.path functions (type-checker safe)
166
+ script_name = os.path.basename(str(script_path))
166
167
  log.info('Creating copy_script prehook for: ' + script_name)
167
168
  prehook = sshreader.Hook(copy_script, args=[script_path], ssh_established=True)
168
- with open(script_path) as s:
169
+ with open(str(script_path)) as s:
169
170
  script = s.readline()
170
171
  if script.startswith('#!') is False:
171
172
  raise click.UsageError('Script must start with #!')
@@ -196,7 +197,7 @@ def cli(**kwargs):
196
197
  kwargs['keyfile'] = sshenv.dsa_key
197
198
  log.info('Using DSA private key file')
198
199
  else:
199
- if len(sshenv.agent_keys) == 0:
200
+ if sshenv.agent_keys is None or len(sshenv.agent_keys) == 0:
200
201
  if not all((kwargs['username'], kwargs['password'])):
201
202
  raise click.ClickException('Unable to find ssh key to use and password not supplied.')
202
203
  else:
@@ -214,7 +215,7 @@ def cli(**kwargs):
214
215
  # If you specify a password or prompt for one it overrides the ssh key
215
216
  if not kwargs['password']:
216
217
  if not kwargs['prompt']:
217
- if not kwargs['keyfile'] and len(sshenv.agent_keys) == 0:
218
+ if not kwargs['keyfile'] and (sshenv.agent_keys is None or len(sshenv.agent_keys) == 0):
218
219
  raise click.ClickException('Unable to find ssh key to use and password not supplied or prompt enabled.')
219
220
  else:
220
221
  log.info('Prompting for password and disabling discovered SSH keyfiles')
sshreader/ssh.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """A wrapper for Paramiko that attempts to make ssh sessions easier to work with.
2
2
  """
3
- # Copyright (C) 2015-2025 Jesse Almanrode
3
+ # Copyright (C) 2015-2026 Jesse Almanrode
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU Lesser General Public License as published by
@@ -173,7 +173,7 @@ class SSH:
173
173
  else:
174
174
  result = Command(cmd=command, stdout=stdout.read().strip(), stderr=None,
175
175
  return_code=stdout.channel.recv_exit_status())
176
- except (paramiko.buffered_pipe.PipeTimeout, socket.timeout):
176
+ except (paramiko.buffered_pipe.PipeTimeout, socket.timeout): # ty:ignore[possibly-missing-submodule]
177
177
  result = Command(cmd=command, stdout='command timed out', stderr=None, return_code=124)
178
178
  else:
179
179
  try:
@@ -184,7 +184,7 @@ class SSH:
184
184
  else:
185
185
  result = Command(cmd=command, stdout=stdout.read().strip(), stderr=stderr.read().strip(),
186
186
  return_code=stdout.channel.recv_exit_status())
187
- except (paramiko.buffered_pipe.PipeTimeout, socket.timeout):
187
+ except (paramiko.buffered_pipe.PipeTimeout, socket.timeout): # ty:ignore[possibly-missing-submodule]
188
188
  result = Command(cmd=command, stdout='', stderr='command timed out', return_code=124)
189
189
  return result
190
190
 
@@ -226,7 +226,7 @@ class SSH:
226
226
  """
227
227
  if self.__alive():
228
228
  raise paramiko.SSHException(f"connection to {self.host} already established")
229
- paramiko.util.logging.getLogger().setLevel(logging.CRITICAL) # Keeping paramiko from logging errors to stdout
229
+ paramiko.util.logging.getLogger().setLevel(logging.CRITICAL) # Keeping paramiko from logging errors to stdout # ty:ignore[possibly-missing-submodule]
230
230
  if not self.keyfile and len(paramiko.Agent().get_keys()) == 0 and not all((self.username, self.password)):
231
231
  paramiko.SSHException('username and password or keyfile not provided')
232
232
  if self.keyfile:
sshreader/utils.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """ All the classes and functions that make sshreader tick
2
2
  """
3
- # Copyright (C) 2015-2025 Jesse Almanrode
3
+ # Copyright (C) 2015-2026 Jesse Almanrode
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU Lesser General Public License as published by
@@ -175,8 +175,8 @@ class ServerJob:
175
175
  self.ssh_timeout = timeout[0]
176
176
  self.cmd_timeout = timeout[1]
177
177
  else:
178
- self.ssh_timeout = timeout
179
- self.cmd_timeout = timeout
178
+ self.ssh_timeout = timeout if timeout is not None else 0.5
179
+ self.cmd_timeout = timeout if timeout is not None else 0.5
180
180
  if pre_hook:
181
181
  if isinstance(pre_hook, Hook):
182
182
  self.pre_hook = pre_hook
@@ -220,8 +220,8 @@ class ServerJob:
220
220
  log.debug(f'{self.name}: running prehook')
221
221
  self.pre_hook.run(self)
222
222
  try:
223
- self._conn = SSH(self.name, username=self.username, password=self.password, keyfile=self.key,
224
- port=self.ssh_port, connect=False, rsa_sha2=self.rsa_sha2)
223
+ self._conn = SSH(self.name, username=self.username or '', password=self.password or '', keyfile=self.key,
224
+ port=self.ssh_port, connect=False, rsa_sha2=self.rsa_sha2 or True)
225
225
  self._conn.connect(timeout=self.ssh_timeout)
226
226
  log.debug(f'{self.name}: ssh connection established')
227
227
  except Exception as errorMsg:
@@ -354,7 +354,7 @@ def sshread(serverjobs: list, pcount: Optional[int] = None, tcount: Optional[int
354
354
 
355
355
  if pcount is None:
356
356
  # Limit the number of threads to spawn
357
- if tcount == 0:
357
+ if tcount == 0 or tcount is None:
358
358
  tcount = int(min(totaljobs, cpu_limit()))
359
359
  else:
360
360
  tcount = int(min(tcount, totaljobs))
@@ -399,10 +399,10 @@ def sshread(serverjobs: list, pcount: Optional[int] = None, tcount: Optional[int
399
399
  log.debug(f'main waiting for {totaljobs} ServerJobs to finish')
400
400
  while result_queue.full() is False:
401
401
  if progress_bar:
402
- bar.update(item_counter.value)
402
+ bar.update(item_counter.value) # ty:ignore[unresolved-attribute]
403
403
  time.sleep(1)
404
404
  if progress_bar:
405
- bar.finish()
405
+ bar.finish() # ty:ignore[unresolved-attribute]
406
406
 
407
407
  if len(threads) > 0:
408
408
  log.info(f'joining {len(threads)} threads')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sshreader
3
- Version: 6.2.0
3
+ Version: 6.3.0
4
4
  Summary: Multi-threading/processing wrapper for Paramiko
5
5
  Author-Email: Jesse Almanrode <jesse@almanrode.com>
6
6
  License: LGPL-3.0-or-later
@@ -14,6 +14,7 @@ Classifier: Programming Language :: Python :: 3.10
14
14
  Classifier: Programming Language :: Python :: 3.11
15
15
  Classifier: Programming Language :: Python :: 3.12
16
16
  Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
17
18
  Classifier: Topic :: Software Development :: Libraries
18
19
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
20
  Project-URL: homepage, http://sshreader.readthedocs.io/
@@ -28,6 +29,8 @@ Description-Content-Type: text/markdown
28
29
 
29
30
  ![logo](./logo.png)
30
31
 
32
+ [![Python Tests](https://github.com/isaiah1112/sshreader/actions/workflows/lint_and_test.yml/badge.svg)](https://github.com/isaiah1112/sshreader/actions/workflows/lint_and_test.yml)
33
+
31
34
  A Python Module for multiprocessing/threading ssh connections in order to make ssh operations
32
35
  across multiple servers parallel. It utilizes the [Paramiko](http://www.paramiko.org/) module
33
36
  for its ssh client.
@@ -62,14 +65,13 @@ The documentation for [SSHreader][] can be found at [ReadTheDocs.](https://sshre
62
65
 
63
66
  Comments and enhancements are very welcome.
64
67
 
65
- Report any issues or feature requests on the [BitBucket bug
66
- tracker](https://bitbucket.org/isaiah1112/sshreader/issues?status=new&status=open). Please include a minimal
67
- not-working example which reproduces the bug and, if appropriate, the
68
+ Report any issues or feature requests on the [GitHub Issue Tracker](https://github.com/isaiah1112/sshreader/issues).
69
+ Please include a minimal not-working example which reproduces the bug and, if appropriate, the
68
70
  traceback information. Please do not request features already being worked
69
71
  towards.
70
72
 
71
- Code contributions are encouraged: please feel free to [fork the
72
- project](https://bitbucket.org/isaiah1112/sshreader) and submit pull requests to the develop branch.
73
+ Code contributions are encouraged: please feel free to [fork the project](https://github.com/isaiah1112/sshreader)
74
+ and submit pull requests to the develop branch.
73
75
 
74
76
  ## Extras
75
77
 
@@ -83,4 +85,4 @@ to process.
83
85
 
84
86
  [GNU Lesser General Public License v3.0]: http://choosealicense.com/licenses/lgpl-3.0/ "LGPL v3"
85
87
 
86
- [sshreader]: https://bitbucket.org/isaiah1112/sshreader "SSHreader Package"
88
+ [sshreader]: https://github.com/isaiah1112/sshreader "SSHreader Package"
@@ -0,0 +1,12 @@
1
+ sshreader-6.3.0.dist-info/METADATA,sha256=rb29O02Udv-7Lw44KoBBBVOQGTjxnjWzGxpmWIIF4kw,3537
2
+ sshreader-6.3.0.dist-info/WHEEL,sha256=VP-D4TPS230sME9Z3vb3INXvo1yt0924YRm5AOsk_dE,90
3
+ sshreader-6.3.0.dist-info/entry_points.txt,sha256=5sY9LSL2Kye-5-JPL7AxOg0rzO54pJlleg8egd6mCVI,70
4
+ sshreader-6.3.0.dist-info/licenses/LICENSE,sha256=WJ7YI-moTFb-uVrFjnzzhGJrnL9P2iqQe8NuED3hutI,35141
5
+ sshreader-6.3.0.dist-info/licenses/LICENSE.lesser,sha256=2n6rt7r999OuXp8iOqW9we7ORaxWncIbOwN1ILRGR2g,7651
6
+ sshreader/__init__.py,sha256=mmg2iie23DpPGkRK6IWwaps3WuAQSJbn4yNp0yrRHDY,1451
7
+ sshreader/customtypes.py,sha256=Q08Ot2aMWxOcLhCLMnWlrwYhOQZ1qAlz6D71E1Ek2nw,1205
8
+ sshreader/scripts/__init__.py,sha256=r94LFIDjlTYga-MaX2nVBBIM11v0lTd5xtA-Gcm6QMk,858
9
+ sshreader/scripts/pydsh.py,sha256=f230Znuqx5acE88gvU5nsKzd8G1tqR2WhKyFN7PJcV8,11177
10
+ sshreader/ssh.py,sha256=dPrZjYHrupgbqhng9uCJq8do0R6mqDePYFIjwUboXJE,11158
11
+ sshreader/utils.py,sha256=NYeXRXkYq6w4jgc0_It6hPUcRUXG3RMdoBLgrnjo_nM,18830
12
+ sshreader-6.3.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: pdm-backend (2.4.5)
2
+ Generator: pdm-backend (2.4.9)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,12 +0,0 @@
1
- sshreader-6.2.0.dist-info/METADATA,sha256=SRoUSuMSWnLZu5V2yzrcFzYJJ4t1Z7YHtX3LQ59Mz9A,3334
2
- sshreader-6.2.0.dist-info/WHEEL,sha256=9P2ygRxDrTJz3gsagc0Z96ukrxjr-LFBGOgv3AuKlCA,90
3
- sshreader-6.2.0.dist-info/entry_points.txt,sha256=5sY9LSL2Kye-5-JPL7AxOg0rzO54pJlleg8egd6mCVI,70
4
- sshreader-6.2.0.dist-info/licenses/LICENSE,sha256=WJ7YI-moTFb-uVrFjnzzhGJrnL9P2iqQe8NuED3hutI,35141
5
- sshreader-6.2.0.dist-info/licenses/LICENSE.lesser,sha256=2n6rt7r999OuXp8iOqW9we7ORaxWncIbOwN1ILRGR2g,7651
6
- sshreader/__init__.py,sha256=lbM35O7ANOPaSbJzPA8DuXJQDCyBGTmkysQPtARD6j4,1451
7
- sshreader/customtypes.py,sha256=kNNT5_NaSl_dBOdQ1ucHy_1Wm_H8-CUy_HT0RdWwFX8,1205
8
- sshreader/scripts/__init__.py,sha256=XJmUL-cn63rXHtkLoF5jY3z0gL5qEF0b50JdkgO8Nhs,858
9
- sshreader/scripts/pydsh.py,sha256=rbXinOe89rq6rK0XSS227mwegl1esssX_LT5etz92Qc,11027
10
- sshreader/ssh.py,sha256=K7uYXn4AFsPH_suCCOGu9m2BBaThAiXW4Do8BN0d8fQ,11035
11
- sshreader/utils.py,sha256=TR_G_ndN5WiKxUv7d-KfNwbgg1LzPxVgWWDknqzqqvU,18658
12
- sshreader-6.2.0.dist-info/RECORD,,