diff --git a/CHANGES b/CHANGES index eb74dc809..b1c4851d0 100644 --- a/CHANGES +++ b/CHANGES @@ -15,6 +15,41 @@ $ pip install --user --upgrade --pre libtmux - _Future release notes will be placed here_ +### Breaking Changes + +#### Test helpers: Refactor + +Test helper functionality has been split into focused modules (#XXX): + +- `libtmux.test` module split into: + - `libtmux.test.constants`: Test-related constants (`TEST_SESSION_PREFIX`, etc.) + - `libtmux.test.environment`: Environment variable mocking + - `libtmux.test.random`: Random string generation utilities + - `libtmux.test.temporary`: Temporary session/window management + +**Breaking**: Import paths have changed. Update imports: + +```python +# Old (0.45.x and earlier) +from libtmux.test import ( + TEST_SESSION_PREFIX, + get_test_session_name, + get_test_window_name, + namer, + temp_session, + temp_window, + EnvironmentVarGuard, +) +``` + +```python +# New (0.46.0+) +from libtmux.test.constants import TEST_SESSION_PREFIX +from libtmux.test.environment import EnvironmentVarGuard +from libtmux.test.random import get_test_session_name, get_test_window_name, namer +from libtmux.test.temporary import temp_session, temp_window +``` + ### Development - CI: Check for runtime dependencies (#574) diff --git a/MIGRATION b/MIGRATION index fcba337e9..ee58dbce6 100644 --- a/MIGRATION +++ b/MIGRATION @@ -25,6 +25,41 @@ _Detailed migration steps for the next version will be posted here._ +## libtmux 0.45.x (Yet to be released) + +### Test helpers: Module moves + +Test helper functionality has been split into focused modules (#XXX): + +- `libtmux.test` module split into: + - `libtmux.test.constants`: Test-related constants (`TEST_SESSION_PREFIX`, etc.) + - `libtmux.test.environment`: Environment variable mocking + - `libtmux.test.random`: Random string generation utilities + - `libtmux.test.temporary`: Temporary session/window management + +**Breaking**: Import paths have changed. Update imports: + +```python +# Old (0.45.x and earlier) +from libtmux.test import ( + TEST_SESSION_PREFIX, + get_test_session_name, + get_test_window_name, + namer, + temp_session, + temp_window, + EnvironmentVarGuard, +) +``` + +```python +# New (0.46.0+) +from libtmux.test.constants import TEST_SESSION_PREFIX +from libtmux.test.environment import EnvironmentVarGuard +from libtmux.test.random import get_test_session_name, get_test_window_name, namer +from libtmux.test.temporary import temp_session, temp_window +``` + ## 0.35.0: Commands require explicit targets (2024-03-17) ### Commands require explicit targets (#535) diff --git a/pyproject.toml b/pyproject.toml index a6a014676..a95f12034 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -197,6 +197,7 @@ required-imports = [ [tool.ruff.lint.flake8-builtins] builtins-allowed-modules = [ "dataclasses", + "random", "types", ] diff --git a/src/libtmux/pytest_plugin.py b/src/libtmux/pytest_plugin.py index 320d31ca2..92da4676d 100644 --- a/src/libtmux/pytest_plugin.py +++ b/src/libtmux/pytest_plugin.py @@ -13,7 +13,8 @@ from libtmux import exc from libtmux.server import Server -from libtmux.test import TEST_SESSION_PREFIX, get_test_session_name, namer +from libtmux.test.constants import TEST_SESSION_PREFIX +from libtmux.test.random import get_test_session_name, namer if t.TYPE_CHECKING: import pathlib diff --git a/src/libtmux/test.py b/src/libtmux/test.py deleted file mode 100644 index 2bbaa2e53..000000000 --- a/src/libtmux/test.py +++ /dev/null @@ -1,356 +0,0 @@ -"""Helper methods for libtmux and downstream libtmux libraries.""" - -from __future__ import annotations - -import contextlib -import logging -import os -import pathlib -import random -import time -import typing as t - -from .exc import WaitTimeout - -logger = logging.getLogger(__name__) - -if t.TYPE_CHECKING: - import sys - import types - from collections.abc import Callable, Generator - - from libtmux.server import Server - from libtmux.session import Session - from libtmux.window import Window - - if sys.version_info >= (3, 11): - from typing import Self - else: - from typing_extensions import Self - - -TEST_SESSION_PREFIX = "libtmux_" -RETRY_TIMEOUT_SECONDS = int(os.getenv("RETRY_TIMEOUT_SECONDS", 8)) -RETRY_INTERVAL_SECONDS = float(os.getenv("RETRY_INTERVAL_SECONDS", 0.05)) - - -class RandomStrSequence: - """Factory to generate random string.""" - - def __init__( - self, - characters: str = "abcdefghijklmnopqrstuvwxyz0123456789_", - ) -> None: - """Create a random letter / number generator. 8 chars in length. - - >>> rng = RandomStrSequence() - >>> next(rng) - '...' - >>> len(next(rng)) - 8 - >>> type(next(rng)) - - """ - self.characters: str = characters - - def __iter__(self) -> RandomStrSequence: - """Return self.""" - return self - - def __next__(self) -> str: - """Return next random string.""" - return "".join(random.sample(self.characters, k=8)) - - -namer = RandomStrSequence() -current_dir = pathlib.Path(__file__) -example_dir = current_dir.parent / "examples" -fixtures_dir = current_dir / "fixtures" - - -def retry_until( - fun: Callable[[], bool], - seconds: float = RETRY_TIMEOUT_SECONDS, - *, - interval: float = RETRY_INTERVAL_SECONDS, - raises: bool | None = True, -) -> bool: - """ - Retry a function until a condition meets or the specified time passes. - - Parameters - ---------- - fun : callable - A function that will be called repeatedly until it returns ``True`` or - the specified time passes. - seconds : float - Seconds to retry. Defaults to ``8``, which is configurable via - ``RETRY_TIMEOUT_SECONDS`` environment variables. - interval : float - Time in seconds to wait between calls. Defaults to ``0.05`` and is - configurable via ``RETRY_INTERVAL_SECONDS`` environment variable. - raises : bool - Whether or not to raise an exception on timeout. Defaults to ``True``. - - Examples - -------- - >>> def fn(): - ... p = session.active_window.active_pane - ... return p.pane_current_path is not None - - >>> retry_until(fn) - True - - In pytest: - - >>> assert retry_until(fn, raises=False) - """ - ini = time.time() - - while not fun(): - end = time.time() - if end - ini >= seconds: - if raises: - raise WaitTimeout - return False - time.sleep(interval) - return True - - -def get_test_session_name(server: Server, prefix: str = TEST_SESSION_PREFIX) -> str: - """ - Faker to create a session name that doesn't exist. - - Parameters - ---------- - server : :class:`libtmux.Server` - libtmux server - prefix : str - prefix for sessions (e.g. ``libtmux_``). Defaults to - ``TEST_SESSION_PREFIX``. - - Returns - ------- - str - Random session name guaranteed to not collide with current ones. - - Examples - -------- - >>> get_test_session_name(server=server) - 'libtmux_...' - - Never the same twice: - >>> get_test_session_name(server=server) != get_test_session_name(server=server) - True - """ - while True: - session_name = prefix + next(namer) - if not server.has_session(session_name): - break - return session_name - - -def get_test_window_name( - session: Session, - prefix: str | None = TEST_SESSION_PREFIX, -) -> str: - """ - Faker to create a window name that doesn't exist. - - Parameters - ---------- - session : :class:`libtmux.Session` - libtmux session - prefix : str - prefix for windows (e.g. ``libtmux_``). Defaults to - ``TEST_SESSION_PREFIX``. - - ATM we reuse the test session prefix here. - - Returns - ------- - str - Random window name guaranteed to not collide with current ones. - - Examples - -------- - >>> get_test_window_name(session=session) - 'libtmux_...' - - Never the same twice: - >>> get_test_window_name(session=session) != get_test_window_name(session=session) - True - """ - assert prefix is not None - while True: - window_name = prefix + next(namer) - if len(session.windows.filter(window_name=window_name)) == 0: - break - return window_name - - -@contextlib.contextmanager -def temp_session( - server: Server, - *args: t.Any, - **kwargs: t.Any, -) -> Generator[Session, t.Any, t.Any]: - """ - Return a context manager with a temporary session. - - If no ``session_name`` is entered, :func:`get_test_session_name` will make - an unused session name. - - The session will destroy itself upon closing with :meth:`Session.session()`. - - Parameters - ---------- - server : :class:`libtmux.Server` - - Other Parameters - ---------------- - args : list - Arguments passed into :meth:`Server.new_session` - kwargs : dict - Keyword arguments passed into :meth:`Server.new_session` - - Yields - ------ - :class:`libtmux.Session` - Temporary session - - Examples - -------- - >>> with temp_session(server) as session: - ... session.new_window(window_name='my window') - Window(@3 2:my window, Session($... ...)) - """ - if "session_name" in kwargs: - session_name = kwargs.pop("session_name") - else: - session_name = get_test_session_name(server) - - session = server.new_session(session_name, *args, **kwargs) - - try: - yield session - finally: - if server.has_session(session_name): - session.kill() - return - - -@contextlib.contextmanager -def temp_window( - session: Session, - *args: t.Any, - **kwargs: t.Any, -) -> Generator[Window, t.Any, t.Any]: - """ - Return a context manager with a temporary window. - - The window will destroy itself upon closing with :meth:`window. - kill()`. - - If no ``window_name`` is entered, :func:`get_test_window_name` will make - an unused window name. - - Parameters - ---------- - session : :class:`libtmux.Session` - - Other Parameters - ---------------- - args : list - Arguments passed into :meth:`Session.new_window` - kwargs : dict - Keyword arguments passed into :meth:`Session.new_window` - - Yields - ------ - :class:`libtmux.Window` - temporary window - - Examples - -------- - >>> with temp_window(session) as window: - ... window - Window(@2 2:... Session($1 libtmux_...)) - - - >>> with temp_window(session) as window: - ... window.split() - Pane(%4 Window(@3 2:libtmux_..., Session($1 libtmux_...))) - """ - if "window_name" not in kwargs: - window_name = get_test_window_name(session) - else: - window_name = kwargs.pop("window_name") - - window = session.new_window(window_name, *args, **kwargs) - - # Get ``window_id`` before returning it, it may be killed within context. - window_id = window.window_id - assert window_id is not None - assert isinstance(window_id, str) - - try: - yield window - finally: - if len(session.windows.filter(window_id=window_id)) > 0: - window.kill() - return - - -class EnvironmentVarGuard: - """Mock environmental variables safely. - - Helps rotect the environment variable properly. Can be used as context - manager. - - Notes - ----- - Vendorized to fix issue with Anaconda Python 2 not including test module, - see #121 [1]_ - - References - ---------- - .. [1] Just installed, "ImportError: cannot import name test_support". - GitHub issue for tmuxp. https://github.com/tmux-python/tmuxp/issues/121. - Created October 12th, 2015. Accessed April 7th, 2018. - """ - - def __init__(self) -> None: - self._environ = os.environ - self._unset: set[str] = set() - self._reset: dict[str, str] = {} - - def set(self, envvar: str, value: str) -> None: - """Set environment variable.""" - if envvar not in self._environ: - self._unset.add(envvar) - else: - self._reset[envvar] = self._environ[envvar] - self._environ[envvar] = value - - def unset(self, envvar: str) -> None: - """Unset environment variable.""" - if envvar in self._environ: - self._reset[envvar] = self._environ[envvar] - del self._environ[envvar] - - def __enter__(self) -> Self: - """Return context for for context manager.""" - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_value: BaseException | None, - exc_tb: types.TracebackType | None, - ) -> None: - """Cleanup to run after context manager finishes.""" - for envvar, value in self._reset.items(): - self._environ[envvar] = value - for unset in self._unset: - del self._environ[unset] diff --git a/src/libtmux/test/__init__.py b/src/libtmux/test/__init__.py new file mode 100644 index 000000000..8fba9fa82 --- /dev/null +++ b/src/libtmux/test/__init__.py @@ -0,0 +1,36 @@ +"""Helper methods for libtmux and downstream libtmux libraries.""" + +from __future__ import annotations + +import contextlib +import logging +import os +import pathlib +import random +import time +import typing as t + +from libtmux.exc import WaitTimeout +from libtmux.test.constants import ( + RETRY_INTERVAL_SECONDS, + RETRY_TIMEOUT_SECONDS, + TEST_SESSION_PREFIX, +) + +from .random import namer + +logger = logging.getLogger(__name__) + +if t.TYPE_CHECKING: + import sys + import types + from collections.abc import Callable, Generator + + from libtmux.server import Server + from libtmux.session import Session + from libtmux.window import Window + + if sys.version_info >= (3, 11): + from typing import Self + else: + from typing_extensions import Self diff --git a/src/libtmux/test/constants.py b/src/libtmux/test/constants.py new file mode 100644 index 000000000..63d644da3 --- /dev/null +++ b/src/libtmux/test/constants.py @@ -0,0 +1,9 @@ +"""Constants for libtmux test helpers.""" + +from __future__ import annotations + +import os + +TEST_SESSION_PREFIX = "libtmux_" +RETRY_TIMEOUT_SECONDS = int(os.getenv("RETRY_TIMEOUT_SECONDS", 8)) +RETRY_INTERVAL_SECONDS = float(os.getenv("RETRY_INTERVAL_SECONDS", 0.05)) diff --git a/src/libtmux/test/environment.py b/src/libtmux/test/environment.py new file mode 100644 index 000000000..9023c1f83 --- /dev/null +++ b/src/libtmux/test/environment.py @@ -0,0 +1,72 @@ +"""Helper methods for libtmux and downstream libtmux libraries.""" + +from __future__ import annotations + +import logging +import os +import typing as t + +logger = logging.getLogger(__name__) + +if t.TYPE_CHECKING: + import sys + import types + + if sys.version_info >= (3, 11): + from typing import Self + else: + from typing_extensions import Self + + +class EnvironmentVarGuard: + """Mock environmental variables safely. + + Helps rotect the environment variable properly. Can be used as context + manager. + + Notes + ----- + Vendorized to fix issue with Anaconda Python 2 not including test module, + see #121 [1]_ + + References + ---------- + .. [1] Just installed, "ImportError: cannot import name test_support". + GitHub issue for tmuxp. https://github.com/tmux-python/tmuxp/issues/121. + Created October 12th, 2015. Accessed April 7th, 2018. + """ + + def __init__(self) -> None: + self._environ = os.environ + self._unset: set[str] = set() + self._reset: dict[str, str] = {} + + def set(self, envvar: str, value: str) -> None: + """Set environment variable.""" + if envvar not in self._environ: + self._unset.add(envvar) + else: + self._reset[envvar] = self._environ[envvar] + self._environ[envvar] = value + + def unset(self, envvar: str) -> None: + """Unset environment variable.""" + if envvar in self._environ: + self._reset[envvar] = self._environ[envvar] + del self._environ[envvar] + + def __enter__(self) -> Self: + """Return context for for context manager.""" + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + exc_tb: types.TracebackType | None, + ) -> None: + """Cleanup to run after context manager finishes.""" + for envvar, value in self._reset.items(): + self._environ[envvar] = value + for unset in self._unset: + del self._environ[unset] diff --git a/src/libtmux/test/random.py b/src/libtmux/test/random.py new file mode 100644 index 000000000..abcb95bce --- /dev/null +++ b/src/libtmux/test/random.py @@ -0,0 +1,134 @@ +"""Random helpers for libtmux and downstream libtmux libraries.""" + +from __future__ import annotations + +import logging +import random +import typing as t + +from libtmux.test.constants import ( + TEST_SESSION_PREFIX, +) + +logger = logging.getLogger(__name__) + +if t.TYPE_CHECKING: + import sys + + from libtmux.server import Server + from libtmux.session import Session + + if sys.version_info >= (3, 11): + pass + + +logger = logging.getLogger(__name__) + +if t.TYPE_CHECKING: + import sys + + if sys.version_info >= (3, 11): + pass + + +class RandomStrSequence: + """Factory to generate random string.""" + + def __init__( + self, + characters: str = "abcdefghijklmnopqrstuvwxyz0123456789_", + ) -> None: + """Create a random letter / number generator. 8 chars in length. + + >>> rng = RandomStrSequence() + >>> next(rng) + '...' + >>> len(next(rng)) + 8 + >>> type(next(rng)) + + """ + self.characters: str = characters + + def __iter__(self) -> RandomStrSequence: + """Return self.""" + return self + + def __next__(self) -> str: + """Return next random string.""" + return "".join(random.sample(self.characters, k=8)) + + +namer = RandomStrSequence() + + +def get_test_session_name(server: Server, prefix: str = TEST_SESSION_PREFIX) -> str: + """ + Faker to create a session name that doesn't exist. + + Parameters + ---------- + server : :class:`libtmux.Server` + libtmux server + prefix : str + prefix for sessions (e.g. ``libtmux_``). Defaults to + ``TEST_SESSION_PREFIX``. + + Returns + ------- + str + Random session name guaranteed to not collide with current ones. + + Examples + -------- + >>> get_test_session_name(server=server) + 'libtmux_...' + + Never the same twice: + >>> get_test_session_name(server=server) != get_test_session_name(server=server) + True + """ + while True: + session_name = prefix + next(namer) + if not server.has_session(session_name): + break + return session_name + + +def get_test_window_name( + session: Session, + prefix: str | None = TEST_SESSION_PREFIX, +) -> str: + """ + Faker to create a window name that doesn't exist. + + Parameters + ---------- + session : :class:`libtmux.Session` + libtmux session + prefix : str + prefix for windows (e.g. ``libtmux_``). Defaults to + ``TEST_SESSION_PREFIX``. + + ATM we reuse the test session prefix here. + + Returns + ------- + str + Random window name guaranteed to not collide with current ones. + + Examples + -------- + >>> get_test_window_name(session=session) + 'libtmux_...' + + Never the same twice: + >>> get_test_window_name(session=session) != get_test_window_name(session=session) + True + """ + assert prefix is not None + while True: + window_name = prefix + next(namer) + if len(session.windows.filter(window_name=window_name)) == 0: + break + return window_name diff --git a/src/libtmux/test/retry.py b/src/libtmux/test/retry.py new file mode 100644 index 000000000..1f989e73a --- /dev/null +++ b/src/libtmux/test/retry.py @@ -0,0 +1,71 @@ +"""Retry helpers for libtmux and downstream libtmux libraries.""" + +from __future__ import annotations + +import logging +import time +import typing as t + +from libtmux.exc import WaitTimeout +from libtmux.test.constants import ( + RETRY_INTERVAL_SECONDS, + RETRY_TIMEOUT_SECONDS, +) + +logger = logging.getLogger(__name__) + +if t.TYPE_CHECKING: + import sys + from collections.abc import Callable + + if sys.version_info >= (3, 11): + pass + + +def retry_until( + fun: Callable[[], bool], + seconds: float = RETRY_TIMEOUT_SECONDS, + *, + interval: float = RETRY_INTERVAL_SECONDS, + raises: bool | None = True, +) -> bool: + """ + Retry a function until a condition meets or the specified time passes. + + Parameters + ---------- + fun : callable + A function that will be called repeatedly until it returns ``True`` or + the specified time passes. + seconds : float + Seconds to retry. Defaults to ``8``, which is configurable via + ``RETRY_TIMEOUT_SECONDS`` environment variables. + interval : float + Time in seconds to wait between calls. Defaults to ``0.05`` and is + configurable via ``RETRY_INTERVAL_SECONDS`` environment variable. + raises : bool + Whether or not to raise an exception on timeout. Defaults to ``True``. + + Examples + -------- + >>> def fn(): + ... p = session.active_window.active_pane + ... return p.pane_current_path is not None + + >>> retry_until(fn) + True + + In pytest: + + >>> assert retry_until(fn, raises=False) + """ + ini = time.time() + + while not fun(): + end = time.time() + if end - ini >= seconds: + if raises: + raise WaitTimeout + return False + time.sleep(interval) + return True diff --git a/src/libtmux/test/temporary.py b/src/libtmux/test/temporary.py new file mode 100644 index 000000000..cc2106edd --- /dev/null +++ b/src/libtmux/test/temporary.py @@ -0,0 +1,135 @@ +"""Temporary object helpers for libtmux and downstream libtmux libraries.""" + +from __future__ import annotations + +import contextlib +import logging +import typing as t + +from libtmux.test.random import get_test_session_name, get_test_window_name + +logger = logging.getLogger(__name__) + +if t.TYPE_CHECKING: + import sys + from collections.abc import Generator + + from libtmux.server import Server + from libtmux.session import Session + from libtmux.window import Window + + if sys.version_info >= (3, 11): + pass + + +@contextlib.contextmanager +def temp_session( + server: Server, + *args: t.Any, + **kwargs: t.Any, +) -> Generator[Session, t.Any, t.Any]: + """ + Return a context manager with a temporary session. + + If no ``session_name`` is entered, :func:`get_test_session_name` will make + an unused session name. + + The session will destroy itself upon closing with :meth:`Session.session()`. + + Parameters + ---------- + server : :class:`libtmux.Server` + + Other Parameters + ---------------- + args : list + Arguments passed into :meth:`Server.new_session` + kwargs : dict + Keyword arguments passed into :meth:`Server.new_session` + + Yields + ------ + :class:`libtmux.Session` + Temporary session + + Examples + -------- + >>> with temp_session(server) as session: + ... session.new_window(window_name='my window') + Window(@3 2:my window, Session($... ...)) + """ + if "session_name" in kwargs: + session_name = kwargs.pop("session_name") + else: + session_name = get_test_session_name(server) + + session = server.new_session(session_name, *args, **kwargs) + + try: + yield session + finally: + if server.has_session(session_name): + session.kill() + return + + +@contextlib.contextmanager +def temp_window( + session: Session, + *args: t.Any, + **kwargs: t.Any, +) -> Generator[Window, t.Any, t.Any]: + """ + Return a context manager with a temporary window. + + The window will destroy itself upon closing with :meth:`window. + kill()`. + + If no ``window_name`` is entered, :func:`get_test_window_name` will make + an unused window name. + + Parameters + ---------- + session : :class:`libtmux.Session` + + Other Parameters + ---------------- + args : list + Arguments passed into :meth:`Session.new_window` + kwargs : dict + Keyword arguments passed into :meth:`Session.new_window` + + Yields + ------ + :class:`libtmux.Window` + temporary window + + Examples + -------- + >>> with temp_window(session) as window: + ... window + Window(@2 2:... Session($1 libtmux_...)) + + + >>> with temp_window(session) as window: + ... window.split() + Pane(%4 Window(@3 2:libtmux_..., Session($1 libtmux_...))) + """ + if "window_name" not in kwargs: + window_name = get_test_window_name(session) + else: + window_name = kwargs.pop("window_name") + + window = session.new_window(window_name, *args, **kwargs) + + # Get ``window_id`` before returning it, it may be killed within context. + window_id = window.window_id + assert window_id is not None + assert isinstance(window_id, str) + + try: + yield window + finally: + if len(session.windows.filter(window_id=window_id)) > 0: + window.kill() + return diff --git a/tests/legacy_api/test_session.py b/tests/legacy_api/test_session.py index ffe115ae2..c756999ea 100644 --- a/tests/legacy_api/test_session.py +++ b/tests/legacy_api/test_session.py @@ -12,7 +12,8 @@ from libtmux.common import has_gte_version, has_lt_version from libtmux.pane import Pane from libtmux.session import Session -from libtmux.test import TEST_SESSION_PREFIX, namer +from libtmux.test.constants import TEST_SESSION_PREFIX +from libtmux.test.random import namer from libtmux.window import Window if t.TYPE_CHECKING: diff --git a/tests/legacy_api/test_tmuxobject.py b/tests/legacy_api/test_tmuxobject.py index 790b8cebb..dc023d24b 100644 --- a/tests/legacy_api/test_tmuxobject.py +++ b/tests/legacy_api/test_tmuxobject.py @@ -7,7 +7,8 @@ from libtmux.pane import Pane from libtmux.session import Session -from libtmux.test import TEST_SESSION_PREFIX, namer +from libtmux.test.constants import TEST_SESSION_PREFIX +from libtmux.test.random import namer from libtmux.window import Window if t.TYPE_CHECKING: diff --git a/tests/test_test.py b/tests/test/test_retry.py similarity index 97% rename from tests/test_test.py rename to tests/test/test_retry.py index a9471363c..36e35930d 100644 --- a/tests/test_test.py +++ b/tests/test/test_retry.py @@ -7,7 +7,7 @@ import pytest from libtmux.exc import WaitTimeout -from libtmux.test import retry_until +from libtmux.test.retry import retry_until def test_retry_three_times() -> None: diff --git a/tests/test_pane.py b/tests/test_pane.py index 21d0cbb87..746467851 100644 --- a/tests/test_pane.py +++ b/tests/test_pane.py @@ -10,7 +10,7 @@ from libtmux.common import has_gte_version, has_lt_version, has_lte_version from libtmux.constants import PaneDirection, ResizeAdjustmentDirection -from libtmux.test import retry_until +from libtmux.test.retry import retry_until if t.TYPE_CHECKING: from libtmux.session import Session diff --git a/tests/test_session.py b/tests/test_session.py index 33b82dd72..88d5f79e6 100644 --- a/tests/test_session.py +++ b/tests/test_session.py @@ -13,7 +13,8 @@ from libtmux.constants import WindowDirection from libtmux.pane import Pane from libtmux.session import Session -from libtmux.test import TEST_SESSION_PREFIX, namer +from libtmux.test.constants import TEST_SESSION_PREFIX +from libtmux.test.random import namer from libtmux.window import Window if t.TYPE_CHECKING: diff --git a/tests/test_tmuxobject.py b/tests/test_tmuxobject.py index 5c77e29e4..e8c8be9ec 100644 --- a/tests/test_tmuxobject.py +++ b/tests/test_tmuxobject.py @@ -7,7 +7,8 @@ from libtmux.pane import Pane from libtmux.session import Session -from libtmux.test import TEST_SESSION_PREFIX, namer +from libtmux.test.constants import TEST_SESSION_PREFIX +from libtmux.test.random import namer from libtmux.window import Window if t.TYPE_CHECKING: