diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index 9a6382c..aed4f70 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -13,6 +13,5 @@ jobs: mypy: true rst: true black: true - pydocstyle: true - pycodestyle: true + ruff: true diff --git a/Pipfile b/Pipfile index 8b88c46..a27c480 100644 --- a/Pipfile +++ b/Pipfile @@ -12,10 +12,9 @@ pytest = "==7.4.2" pytest-cov = "==4.1.0" coverage = "==7.3.2" python-daemon = "==3.0.1" -pycodestyle = "==2.11.1" -pydocstyle = {version = "==6.3.0", extras = ["toml"]} restructuredtext-lint = "==1.4.0" mypy = "==1.6.0" black = {version = "==23.9.1", markers="python_version >= '3.8'"} pygments = "==2.16.1" tbump = "==6.11.0" +ruff = "==0.1.0" diff --git a/mirakuru/__init__.py b/mirakuru/__init__.py index b47690a..ff8e80a 100644 --- a/mirakuru/__init__.py +++ b/mirakuru/__init__.py @@ -21,17 +21,16 @@ import logging from mirakuru.base import Executor, SimpleExecutor -from mirakuru.output import OutputExecutor -from mirakuru.tcp import TCPExecutor -from mirakuru.http import HTTPExecutor -from mirakuru.pid import PidExecutor - from mirakuru.exceptions import ( - ExecutorError, - TimeoutExpired, AlreadyRunning, + ExecutorError, ProcessExitedWithError, + TimeoutExpired, ) +from mirakuru.http import HTTPExecutor +from mirakuru.output import OutputExecutor +from mirakuru.pid import PidExecutor +from mirakuru.tcp import TCPExecutor __version__ = "2.5.1" diff --git a/mirakuru/base.py b/mirakuru/base.py index 8147ac9..ab0b535 100644 --- a/mirakuru/base.py +++ b/mirakuru/base.py @@ -18,40 +18,40 @@ """Executor with the core functionality.""" import atexit -from contextlib import contextmanager +import errno import logging import os +import platform import shlex import signal import subprocess import time import uuid -import errno -import platform +from contextlib import contextmanager from types import TracebackType from typing import ( - Union, IO, Any, + Callable, + Dict, + Iterator, List, - Tuple, Optional, - Dict, - TypeVar, - Type, Set, - Iterator, - Callable, + Tuple, + Type, + TypeVar, + Union, ) from mirakuru.base_env import processes_with_env +from mirakuru.compat import SIGKILL from mirakuru.exceptions import ( AlreadyRunning, ProcessExitedWithError, ProcessFinishedWithError, TimeoutExpired, ) -from mirakuru.compat import SIGKILL LOG = logging.getLogger(__name__) @@ -75,8 +75,9 @@ def cleanup_subprocesses() -> None: """On python exit: find possibly running subprocesses and kill them.""" # atexit functions tends to loose global imports sometimes so reimport # everything what is needed again here: - import os import errno + import os + from mirakuru.base_env import processes_with_env from mirakuru.compat import SIGKILL @@ -107,8 +108,7 @@ def __init__( # pylint:disable=too-many-arguments stdout: Union[None, int, IO[Any]] = subprocess.PIPE, stderr: Union[None, int, IO[Any]] = None, ) -> None: - """ - Initialize executor. + """Initialize executor. :param (str, list) command: command to be run by the subprocess :param str cwd: current working directory to be set for executor @@ -172,8 +172,7 @@ def __init__( # pylint:disable=too-many-arguments self._uuid = f"{os.getpid()}:{uuid.uuid4()}" def __enter__(self: SimpleExecutorType) -> SimpleExecutorType: - """ - Enter context manager starting the subprocess. + """Enter context manager starting the subprocess. :returns: itself :rtype: SimpleExecutor @@ -190,8 +189,7 @@ def __exit__( self.stop() def running(self) -> bool: - """ - Check if executor is running. + """Check if executor is running. :returns: True if process is running, False otherwise :rtype: bool @@ -203,8 +201,7 @@ def running(self) -> bool: @property def _popen_kwargs(self) -> Dict[str, Any]: - """ - Get kwargs for the process instance. + """Get kwargs for the process instance. .. note:: We want to open ``stdin``, ``stdout`` and ``stderr`` as text @@ -247,8 +244,7 @@ def _popen_kwargs(self) -> Dict[str, Any]: return kwargs def start(self: SimpleExecutorType) -> SimpleExecutorType: - """ - Start defined process. + """Start defined process. After process gets started, timeout countdown begins as well. @@ -270,8 +266,7 @@ def _set_timeout(self) -> None: self._endtime = time.time() + self._timeout def _clear_process(self) -> None: - """ - Close stdin/stdout of subprocess. + """Close stdin/stdout of subprocess. It is required because of ResourceWarning in Python 3. """ @@ -282,8 +277,7 @@ def _clear_process(self) -> None: self._endtime = None def _kill_all_kids(self, sig: int) -> Set[int]: - """ - Kill all subprocesses (and its subprocesses) that executor started. + """Kill all subprocesses (and its subprocesses) that executor started. This function tries to kill all leftovers in process tree that current executor may have left. It uses environment variable to recognise if @@ -313,8 +307,7 @@ def stop( stop_signal: Optional[int] = None, expected_returncode: Optional[int] = None, ) -> SimpleExecutorType: - """ - Stop process running. + """Stop process running. Wait 10 seconds for the process to end, then just kill it. @@ -378,8 +371,7 @@ def process_stopped() -> bool: @contextmanager def stopped(self: SimpleExecutorType) -> Iterator[SimpleExecutorType]: - """ - Stop process for given context and starts it afterwards. + """Stop process for given context and starts it afterwards. Allows for easier writing resistance integration tests whenever one of the service fails. @@ -394,8 +386,7 @@ def stopped(self: SimpleExecutorType) -> Iterator[SimpleExecutorType]: def kill( self: SimpleExecutorType, wait: bool = True, sig: Optional[int] = None ) -> SimpleExecutorType: - """ - Kill the process if running. + """Kill the process if running. :param bool wait: set to `True` to wait for the process to end, or False, to simply proceed after sending signal. @@ -430,8 +421,7 @@ def err_output(self) -> Optional[IO[Any]]: def wait_for( self: SimpleExecutorType, wait_for: Callable[[], bool] ) -> SimpleExecutorType: - """ - Wait for callback to return True. + """Wait for callback to return True. Simply returns if wait_for condition has been met, raises TimeoutExpired otherwise and kills the process. @@ -450,8 +440,7 @@ def wait_for( raise TimeoutExpired(self, timeout=self._timeout) def check_timeout(self) -> bool: - """ - Check if timeout has expired. + """Check if timeout has expired. Returns True if there is no timeout set or the timeout has not expired. Kills the process and raises TimeoutExpired exception otherwise. @@ -498,8 +487,7 @@ class Executor(SimpleExecutor): """Base class for executors with a pre- and after-start checks.""" def pre_start_check(self) -> bool: - """ - Check process before the start of executor. + """Check process before the start of executor. Should be overridden in order to return True when some other executor (or process) has already started with the same configuration. @@ -508,8 +496,7 @@ def pre_start_check(self) -> bool: raise NotImplementedError def start(self: ExecutorType) -> ExecutorType: - """ - Start executor with additional checks. + """Start executor with additional checks. Checks if previous executor isn't running then start process (executor) and wait until it's started. @@ -526,8 +513,7 @@ def start(self: ExecutorType) -> ExecutorType: return self def check_subprocess(self) -> bool: - """ - Make sure the process didn't exit with an error and run the checks. + """Make sure the process didn't exit with an error and run the checks. :rtype: bool :return: the actual check status or False before starting the process @@ -548,8 +534,7 @@ def check_subprocess(self) -> bool: return self.after_start_check() def after_start_check(self) -> bool: - """ - Check process after the start of executor. + """Check process after the start of executor. Should be overridden in order to return boolean value if executor can be treated as started. diff --git a/mirakuru/base_env.py b/mirakuru/base_env.py index adb32c5..20ed96b 100644 --- a/mirakuru/base_env.py +++ b/mirakuru/base_env.py @@ -21,7 +21,7 @@ import logging import re import subprocess -from typing import Set, List +from typing import List, Set try: import psutil @@ -37,8 +37,7 @@ def processes_with_env_psutil(env_name: str, env_value: str) -> Set[int]: - """ - Find PIDs of processes having environment variable matching given one. + """Find PIDs of processes having environment variable matching given one. Internally it uses `psutil` library. @@ -65,8 +64,7 @@ def processes_with_env_psutil(env_name: str, env_value: str) -> Set[int]: def processes_with_env_ps(env_name: str, env_value: str) -> Set[int]: - """ - Find PIDs of processes having environment variable matching given one. + """Find PIDs of processes having environment variable matching given one. It uses `$ ps xe -o pid,cmd` command so it works only on systems having such command available (Linux, MacOS). If not available function diff --git a/mirakuru/exceptions.py b/mirakuru/exceptions.py index c5e870c..4d97049 100644 --- a/mirakuru/exceptions.py +++ b/mirakuru/exceptions.py @@ -1,6 +1,6 @@ """Mirakuru exceptions.""" -from typing import Union, TYPE_CHECKING +from typing import TYPE_CHECKING, Union if TYPE_CHECKING: # pragma: no cover from mirakuru.base import SimpleExecutor # pylint:disable=cyclic-import @@ -10,8 +10,7 @@ class ExecutorError(Exception): """Base exception for executor failures.""" def __init__(self, executor: "SimpleExecutor") -> None: - """ - Exception initialization. + """Exception initialization. :param mirakuru.base.SimpleExecutor executor: for which exception occurred @@ -26,8 +25,7 @@ class TimeoutExpired(ExecutorError): def __init__( self, executor: "SimpleExecutor", timeout: Union[int, float] ) -> None: - """ - Exception initialization with an extra ``timeout`` argument. + """Exception initialization with an extra ``timeout`` argument. :param mirakuru.base.SimpleExecutor executor: for which exception occurred @@ -37,8 +35,7 @@ def __init__( self.timeout = timeout def __str__(self) -> str: - """ - Return Exception's string representation. + """Return Exception's string representation. :returns: string representation :rtype: str @@ -49,16 +46,14 @@ def __str__(self) -> str: class AlreadyRunning(ExecutorError): - """ - Is raised when the executor seems to be already running. + """Is raised when the executor seems to be already running. When some other process (not necessary executor) seems to be started with same configuration we can't bind to same port. """ def __str__(self) -> str: - """ - Return Exception's string representation. + """Return Exception's string representation. :returns: string representation :rtype: str @@ -78,8 +73,7 @@ def __str__(self) -> str: class ProcessExitedWithError(ExecutorError): - """ - Raised when the process invoked by the executor returns a non-zero code. + """Raised when the process invoked by the executor returns a non-zero code. We allow the process to exit with zero because we support daemonizing subprocesses. We assume that when double-forking, the parent process will @@ -87,8 +81,7 @@ class ProcessExitedWithError(ExecutorError): """ def __init__(self, executor: "SimpleExecutor", exit_code: int) -> None: - """ - Exception initialization with an extra ``exit_code`` argument. + """Exception initialization with an extra ``exit_code`` argument. :param mirakuru.base.SimpleExecutor executor: for which exception occurred @@ -98,8 +91,7 @@ def __init__(self, executor: "SimpleExecutor", exit_code: int) -> None: self.exit_code = exit_code def __str__(self) -> str: - """ - Return Exception's string representation. + """Return Exception's string representation. :returns: string representation :rtype: str @@ -111,8 +103,7 @@ def __str__(self) -> str: class ProcessFinishedWithError(ProcessExitedWithError): - """ - Raised when the process invoked by the executor fails when stopping. + """Raised when the process invoked by the executor fails when stopping. When a process is stopped, it should shut down cleanly and return zero as exit code. When is returns a non-zero exit code, this exception is raised. diff --git a/mirakuru/http.py b/mirakuru/http.py index bf44a84..4a6fdc2 100644 --- a/mirakuru/http.py +++ b/mirakuru/http.py @@ -19,10 +19,10 @@ import re import socket -from logging import getLogger -from urllib.parse import urlparse, urlencode from http.client import HTTPConnection, HTTPException -from typing import Union, List, Tuple, Optional, Dict, Any +from logging import getLogger +from typing import Any, Dict, List, Optional, Tuple, Union +from urllib.parse import urlencode, urlparse from mirakuru.tcp import TCPExecutor @@ -45,8 +45,7 @@ def __init__( headers: Optional[Dict[str, str]] = None, **kwargs: Any, ) -> None: - """ - Initialize HTTPExecutor executor. + """Initialize HTTPExecutor executor. :param (str, list) command: command to be run by the subprocess :param str url: URL that executor checks to verify diff --git a/mirakuru/output.py b/mirakuru/output.py index 89db070..68c6c23 100644 --- a/mirakuru/output.py +++ b/mirakuru/output.py @@ -19,11 +19,10 @@ import platform import re import select -from typing import Union, List, Any, TypeVar, Tuple, IO, Optional +from typing import IO, Any, List, Optional, Tuple, TypeVar, Union from mirakuru.base import SimpleExecutor - IS_DARWIN = platform.system() == "Darwin" @@ -39,8 +38,7 @@ def __init__( banner: str, **kwargs: Any, ) -> None: - """ - Initialize OutputExecutor executor. + """Initialize OutputExecutor executor. :param (str, list) command: command to be run by the subprocess :param str banner: string that has to appear in process output - @@ -63,8 +61,7 @@ def __init__( ) def start(self: OutputExecutorType) -> OutputExecutorType: - """ - Start process. + """Start process. :returns: itself :rtype: OutputExecutor @@ -137,8 +134,7 @@ def _wait_for_darwin_output(self, *fds: Optional[IO[Any]]) -> bool: return False def _wait_for_output(self, *polls: Tuple["select.poll", IO[Any]]) -> bool: - """ - Check if output matches banner. + """Check if output matches banner. .. warning:: Waiting for I/O completion. It does not work on Windows. Sorry. diff --git a/mirakuru/pid.py b/mirakuru/pid.py index e2b32ab..96ad5c1 100644 --- a/mirakuru/pid.py +++ b/mirakuru/pid.py @@ -18,14 +18,13 @@ """Pid executor definition.""" import os.path -from typing import Union, List, Tuple, Any +from typing import Any, List, Tuple, Union from mirakuru.base import Executor class PidExecutor(Executor): - """ - File existence checking process executor. + """File existence checking process executor. Used to start processes that create pid files (or any other for that matter). Starts the given process and waits for the given file to be @@ -38,8 +37,7 @@ def __init__( filename: str, **kwargs: Any, ) -> None: - """ - Initialize the PidExecutor executor. + """Initialize the PidExecutor executor. If the filename is empty, a ValueError is thrown. @@ -64,8 +62,7 @@ def __init__( """the name of the file which the process is to create.""" def pre_start_check(self) -> bool: - """ - Check if the specified file has been created. + """Check if the specified file has been created. .. note:: @@ -75,8 +72,7 @@ def pre_start_check(self) -> bool: return os.path.isfile(self.filename) def after_start_check(self) -> bool: - """ - Check if the process has created the specified file. + """Check if the process has created the specified file. .. note:: diff --git a/mirakuru/tcp.py b/mirakuru/tcp.py index a126582..7972f15 100644 --- a/mirakuru/tcp.py +++ b/mirakuru/tcp.py @@ -18,14 +18,13 @@ """TCP executor definition.""" import socket -from typing import Union, List, Tuple, Any +from typing import Any, List, Tuple, Union from mirakuru.base import Executor class TCPExecutor(Executor): - """ - TCP-listening process executor. + """TCP-listening process executor. Used to start (and wait to actually be running) processes that can accept TCP connections. @@ -38,8 +37,7 @@ def __init__( port: int, **kwargs: Any, ) -> None: - """ - Initialize TCPExecutor executor. + """Initialize TCPExecutor executor. :param (str, list) command: command to be run by the subprocess :param str host: host under which process is accessible @@ -61,8 +59,7 @@ def __init__( """Port number, process is listening on.""" def pre_start_check(self) -> bool: - """ - Check if process accepts connections. + """Check if process accepts connections. .. note:: @@ -80,8 +77,7 @@ def pre_start_check(self) -> bool: sock.close() def after_start_check(self) -> bool: - """ - Check if process accepts connections. + """Check if process accepts connections. .. note:: diff --git a/mirakuru/unixsocket.py b/mirakuru/unixsocket.py index 3dd1f9f..a3249c6 100644 --- a/mirakuru/unixsocket.py +++ b/mirakuru/unixsocket.py @@ -18,7 +18,7 @@ """TCP Socket executor definition.""" import logging import socket -from typing import Union, List, Tuple, Any +from typing import Any, List, Tuple, Union from mirakuru import Executor @@ -26,8 +26,7 @@ class UnixSocketExecutor(Executor): - """ - Unixsocket listening process executor. + """Unixsocket listening process executor. Used to start (and wait to actually be running) processes that can accept stream Unix socket connections. @@ -39,8 +38,7 @@ def __init__( socket_name: str, **kwargs: Any, ) -> None: - """ - Initialize UnixSocketExecutor executor. + """Initialize UnixSocketExecutor executor. :param (str, list) command: command to be run by the subprocess :param str socket_name: unix socket path @@ -57,8 +55,7 @@ def __init__( self.socket = socket_name def pre_start_check(self) -> bool: - """ - Check if process accepts connections. + """Check if process accepts connections. .. note:: @@ -77,8 +74,7 @@ def pre_start_check(self) -> bool: exec_sock.close() def after_start_check(self) -> bool: - """ - Check if process accepts connections. + """Check if process accepts connections. .. note:: diff --git a/newsfragments/655.misc.rst b/newsfragments/655.misc.rst new file mode 100644 index 0000000..2565766 --- /dev/null +++ b/newsfragments/655.misc.rst @@ -0,0 +1 @@ +Replace pydocstyle, pycodestyle with ruff \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 03b9476..91a757e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -84,14 +84,19 @@ showcontent = false filterwarnings = "error" xfail_strict = "True" -[tool.pydocstyle] -ignore = "D203,D212" - [tool.black] line-length = 80 target-version = ['py38'] include = '.*\.pyi?$' +[tool.ruff] +line-length = 80 +select = [ + "E", # pycodestyle + "F", # pyflakes + "I", # isort + "D", # pydocstyle +] [tool.tbump] # Uncomment this if your project is hosted on GitHub: diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index ddbd715..0000000 --- a/setup.cfg +++ /dev/null @@ -1,3 +0,0 @@ -[pycodestyle] -max-line-length = 80 -exclude = docs/*,build/*,venv/* \ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py index 6105b41..ccec28d 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,5 +1,4 @@ -""" -Package of tests for mirakuru. +"""Package of tests for mirakuru. Tests are written using py.test framework which dictates patterns that should be followed in test cases. @@ -8,7 +7,6 @@ from os import path from subprocess import check_output - TEST_PATH = path.abspath(path.dirname(__file__)) TEST_SERVER_PATH = path.join(TEST_PATH, "server_for_tests.py") @@ -19,8 +17,7 @@ def ps_aux() -> str: - """ - Return output of systems `ps aux -w` call. + """Return output of systems `ps aux -w` call. :rtype str """ diff --git a/tests/executors/test_executor.py b/tests/executors/test_executor.py index c049124..d5bcd61 100644 --- a/tests/executors/test_executor.py +++ b/tests/executors/test_executor.py @@ -3,17 +3,16 @@ import gc import shlex import signal -from subprocess import check_output import uuid +from subprocess import check_output +from typing import List, Union from unittest import mock -from typing import Union, List import pytest from mirakuru import Executor from mirakuru.base import SimpleExecutor from mirakuru.exceptions import ProcessExitedWithError, TimeoutExpired - from tests import SAMPLE_DAEMON_PATH, ps_aux from tests.retry import retry @@ -37,7 +36,6 @@ def test_running_process(command: Union[str, List[str]]) -> None: @pytest.mark.parametrize("command", (SLEEP_300, SLEEP_300.split())) def test_command(command: Union[str, List[str]]) -> None: """Check that the command and command parts are equivalent.""" - executor = SimpleExecutor(command) assert executor.command == SLEEP_300 assert executor.command_parts == SLEEP_300.split() @@ -143,8 +141,7 @@ def test_start_check_executor() -> None: def test_stopping_not_yet_running_executor() -> None: - """ - Test if SimpleExecutor can be stopped even it was never running. + """Test if SimpleExecutor can be stopped even it was never running. We must make sure that it's possible to call .stop() and SimpleExecutor will not raise any exception and .start() can be called afterwards. @@ -157,8 +154,7 @@ def test_stopping_not_yet_running_executor() -> None: def test_forgotten_stop() -> None: - """ - Test if SimpleExecutor subprocess is killed after an instance is deleted. + """Test if SimpleExecutor subprocess is killed after an instance is deleted. Existence can end because of context scope end or by calling 'del'. If someone forgot to stop() or kill() subprocess it should be killed @@ -185,8 +181,7 @@ def test_forgotten_stop() -> None: def test_executor_raises_if_process_exits_with_error() -> None: - """ - Test process exit detection. + """Test process exit detection. If the process exits with an error while checks are being polled, executor should raise an exception. @@ -216,8 +211,7 @@ def test_executor_raises_if_process_exits_with_error() -> None: def test_executor_ignores_processes_exiting_with_0() -> None: - """ - Test process exit detection. + """Test process exit detection. Subprocess exiting with zero should be tolerated in order to support double-forking applications. diff --git a/tests/executors/test_executor_kill.py b/tests/executors/test_executor_kill.py index ae0f8b7..2e05e8e 100644 --- a/tests/executors/test_executor_kill.py +++ b/tests/executors/test_executor_kill.py @@ -1,22 +1,19 @@ # mypy: no-strict-optional """Tests that check various kill behaviours.""" +import errno +import os import signal -import time import sys +import time from typing import NoReturn, Set - -import errno - -import os from unittest.mock import patch import pytest -from mirakuru import SimpleExecutor, HTTPExecutor +from mirakuru import HTTPExecutor, SimpleExecutor from mirakuru.compat import SIGKILL from mirakuru.exceptions import ProcessFinishedWithError - -from tests import SAMPLE_DAEMON_PATH, ps_aux, TEST_SERVER_PATH +from tests import SAMPLE_DAEMON_PATH, TEST_SERVER_PATH, ps_aux SLEEP_300 = "sleep 300" @@ -57,8 +54,7 @@ def process_stopped() -> bool: def test_daemons_killing() -> None: - """ - Test if all subprocesses of SimpleExecutor can be killed. + """Test if all subprocesses of SimpleExecutor can be killed. The most problematic subprocesses are daemons or other services that change the process group ID. This test verifies that daemon process @@ -77,8 +73,7 @@ def test_daemons_killing() -> None: def test_stopping_brutally() -> None: - """ - Test if SimpleExecutor is stopping insubordinate process. + """Test if SimpleExecutor is stopping insubordinate process. Check if the process that doesn't react to SIGTERM signal will be killed by executor with SIGKILL automatically. @@ -96,8 +91,7 @@ def test_stopping_brutally() -> None: def test_stopping_children_of_stopped_process() -> None: - """ - Check that children exiting between listing and killing are ignored. + """Check that children exiting between listing and killing are ignored. Given: Executor is running and it's process spawn children, diff --git a/tests/executors/test_http_executor.py b/tests/executors/test_http_executor.py index 8bd623f..5aefc2a 100644 --- a/tests/executors/test_http_executor.py +++ b/tests/executors/test_http_executor.py @@ -1,16 +1,15 @@ """HTTP Executor tests.""" -import sys import socket +import sys from functools import partial -from http.client import HTTPConnection, OK -from typing import Dict, Any, Union +from http.client import OK, HTTPConnection +from typing import Any, Dict, Union from unittest.mock import patch import pytest -from mirakuru import HTTPExecutor, TCPExecutor -from mirakuru import TimeoutExpired, AlreadyRunning -from tests import TEST_SERVER_PATH, HTTP_SERVER_CMD +from mirakuru import AlreadyRunning, HTTPExecutor, TCPExecutor, TimeoutExpired +from tests import HTTP_SERVER_CMD, TEST_SERVER_PATH HOST = "127.0.0.1" PORT = 7987 @@ -72,13 +71,11 @@ def test_shell_started_server_stops() -> None: @pytest.mark.parametrize("method", ("HEAD", "GET", "POST")) def test_slow_method_server_starting(method: str) -> None: - """ - Test whether or not executor awaits for slow starting servers. + """Test whether or not executor awaits for slow starting servers. Simple example. You run Gunicorn and it is working but you have to wait for worker processes. """ - http_method_slow_cmd = ( f"{sys.executable} {TEST_SERVER_PATH} {HOST}:{PORT} False {method}" ) @@ -93,13 +90,11 @@ def test_slow_method_server_starting(method: str) -> None: def test_slow_post_payload_server_starting() -> None: - """ - Test whether or not executor awaits for slow starting servers. + """Test whether or not executor awaits for slow starting servers. Simple example. You run Gunicorn and it is working but you have to wait for worker processes. """ - http_method_slow_cmd = ( f"{sys.executable} {TEST_SERVER_PATH} {HOST}:{PORT} False Key" ) @@ -117,7 +112,6 @@ def test_slow_post_payload_server_starting() -> None: @pytest.mark.parametrize("method", ("HEAD", "GET", "POST")) def test_slow_method_server_timed_out(method: str) -> None: """Check if timeout properly expires.""" - http_method_slow_cmd = ( f"{sys.executable} {TEST_SERVER_PATH} {HOST}:{PORT} False {method}" ) @@ -157,8 +151,7 @@ def test_fail_if_other_running() -> None: @patch.object(HTTPExecutor, "DEFAULT_PORT", PORT) def test_default_port() -> None: - """ - Test default port for the base TCP check. + """Test default port for the base TCP check. Check if HTTP executor fills in the default port for the TCP check from the base class if no port is provided in the URL. @@ -192,8 +185,7 @@ def test_default_port() -> None: def test_http_status_codes( accepted_status: Union[None, int, str], expected_timeout: bool ) -> None: - """ - Test how 'status' argument influences executor start. + """Test how 'status' argument influences executor start. :param int|str accepted_status: Executor 'status' value :param bool expected_timeout: if Executor raises TimeoutExpired or not diff --git a/tests/executors/test_pid_executor.py b/tests/executors/test_pid_executor.py index caf658e..9d392d9 100644 --- a/tests/executors/test_pid_executor.py +++ b/tests/executors/test_pid_executor.py @@ -4,9 +4,7 @@ import pytest -from mirakuru import PidExecutor -from mirakuru import TimeoutExpired, AlreadyRunning - +from mirakuru import AlreadyRunning, PidExecutor, TimeoutExpired FILENAME = f"pid-test-tmp{os.getpid()}" SLEEP = f'bash -c "sleep 1 && touch {FILENAME} && sleep 1"' @@ -14,8 +12,7 @@ @pytest.fixture(autouse=True) def run_around_tests() -> Iterator[None]: - """ - Make sure the **FILENAME** file is not present. + """Make sure the **FILENAME** file is not present. This executor actually removes FILENAME as process used to test PidExecutor only creates it. diff --git a/tests/executors/test_tcp_executor.py b/tests/executors/test_tcp_executor.py index 83ee5fd..075e1bd 100644 --- a/tests/executors/test_tcp_executor.py +++ b/tests/executors/test_tcp_executor.py @@ -1,5 +1,4 @@ -""" -TCPExecutor tests. +"""TCPExecutor tests. Some of these tests run ``nc``: when running Debian, make sure the ``netcat-openbsd`` package is used, not ``netcat-traditional``. @@ -9,12 +8,9 @@ import pytest from _pytest.logging import LogCaptureFixture -from mirakuru import TCPExecutor -from mirakuru import TimeoutExpired, AlreadyRunning - +from mirakuru import AlreadyRunning, TCPExecutor, TimeoutExpired from tests import HTTP_SERVER_CMD - PORT = 7986 HTTP_SERVER = f"{HTTP_SERVER_CMD} {PORT}" diff --git a/tests/executors/test_unixsocket_executor.py b/tests/executors/test_unixsocket_executor.py index 61befd5..2b467f6 100644 --- a/tests/executors/test_unixsocket_executor.py +++ b/tests/executors/test_unixsocket_executor.py @@ -1,5 +1,4 @@ -""" -TCPExecutor tests. +"""TCPExecutor tests. Some of these tests run ``nc``: when running Debian, make sure the ``netcat-openbsd`` package is used, not ``netcat-traditional``. diff --git a/tests/retry.py b/tests/retry.py index 6f30226..8741a6c 100644 --- a/tests/retry.py +++ b/tests/retry.py @@ -2,11 +2,10 @@ from datetime import datetime, timedelta, timezone from time import sleep -from typing import TypeVar, Callable, Type +from typing import Callable, Type, TypeVar from mirakuru import ExecutorError - T = TypeVar("T") diff --git a/tests/sample_daemon.py b/tests/sample_daemon.py index 79e625a..aff2281 100644 --- a/tests/sample_daemon.py +++ b/tests/sample_daemon.py @@ -1,5 +1,4 @@ -""" -Daemon sample application for tests purposes. +"""Daemon sample application for tests purposes. Stopping this process is possible only by the SIGKILL signal. @@ -14,10 +13,9 @@ import daemon -sys.path.append(os.getcwd()) # noqa - -from tests.signals import block_signals # pylint:disable=wrong-import-position +sys.path.append(os.getcwd()) +from tests.signals import block_signals # noqa: E402 with daemon.DaemonContext(initgroups=False): block_signals() diff --git a/tests/server_for_tests.py b/tests/server_for_tests.py index 4484a04..76d5428 100644 --- a/tests/server_for_tests.py +++ b/tests/server_for_tests.py @@ -1,5 +1,4 @@ -""" -HTTP server that responses with delays used for tests. +"""HTTP server that responses with delays used for tests. Example usage: @@ -13,18 +12,15 @@ """ import ast -import sys import os +import sys import time -from http.server import HTTPServer, BaseHTTPRequestHandler +from http.server import BaseHTTPRequestHandler, HTTPServer from urllib.parse import parse_qs -sys.path.append(os.getcwd()) # noqa +sys.path.append(os.getcwd()) -# pylint:disable=wrong-import-position -from tests.signals import block_signals - -# pylint:enable=wrong-import-position +from tests.signals import block_signals # noqa: E402 class SlowServerHandler(BaseHTTPRequestHandler): @@ -41,8 +37,7 @@ def do_GET(self) -> None: # pylint:disable=invalid-name self.wfile.write(b"Hi. I am very slow.") def do_HEAD(self) -> None: # pylint:disable=invalid-name - """ - Serve HEAD request. + """Serve HEAD request. but count to wait and return 500 response if wait time not exceeded due to the fact that HTTPServer will hang waiting for response diff --git a/tests/signals.py b/tests/signals.py index 4e4fc19..22760c5 100644 --- a/tests/signals.py +++ b/tests/signals.py @@ -5,8 +5,7 @@ def block_signals() -> None: - """ - Catch all of the signals that it is possible. + """Catch all of the signals that it is possible. Reject their default behaviour. The process is actually mortal but the only way to kill is to send SIGKILL signal (kill -9). diff --git a/tests/test_base.py b/tests/test_base.py index a37331b..c9777c6 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -1,6 +1,5 @@ """General mirakuru library tests.""" -# pylint: disable=wildcard-import,unused-wildcard-import -from mirakuru import * +from mirakuru import * # noqa: F403 def test_importing_mirakuru() -> None: diff --git a/tests/unixsocketserver_for_tests.py b/tests/unixsocketserver_for_tests.py index fee73f2..3c48859 100644 --- a/tests/unixsocketserver_for_tests.py +++ b/tests/unixsocketserver_for_tests.py @@ -22,9 +22,9 @@ # POSSIBILITY OF SUCH DAMAGE. """Sample unixsocket server with small modifications.""" +import os import socket import sys -import os from time import sleep SOCKET_ADDRESS = "./uds_socket"