tests: improve exception handling in Python test code
No binary (build failed)
—
(log yok)
| @@ -101,8 +101,8 @@ class DictHandler(socketserver.BaseRequestHandler): | |
| log.debug("[DICT] Responding with %r", response) | |
| self.request.sendall(response.encode("utf-8")) | |
| - | except IOError: |
| - | log.exception("[DICT] IOError hit during request") |
| + | except OSError: |
| + | log.exception("[DICT] OSError hit during request") |
| def get_options(): | |
| @@ -148,7 +148,7 @@ class Card: | |
| def parse_size(cls, s): | |
| m = re.match(r'(\d+)(mb|kb|gb)?', s, re.IGNORECASE) | |
| if m is None: | |
| - | raise Exception(f'unrecognized size: {s}') |
| + | raise ScoreCardError(f'unrecognized size: {s}') |
| size = int(m.group(1)) | |
| if not m.group(2): | |
| pass | |
| @@ -263,7 +263,7 @@ class ScoreRunner: | |
| if self._limit_rate: | |
| m = re.match(r'(\d+(\.\d+)?)([gmkb])?', self._limit_rate.lower()) | |
| if not m: | |
| - | raise Exception(f'unrecognised limit-rate: {self._limit_rate}') |
| + | raise ScoreCardError(f'unrecognised limit-rate: {self._limit_rate}') |
| self._limit_rate_num = float(m.group(1)) | |
| if m.group(3) == 'g': | |
| self._limit_rate_num *= 1024 * 1024 * 1024 | |
| @@ -274,7 +274,7 @@ class ScoreRunner: | |
| elif m.group(3) == 'b': | |
| pass | |
| else: | |
| - | raise Exception(f'unrecognised limit-rate: {self._limit_rate}') |
| + | raise ScoreCardError(f'unrecognised limit-rate: {self._limit_rate}') |
| self.suppress_cl = suppress_cl | |
| def info(self, msg): | |
| @@ -24,6 +24,7 @@ | |
| # | |
| ########################################################################### | |
| # | |
| + | import contextlib |
| import logging | |
| import os | |
| import socket | |
| @@ -192,13 +193,11 @@ class TestErrors: | |
| # accept one connection and immediately close it | |
| def accept_and_close(): | |
| - | try: |
| + | # ignore expected socket error |
| + | with contextlib.suppress(OSError): |
| conn, _ = server.accept() | |
| conn.recv(1) # wait for ClientHello | |
| conn.close() | |
| - | except Exception: |
| - | # ignore expected socket error |
| - | pass |
| t = threading.Thread(target=accept_and_close) | |
| t.start() | |
| @@ -82,9 +82,7 @@ Content-Length: 19 | |
| finally: | |
| c.close() | |
| - | except ConnectionAbortedError: |
| - | self._done = True |
| - | except OSError: |
| + | except (ConnectionAbortedError, OSError): |
| self._done = True | |
| @@ -125,7 +125,7 @@ class Caddy: | |
| self._process.terminate() | |
| try: | |
| self._process.wait(timeout=1) | |
| - | except Exception: |
| + | except subprocess.TimeoutExpired: |
| self._process.kill() | |
| self._process = None | |
| self.close_log() | |
| @@ -57,6 +57,10 @@ EC_SUPPORTED.update([(curve.name.upper(), curve) for curve in [ | |
| ]]) | |
| + | class CertError(Exception): |
| + | """Error in certificate handling.""" |
| + | |
| + | |
| def _private_key(key_type): | |
| if isinstance(key_type, str): | |
| key_type = key_type.upper() | |
| @@ -150,7 +154,7 @@ class Credentials: | |
| return f"rsa{self._pkey.key_size}" | |
| if isinstance(self._pkey, EllipticCurvePrivateKey): | |
| return f"{self._pkey.curve.name}" | |
| - | raise Exception(f"unknown key type: {self._pkey}") |
| + | raise CertError(f"unknown key type: {self._pkey}") |
| @property | |
| def private_key(self) -> Any: | |
| @@ -249,9 +253,7 @@ class Credentials: | |
| os.makedirs(self.hashdir, exist_ok=True) | |
| p = subprocess.run(args=[ | |
| openssl, 'x509', '-hash', '-noout', '-in', self.cert_file | |
| - | ], capture_output=True, text=True) |
| - | if p.returncode != 0: |
| - | raise Exception(f'openssl failed to compute cert hash: {p}') |
| + | ], capture_output=True, text=True, check=True) |
| cert_hname = f'{p.stdout.strip()}.0' | |
| shutil.copy(self.cert_file, os.path.join(self.hashdir, cert_hname)) | |
| @@ -401,7 +403,7 @@ class TestCA: | |
| valid_from=valid_from, valid_to=valid_to, | |
| key_type=key_type) | |
| else: | |
| - | raise Exception(f"unrecognized certificate specification: {spec}") |
| + | raise CertError(f"unrecognized certificate specification: {spec}") |
| return creds | |
| @staticmethod | |
| @@ -98,7 +98,7 @@ class LocalClient: | |
| p = subprocess.run(myargs, stderr=cerr, stdout=cout, | |
| cwd=self._run_dir, shell=False, | |
| input=None, env=run_env, | |
| - | timeout=self._timeout) |
| + | timeout=self._timeout, check=False) |
| exitcode = p.returncode | |
| except subprocess.TimeoutExpired: | |
| log.warning(f'Timeout after {self._timeout}s: {args}') | |
| @@ -24,6 +24,7 @@ | |
| # | |
| ########################################################################### | |
| # | |
| + | import contextlib |
| import json | |
| import logging | |
| import os | |
| @@ -41,7 +42,7 @@ from urllib.parse import urlparse | |
| import psutil | |
| - | from .env import Env |
| + | from .env import Env, EnvError |
| log = logging.getLogger(__name__) | |
| @@ -133,12 +134,9 @@ class PerfProfile: | |
| self._proc.terminate() | |
| self._rc = self._proc.returncode | |
| with open(self._file, 'w') as cout: | |
| - | p = subprocess.run([ |
| + | subprocess.run([ |
| 'sudo', 'perf', 'script' | |
| - | ], stdout=cout, cwd=self._run_dir, shell=False) |
| - | rc = p.returncode |
| - | if rc != 0: |
| - | raise Exception(f'perf returned error {rc}') |
| + | ], stdout=cout, cwd=self._run_dir, shell=False, check=True) |
| @property | |
| def file(self): | |
| @@ -192,7 +190,7 @@ class RunTcpDump: | |
| port_pairs: Optional[List[Tuple[int, int]]] = None | |
| ) -> Optional[List[str]]: | |
| if self._proc: | |
| - | raise Exception('tcpdump still running') |
| + | raise EnvError('tcpdump still running') |
| # a pair matches only a RST between exactly these two ports, while | |
| # a port in `ports` matches any RST it is involved in | |
| pairs = None | |
| @@ -222,7 +220,7 @@ class RunTcpDump: | |
| @property | |
| def stderr(self) -> List[str]: | |
| if self._proc: | |
| - | raise Exception('tcpdump still running') |
| + | raise EnvError('tcpdump still running') |
| with open(self._stderrfile) as fd: | |
| return fd.readlines() | |
| @@ -232,7 +230,7 @@ class RunTcpDump: | |
| try: | |
| tcpdump = self._env.tcpdump() | |
| if tcpdump is None: | |
| - | raise Exception('tcpdump not available') |
| + | raise EnvError('tcpdump not available') |
| # look with tcpdump for TCP RST packets which indicate | |
| # we did not shut down connections cleanly | |
| args = [] | |
| @@ -249,11 +247,9 @@ class RunTcpDump: | |
| assert self._proc | |
| assert self._proc.returncode is None | |
| while self._proc: | |
| - | try: |
| + | # timeout means tcpdump is still running |
| + | with contextlib.suppress(subprocess.TimeoutExpired): |
| self._proc.wait(timeout=1) | |
| - | except subprocess.TimeoutExpired: |
| - | # timeout means tcpdump is still running |
| - | pass |
| except Exception: | |
| log.exception('Tcpdump') | |
| @@ -649,13 +645,13 @@ class CurlClient: | |
| if 'FLAMEGRAPH' in os.environ: | |
| self._fg_dir = os.environ['FLAMEGRAPH'] | |
| if not os.path.exists(self._fg_dir): | |
| - | raise Exception(f'FlameGraph checkout not found in {self._fg_dir}, set env variable FLAMEGRAPH') |
| + | raise EnvError(f'FlameGraph checkout not found in {self._fg_dir}, set env variable FLAMEGRAPH') |
| if sys.platform.startswith('linux'): | |
| self._with_perf = True | |
| elif sys.platform.startswith('darwin'): | |
| self._with_dtrace = True | |
| else: | |
| - | raise Exception(f'flame graphs unsupported on {sys.platform}') |
| + | raise EnvError(f'flame graphs unsupported on {sys.platform}') |
| self._socks_args = socks_args | |
| self._silent = silent | |
| self._run_env = run_env | |
| @@ -919,7 +915,7 @@ class CurlClient: | |
| '--upload-file', '-' | |
| ]) | |
| else: | |
| - | raise Exception('need either file or data to upload') |
| + | raise EnvError('need either file or data to upload') |
| if with_stats: | |
| extra_args.extend([ | |
| '-w', '%{json}\\n' | |
| @@ -995,7 +991,7 @@ class CurlClient: | |
| '--upload-file', '-' | |
| ]) | |
| else: | |
| - | raise Exception('need either file or data to upload') |
| + | raise EnvError('need either file or data to upload') |
| if with_stats: | |
| extra_args.extend([ | |
| '-w', '%{json}\\n' | |
| @@ -1071,7 +1067,7 @@ class CurlClient: | |
| cwd=self._run_dir, shell=False, | |
| input=intext.encode() if intext else None, | |
| timeout=self._timeout, | |
| - | env=self._run_env) |
| + | env=self._run_env, check=False) |
| exitcode = p.returncode | |
| except subprocess.TimeoutExpired: | |
| now = datetime.now() | |
| @@ -1160,7 +1156,7 @@ class CurlClient: | |
| args.extend(options) | |
| if alpn_proto is not None: | |
| if alpn_proto not in self.ALPN_ARG: | |
| - | raise Exception(f'unknown ALPN protocol: "{alpn_proto}"') |
| + | raise EnvError(f'unknown ALPN protocol: "{alpn_proto}"') |
| args.append(self.ALPN_ARG[alpn_proto]) | |
| if u.scheme == 'http': | |
| @@ -1243,36 +1239,30 @@ class CurlClient: | |
| def _perf_collapse(self, perf: PerfProfile, file_err): | |
| if not os.path.exists(perf.file): | |
| - | raise Exception(f'perf output file does not exist: {perf.file}') |
| + | raise EnvError(f'perf output file does not exist: {perf.file}') |
| fg_collapse = os.path.join(self._fg_dir, 'stackcollapse-perf.pl') | |
| if not os.path.exists(fg_collapse): | |
| - | raise Exception(f'FlameGraph script not found: {fg_collapse}') |
| + | raise EnvError(f'FlameGraph script not found: {fg_collapse}') |
| stacks_collapsed = f'{perf.file}.collapsed' | |
| log.info(f'collapsing stacks into {stacks_collapsed}') | |
| with open(stacks_collapsed, 'w') as cout, open(file_err, 'w') as cerr: | |
| - | p = subprocess.run([ |
| + | subprocess.run([ |
| fg_collapse, perf.file | |
| - | ], stdout=cout, stderr=cerr, cwd=self._run_dir, shell=False) |
| - | rc = p.returncode |
| - | if rc != 0: |
| - | raise Exception(f'{fg_collapse} returned error {rc}') |
| + | ], stdout=cout, stderr=cerr, cwd=self._run_dir, shell=False, check=True) |
| return stacks_collapsed | |
| def _dtrace_collapse(self, dtrace: DTraceProfile, file_err): | |
| if not os.path.exists(dtrace.file): | |
| - | raise Exception(f'dtrace output file does not exist: {dtrace.file}') |
| + | raise EnvError(f'dtrace output file does not exist: {dtrace.file}') |
| fg_collapse = os.path.join(self._fg_dir, 'stackcollapse.pl') | |
| if not os.path.exists(fg_collapse): | |
| - | raise Exception(f'FlameGraph script not found: {fg_collapse}') |
| + | raise EnvError(f'FlameGraph script not found: {fg_collapse}') |
| stacks_collapsed = f'{dtrace.file}.collapsed' | |
| log.info(f'collapsing stacks into {stacks_collapsed}') | |
| with open(stacks_collapsed, 'w') as cout, open(file_err, 'a') as cerr: | |
| - | p = subprocess.run([ |
| + | subprocess.run([ |
| fg_collapse, dtrace.file | |
| - | ], stdout=cout, stderr=cerr, cwd=self._run_dir, shell=False) |
| - | rc = p.returncode |
| - | if rc != 0: |
| - | raise Exception(f'{fg_collapse} returned error {rc}') |
| + | ], stdout=cout, stderr=cerr, cwd=self._run_dir, shell=False, check=True) |
| return stacks_collapsed | |
| def _generate_flame(self, curl_args: List[str], | |
| @@ -1281,7 +1271,7 @@ class CurlClient: | |
| fg_gen_flame = os.path.join(self._fg_dir, 'flamegraph.pl') | |
| file_svg = os.path.join(self._run_dir, 'curl.flamegraph.svg') | |
| if not os.path.exists(fg_gen_flame): | |
| - | raise Exception(f'FlameGraph script not found: {fg_gen_flame}') |
| + | raise EnvError(f'FlameGraph script not found: {fg_gen_flame}') |
| log.info('waiting a sec for perf/dtrace to finish flushing') | |
| time.sleep(2) | |
| @@ -1292,7 +1282,7 @@ class CurlClient: | |
| elif dtrace: | |
| stacks_collapsed = self._dtrace_collapse(dtrace, file_err) | |
| else: | |
| - | raise Exception('no stacks measure given') |
| + | raise EnvError('no stacks measure given') |
| log.info(f'generating graph into {file_svg}') | |
| cmdline = ' '.join(curl_args) | |
| @@ -1303,14 +1293,11 @@ class CurlClient: | |
| title = cmdline | |
| subtitle = '' | |
| with open(file_svg, 'w') as cout, open(file_err, 'a') as cerr: | |
| - | p = subprocess.run([ |
| + | subprocess.run([ |
| fg_gen_flame, '--colors', 'green', | |
| '--title', title, '--subtitle', subtitle, | |
| stacks_collapsed | |
| - | ], stdout=cout, stderr=cerr, cwd=self._run_dir, shell=False) |
| - | rc = p.returncode |
| - | if rc != 0: |
| - | raise Exception(f'{fg_gen_flame} returned error {rc}') |
| + | ], stdout=cout, stderr=cerr, cwd=self._run_dir, shell=False, check=True) |
| def mk_altsvc_file(self, name, src_alpn, src_host, src_port, | |
| dest_alpn, dest_host, dest_port): | |
| @@ -43,6 +43,10 @@ from .certs import CertificateSpec, Credentials, TestCA | |
| log = logging.getLogger(__name__) | |
| + | class EnvError(Exception): |
| + | """Exception from the test environment.""" |
| + | |
| + | |
| def init_config_from(conf_path): | |
| if os.path.isfile(conf_path): | |
| config = ConfigParser(interpolation=ExtendedInterpolation()) | |
| @@ -58,7 +62,7 @@ CONFIG_PATH = os.path.join(TOP_PATH, "tests", "http", "config.ini") | |
| if not os.path.exists(CONFIG_PATH): | |
| ALT_CONFIG_PATH = os.path.join(PROJ_PATH, "tests", "http", "config.ini") | |
| if not os.path.exists(ALT_CONFIG_PATH): | |
| - | raise Exception( |
| + | raise EnvError( |
| f"unable to find config.ini in {CONFIG_PATH} nor {ALT_CONFIG_PATH}" | |
| ) | |
| TOP_PATH = PROJ_PATH | |
| @@ -77,11 +81,7 @@ class NghttpxUtil: | |
| if cmd is None: | |
| return None | |
| if cls.VERSION_FULL is None or cmd != cls.CMD: | |
| - | p = subprocess.run(args=[cmd, "--version"], capture_output=True, text=True) |
| - | if p.returncode != 0: |
| - | raise RuntimeError( |
| - | f"{cmd} --version failed with exit code: {p.returncode}" |
| - | ) |
| + | p = subprocess.run(args=[cmd, "--version"], capture_output=True, text=True, check=True) |
| cls.CMD = cmd | |
| for line in p.stdout.splitlines(keepends=False): | |
| if line.startswith("nghttpx "): | |
| @@ -131,9 +131,7 @@ class EnvConfig: | |
| } | |
| self.curl_is_debug = False | |
| self.curl_protos = [] | |
| - | p = subprocess.run(args=[self.curl, "-V"], capture_output=True, text=True) |
| - | if p.returncode != 0: |
| - | raise RuntimeError(f"{self.curl} -V failed with exit code: {p.returncode}") |
| + | p = subprocess.run(args=[self.curl, "-V"], capture_output=True, text=True, check=True) |
| if p.stderr.startswith("WARNING:"): | |
| self.curl_is_debug = True | |
| for line in p.stdout.splitlines(keepends=False): | |
| @@ -162,9 +160,7 @@ class EnvConfig: | |
| prot.lower() for prot in line[11:].split(" ") | |
| } | |
| - | p = subprocess.run(args=[self.curlinfo], capture_output=True, text=True) |
| - | if p.returncode != 0: |
| - | raise RuntimeError(f"{self.curlinfo} failed with exit code: {p.returncode}") |
| + | p = subprocess.run(args=[self.curlinfo], capture_output=True, text=True, check=True) |
| self.curl_is_verbose = 'verbose-strings: ON' in p.stdout | |
| self.curl_can_cert_status = 'cert-status: ON' in p.stdout | |
| self.curl_override_dns = 'override-dns: ON' in p.stdout | |
| @@ -226,7 +222,7 @@ class EnvConfig: | |
| self.openssl = "openssl" | |
| p = subprocess.run( | |
| - | args=[self.openssl, "version"], capture_output=True, text=True |
| + | args=[self.openssl, "version"], capture_output=True, text=True, check=False |
| ) | |
| if p.returncode != 0: | |
| # no openssl in path | |
| @@ -256,7 +252,7 @@ class EnvConfig: | |
| if self.h2o is not None: | |
| try: | |
| p = subprocess.run( | |
| - | args=[self.h2o, "--version"], capture_output=True, text=True |
| + | args=[self.h2o, "--version"], capture_output=True, text=True, check=False |
| ) | |
| if p.returncode != 0: | |
| # not a working h2o | |
| @@ -274,7 +270,7 @@ class EnvConfig: | |
| if self.caddy is not None: | |
| p = subprocess.run( | |
| - | args=[self.caddy, "version"], capture_output=True, text=True |
| + | args=[self.caddy, "version"], capture_output=True, text=True, check=False |
| ) | |
| if p.returncode != 0: | |
| # not a working caddy | |
| @@ -294,7 +290,7 @@ class EnvConfig: | |
| if self.vsftpd is not None: | |
| with tempfile.TemporaryFile("w+") as tmp: | |
| p = subprocess.run( | |
| - | args=[self.vsftpd, "-v"], capture_output=True, text=True, stdin=tmp |
| + | args=[self.vsftpd, "-v"], capture_output=True, text=True, stdin=tmp, check=False |
| ) | |
| if p.returncode != 0: | |
| # not a working vsftpd | |
| @@ -315,14 +311,14 @@ class EnvConfig: | |
| # vsftp does not use stdout or stderr for printing its version... -.- | |
| self._vsftpd_version = "unknown" | |
| else: | |
| - | raise Exception(f"Unable to determine VsFTPD version from: {p.stderr}") |
| + | raise EnvError(f"Unable to determine VsFTPD version from: {p.stderr}") |
| self.danted = self.config["danted"]["danted"] | |
| if self.danted == "": | |
| self.danted = None | |
| self._danted_version = None | |
| if self.danted is not None: | |
| - | p = subprocess.run(args=[self.danted, "-v"], capture_output=True, text=True) |
| + | p = subprocess.run(args=[self.danted, "-v"], capture_output=True, text=True, check=False) |
| assert p.returncode == 0 | |
| if p.returncode != 0: | |
| # not a working vsftpd | |
| @@ -334,14 +330,14 @@ class EnvConfig: | |
| self._danted_version = m.group(1) | |
| else: | |
| self.danted = None | |
| - | raise Exception(f"Unable to determine danted version from: {p.stderr}") |
| + | raise EnvError(f"Unable to determine danted version from: {p.stderr}") |
| self.sshd = self.config["sshd"]["sshd"] | |
| if self.sshd == "": | |
| self.sshd = None | |
| self._sshd_version = None | |
| if self.sshd is not None: | |
| - | p = subprocess.run(args=[self.sshd, "-V"], capture_output=True, text=True) |
| + | p = subprocess.run(args=[self.sshd, "-V"], capture_output=True, text=True, check=False) |
| assert p.returncode == 0 | |
| if p.returncode != 0: | |
| self.sshd = None | |
| @@ -352,7 +348,7 @@ class EnvConfig: | |
| self._sshd_version = m.group(1) | |
| else: | |
| self.sshd = None | |
| - | raise Exception( |
| + | raise EnvError( |
| f"Unable to determine sshd version from: {p.stderr}" | |
| ) | |
| @@ -373,6 +369,7 @@ class EnvConfig: | |
| args=[self.apxs, "-q", "HTTPD_VERSION"], | |
| capture_output=True, | |
| text=True, | |
| + | check=False, |
| ) | |
| if p.returncode != 0: | |
| log.error(f"{self.apxs} failed to query HTTPD_VERSION: {p}") | |
| @@ -37,7 +37,7 @@ from json import JSONEncoder | |
| from typing import Dict, List, Optional, Union | |
| from .curl import CurlClient, ExecResult | |
| - | from .env import Env |
| + | from .env import Env, EnvError |
| from .ports import alloc_ports_and_do | |
| log = logging.getLogger(__name__) | |
| @@ -95,14 +95,12 @@ class Httpd: | |
| self._loaded_domain1_cred_name = None | |
| assert env.apxs | |
| p = subprocess.run(args=[env.apxs, '-q', 'libexecdir'], | |
| - | capture_output=True, text=True) |
| - | if p.returncode != 0: |
| - | raise Exception(f'{env.apxs} failed to query libexecdir: {p}') |
| + | capture_output=True, text=True, check=True) |
| self._mods_dir = p.stdout.strip() | |
| if self._mods_dir is None: | |
| - | raise Exception('apache modules directory cannot be found') |
| + | raise EnvError('apache modules directory cannot be found') |
| if not os.path.exists(self._mods_dir): | |
| - | raise Exception(f'apache modules directory does not exist: {self._mods_dir}') |
| + | raise EnvError(f'apache modules directory does not exist: {self._mods_dir}') |
| self._maybe_running = False | |
| self.ports = {} | |
| self._rmf(self._error_log) | |
| @@ -144,7 +142,7 @@ class Httpd: | |
| p = subprocess.run(args, stderr=subprocess.PIPE, stdout=subprocess.PIPE, | |
| cwd=self.env.gen_dir, | |
| input=intext.encode() if intext else None, | |
| - | env=env) |
| + | env=env, check=True) |
| start = datetime.now() | |
| return ExecResult(args=args, exit_code=p.returncode, | |
| stdout=p.stdout.decode().splitlines(), | |
| @@ -587,9 +585,9 @@ class Httpd: | |
| shutil.copy(in_source, out_source) | |
| p = subprocess.run([ | |
| self.env.apxs, '-c', out_source | |
| - | ], capture_output=True, cwd=out_dir) |
| + | ], capture_output=True, cwd=out_dir, check=False) |
| rv = p.returncode | |
| if rv != 0: | |
| log.error(f"compiling mod_curltest failed: {p.stderr}") | |
| - | raise Exception(f"compiling mod_curltest failed: {p.stderr}") |
| + | raise EnvError(f"compiling mod_curltest failed: {p.stderr}") |
| Httpd.MOD_CURLTEST = os.path.join(out_dir, '.libs/mod_curltest.so') | |
| @@ -39,13 +39,10 @@ def alloc_port_set(port_specs: Dict[str, int]) -> Dict[str, int]: | |
| socks = [] | |
| ports = {} | |
| for name, ptype in port_specs.items(): | |
| - | try: |
| - | s = socket.socket(type=ptype) |
| - | s.bind(('127.0.0.1', 0)) |
| - | ports[name] = s.getsockname()[1] |
| - | socks.append(s) |
| - | except Exception as e: |
| - | raise e |
| + | s = socket.socket(type=ptype) |
| + | s.bind(('127.0.0.1', 0)) |
| + | ports[name] = s.getsockname()[1] |
| + | socks.append(s) |
| for s in socks: | |
| s.close() | |
| return ports | |
| @@ -125,11 +125,9 @@ class Sshd: | |
| for alg in self._key_algs: | |
| key_file = os.path.join(self._sshd_dir, f'ssh_host_{alg}_key') | |
| if not os.path.exists(key_file): | |
| - | p = subprocess.run(args=[ |
| + | subprocess.run(args=[ |
| self._keygen, '-q', '-N', '', '-t', alg, '-f', key_file | |
| - | ], capture_output=True, text=True) |
| - | if p.returncode != 0: |
| - | raise RuntimeError(f'error generating host key {key_file}: {p.returncode}') |
| + | ], capture_output=True, text=True, check=True) |
| self._host_key_files.append(key_file) | |
| pub_file = f'{key_file}.pub' | |
| self._host_pub_files.append(pub_file) | |
| @@ -139,11 +137,9 @@ class Sshd: | |
| fd_known.write(f'[{self.env.domain1.lower()}]:{self.port} {pubkey}') | |
| fd_unknown.write(f'dummy.invalid {pubkey}') | |
| # hash the known_hosts file, libssh requires it | |
| - | p = subprocess.run(args=[ |
| + | subprocess.run(args=[ |
| self._keygen, '-H', '-f', self._known_hosts | |
| - | ], capture_output=True, text=True) |
| - | if p.returncode != 0: |
| - | raise RuntimeError(f'error hashing {self._known_hosts}: {p.returncode}') |
| + | ], capture_output=True, text=True, check=True) |
| def mk_user_keys(self): | |
| self._user_key_files = [] | |
| @@ -152,11 +148,9 @@ class Sshd: | |
| for user in self._users: | |
| key_file = os.path.join(self._sshd_dir, f'id_{user}_user_{alg}_key') | |
| if not os.path.exists(key_file): | |
| - | p = subprocess.run(args=[ |
| + | subprocess.run(args=[ |
| self._keygen, '-q', '-N', '', '-t', alg, '-f', key_file | |
| - | ], capture_output=True, text=True) |
| - | if p.returncode != 0: |
| - | raise RuntimeError(f'error generating user key {key_file}: {p.returncode}') |
| + | ], capture_output=True, text=True, check=True) |
| self._user_key_files.append(key_file) | |
| self._user_pub_files.append(f'{key_file}.pub') | |
| with open(self._auth_keys, 'w') as fd: | |
| @@ -26,6 +26,7 @@ | |
| # | |
| import argparse | |
| import asyncio | |
| + | import contextlib |
| import logging | |
| from websockets import server | |
| @@ -33,12 +34,10 @@ from websockets.exceptions import ConnectionClosedError | |
| async def echo(websocket): | |
| - | try: |
| + | # exception when websocket connection closed by client |
| + | with contextlib.suppress(ConnectionClosedError): |
| async for message in websocket: | |
| await websocket.send(message) | |
| - | except ConnectionClosedError: |
| - | # websocket connection closed by client |
| - | pass |
| async def run_server(port): | |
| @@ -109,8 +109,8 @@ class NegotiatingTelnetHandler(socketserver.BaseRequestHandler): | |
| self.request.recv(4 * 1024) | |
| self.request.shutdown(socket.SHUT_RDWR) | |
| - | except IOError: |
| - | log.exception("IOError hit during request") |
| + | except OSError: |
| + | log.exception("OSError hit during request") |
| class Negotiator: | |
| @@ -77,7 +77,7 @@ class TestData: | |
| m = REPLY_DATA.search(contents) | |
| if not m: | |
| - | raise Exception("Could not find a <reply><data> section") |
| + | raise RuntimeError("Could not find a <reply><data> section") |
| # Left-strip the data so we do not get a newline before our data. | |
| return m.group(1).lstrip() | |