speedtest-ssh 2.8.0__tar.gz → 2.9.0__tar.gz
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.
- {speedtest_ssh-2.8.0/speedtest_ssh.egg-info → speedtest_ssh-2.9.0}/PKG-INFO +1 -1
- {speedtest_ssh-2.8.0 → speedtest_ssh-2.9.0}/pyproject.toml +7 -0
- speedtest_ssh-2.9.0/speedtest_ssh/_version.py +1 -0
- {speedtest_ssh-2.8.0 → speedtest_ssh-2.9.0}/speedtest_ssh/data_transfer.py +9 -3
- {speedtest_ssh-2.8.0 → speedtest_ssh-2.9.0}/speedtest_ssh/speedtest_ssh.py +36 -39
- {speedtest_ssh-2.8.0 → speedtest_ssh-2.9.0}/speedtest_ssh/util.py +4 -4
- {speedtest_ssh-2.8.0 → speedtest_ssh-2.9.0/speedtest_ssh.egg-info}/PKG-INFO +1 -1
- speedtest_ssh-2.8.0/speedtest_ssh/_version.py +0 -1
- {speedtest_ssh-2.8.0 → speedtest_ssh-2.9.0}/LICENSE +0 -0
- {speedtest_ssh-2.8.0 → speedtest_ssh-2.9.0}/README.md +0 -0
- {speedtest_ssh-2.8.0 → speedtest_ssh-2.9.0}/setup.cfg +0 -0
- {speedtest_ssh-2.8.0 → speedtest_ssh-2.9.0}/speedtest_ssh/__init__.py +0 -0
- {speedtest_ssh-2.8.0 → speedtest_ssh-2.9.0}/speedtest_ssh/config.py +0 -0
- {speedtest_ssh-2.8.0 → speedtest_ssh-2.9.0}/speedtest_ssh/ping.py +0 -0
- {speedtest_ssh-2.8.0 → speedtest_ssh-2.9.0}/speedtest_ssh/py.typed +0 -0
- {speedtest_ssh-2.8.0 → speedtest_ssh-2.9.0}/speedtest_ssh/sftp_wrapper.py +0 -0
- {speedtest_ssh-2.8.0 → speedtest_ssh-2.9.0}/speedtest_ssh.egg-info/SOURCES.txt +0 -0
- {speedtest_ssh-2.8.0 → speedtest_ssh-2.9.0}/speedtest_ssh.egg-info/dependency_links.txt +0 -0
- {speedtest_ssh-2.8.0 → speedtest_ssh-2.9.0}/speedtest_ssh.egg-info/entry_points.txt +0 -0
- {speedtest_ssh-2.8.0 → speedtest_ssh-2.9.0}/speedtest_ssh.egg-info/requires.txt +0 -0
- {speedtest_ssh-2.8.0 → speedtest_ssh-2.9.0}/speedtest_ssh.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__: str = "2.9.0"
|
|
@@ -22,6 +22,13 @@ if TYPE_CHECKING:
|
|
|
22
22
|
__all__ = ("DataTransfer", "SFTP", "Rsync")
|
|
23
23
|
|
|
24
24
|
|
|
25
|
+
_dict = string.ascii_uppercase + string.ascii_lowercase + string.digits
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _rand_str(size: int) -> str:
|
|
29
|
+
return "".join(random.choice(_dict) for _ in range(size)) # nosec B311
|
|
30
|
+
|
|
31
|
+
|
|
25
32
|
class ProgressBar(tqdm):
|
|
26
33
|
"""
|
|
27
34
|
A small tqdm wrapper for paramiko's SFTP callbacks to use
|
|
@@ -43,7 +50,7 @@ class ProgressBar(tqdm):
|
|
|
43
50
|
|
|
44
51
|
class DataTransfer:
|
|
45
52
|
"""
|
|
46
|
-
A context
|
|
53
|
+
A context manager used to send and receive data to and from the remote client
|
|
47
54
|
This class is a context manager; on exit will remove the remote file on deletion
|
|
48
55
|
"""
|
|
49
56
|
|
|
@@ -54,8 +61,7 @@ class DataTransfer:
|
|
|
54
61
|
:param config: The Config object the DataTransfer instance should use
|
|
55
62
|
"""
|
|
56
63
|
self._l = getLogger(self._LOG)
|
|
57
|
-
|
|
58
|
-
self._remote_f: str = f"/tmp/speedtest-ssh_{datetime.now()}_{''.join(rand() for _ in range(8))}.tmp"
|
|
64
|
+
self._remote_f: str = f"/tmp/speedtest-ssh_{datetime.now()}_{_rand_str(8)}.tmp"
|
|
59
65
|
self._remote_f = self._remote_f.replace(":", "-").replace(" ", "_")
|
|
60
66
|
# We promise that _remote_f components match: ^[a-zA-Z\d_.-]+$ (old rsync args suck)
|
|
61
67
|
self._l.debug("Parsing ssh config and loading keys...")
|
|
@@ -5,7 +5,6 @@ from pathlib import Path
|
|
|
5
5
|
import argparse
|
|
6
6
|
import math
|
|
7
7
|
import time
|
|
8
|
-
import sys
|
|
9
8
|
import os
|
|
10
9
|
|
|
11
10
|
from .config import Config
|
|
@@ -15,7 +14,8 @@ from ._version import __version__
|
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
base_size = 2 * (1024**2)
|
|
18
|
-
_password_env_name = "SPEEDTEST_SSH_PASSWORD"
|
|
17
|
+
_password_env_name = "SPEEDTEST_SSH_PASSWORD" # nosec B105
|
|
18
|
+
_LOG_VERBOSITY: dict[int, int] = {0: WARNING, 1: INFO, 2: DEBUG}
|
|
19
19
|
_LOG = "speedtest_ssh"
|
|
20
20
|
|
|
21
21
|
|
|
@@ -63,7 +63,7 @@ def _print_results(ping_delay: float | None, up_ns: int, down_ns: int, size: int
|
|
|
63
63
|
print(f"{prefix}Upload Speed: {fmt(up_ns)}\nDownload Speed: {fmt(down_ns)}")
|
|
64
64
|
|
|
65
65
|
|
|
66
|
-
def speedtest_ssh(
|
|
66
|
+
def speedtest_ssh(seconds: int, ping: bool, mode: str, conf: Config) -> None:
|
|
67
67
|
"""
|
|
68
68
|
Run speedtest_ssh
|
|
69
69
|
"""
|
|
@@ -78,7 +78,7 @@ def speedtest_ssh(num_seconds: int, ping: bool, mode: str, conf: Config) -> None
|
|
|
78
78
|
print("Testing...")
|
|
79
79
|
nano_sec: int = 0
|
|
80
80
|
size: int = base_size
|
|
81
|
-
remaining: int = int(1e9) *
|
|
81
|
+
remaining: int = int(1e9) * seconds
|
|
82
82
|
while int(1.5 * nano_sec) < remaining - 1: # Try to get close to seconds
|
|
83
83
|
size *= 2 ** (0 if not nano_sec else max(1, int(math.log(remaining / nano_sec, 2))))
|
|
84
84
|
# ^ Faster than just *=2
|
|
@@ -89,51 +89,48 @@ def speedtest_ssh(num_seconds: int, ping: bool, mode: str, conf: Config) -> None
|
|
|
89
89
|
_print_results(ping_delay, up_t, down_t, size)
|
|
90
90
|
|
|
91
91
|
|
|
92
|
-
def
|
|
92
|
+
def cli() -> None:
|
|
93
93
|
"""
|
|
94
|
-
speedtest_ssh
|
|
94
|
+
speedtest_ssh main
|
|
95
95
|
"""
|
|
96
|
-
|
|
97
|
-
parser =
|
|
98
|
-
parser.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
96
|
+
parser = argparse.ArgumentParser()
|
|
97
|
+
parser.add_argument("-V", "--version", action="version", version=f"{parser.prog} {__version__}")
|
|
98
|
+
remote = parser.add_argument_group("SSH Options")
|
|
99
|
+
remote.add_argument("host", help="The host to speedtest the conection to")
|
|
100
|
+
remote.add_argument("-u", "--user", help="The user used for ssh")
|
|
101
|
+
remote.add_argument("-p", "--port", type=int, help="The port used for ssh")
|
|
102
|
+
remote.add_argument(
|
|
103
|
+
"-E",
|
|
104
|
+
"--password-env",
|
|
105
|
+
action="store_true",
|
|
106
|
+
help=f"Read password from {_password_env_name} environment variable",
|
|
106
107
|
)
|
|
107
|
-
parser.add_argument("-p", "--port", type=int, help="The port used for ssh")
|
|
108
108
|
parser.add_argument(
|
|
109
|
-
"
|
|
109
|
+
"-v",
|
|
110
|
+
"--verbose",
|
|
111
|
+
action="count",
|
|
112
|
+
default=0,
|
|
113
|
+
help="Increase Log verbosity, pass more than once to increase verbosity",
|
|
110
114
|
)
|
|
111
|
-
parser.
|
|
115
|
+
modes = parser.add_argument_group("SpeedTest Options")
|
|
116
|
+
modes.add_argument("-P", "--ping", action="store_true", help="Ping test the host as well")
|
|
117
|
+
modes.add_argument(
|
|
118
|
+
"-s", "--seconds", type=int, default=20, help="An approximate number of seconds the speed tests should take"
|
|
119
|
+
)
|
|
120
|
+
modes.add_argument(
|
|
112
121
|
"-m", "--mode", choices=["rsync", "sftp"], default="sftp", help="The speedtest method. Defaults to rsync"
|
|
113
122
|
)
|
|
114
|
-
ns = vars(parser.parse_args(
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
log.debug("Very verbose logging enabled")
|
|
123
|
+
ns = vars(parser.parse_args())
|
|
124
|
+
# Configure logging
|
|
125
|
+
lvl = ns.pop("verbose")
|
|
126
|
+
lvl = _LOG_VERBOSITY[max(i for i in _LOG_VERBOSITY if i <= lvl)]
|
|
127
|
+
basicConfig(level=lvl, format="%(levelname)-8s %(message)s")
|
|
128
|
+
getLogger("main").debug("Log level set to %d", lvl)
|
|
129
|
+
# Call speedtest
|
|
122
130
|
ns["password"] = None
|
|
123
131
|
if ns.pop("password_env"):
|
|
124
132
|
ns["password"] = os.environ.get(_password_env_name, None)
|
|
125
133
|
if ns["password"] is None:
|
|
126
134
|
raise RuntimeError(f"{_password_env_name} is not set")
|
|
127
135
|
conf = Config(**{i.name: ns.pop(i.name) for i in fields(Config)}) # type: ignore
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
def cli() -> None:
|
|
132
|
-
"""
|
|
133
|
-
speedtest_ssh CLI
|
|
134
|
-
"""
|
|
135
|
-
main(sys.argv)
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
if __name__ == "__main__":
|
|
139
|
-
cli()
|
|
136
|
+
speedtest_ssh(**ns, conf=conf) # type: ignore
|
|
@@ -43,7 +43,7 @@ def run_cmd(cmd: Path, *args: str | Path, **kwargs) -> subprocess.CompletedProce
|
|
|
43
43
|
:return: Completed process
|
|
44
44
|
"""
|
|
45
45
|
_log_cmd(cmd, args)
|
|
46
|
-
return subprocess.run((cmd, *args), **kwargs)
|
|
46
|
+
return subprocess.run((cmd, *args), **kwargs) # nosec B603
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
def tee_cmd(cmd: Path, *args: str | Path, level: int, **kwargs) -> tuple[subprocess.Popen, str]:
|
|
@@ -54,11 +54,11 @@ def tee_cmd(cmd: Path, *args: str | Path, level: int, **kwargs) -> tuple[subproc
|
|
|
54
54
|
:param kwargs: Fowarded to subprocess.Popen aside from test and stdout
|
|
55
55
|
:return: Completed process, stdout (do not read stdout from CompletedProcess)
|
|
56
56
|
"""
|
|
57
|
-
assert "text" not in kwargs
|
|
58
|
-
assert "stdout" not in kwargs
|
|
57
|
+
assert "text" not in kwargs # nosec B101
|
|
58
|
+
assert "stdout" not in kwargs # nosec B101
|
|
59
59
|
log = getLogger(_LOG)
|
|
60
60
|
_log_cmd(cmd, args)
|
|
61
|
-
p = subprocess.Popen((cmd, *args), text=True, stdout=subprocess.PIPE, **kwargs)
|
|
61
|
+
p = subprocess.Popen((cmd, *args), text=True, stdout=subprocess.PIPE, **kwargs) # nosec B603
|
|
62
62
|
stdout = ""
|
|
63
63
|
for line in p.stdout: # type: ignore
|
|
64
64
|
log.log(level, line[:-1])
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__: str = "2.8.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|