1
- """Helper methods for libtmux and downstream libtmux libraries."""
1
+ """Provide helper methods for libtmux and downstream libtmux libraries.
2
+
3
+ This module includes various testing utilities, context managers, and utility
4
+ functions to facilitate session creation, window creation, retries, and
5
+ environment variable manipulation. It preserves existing testing scenarios and
6
+ patterns, ensuring stable and consistent integration tests across different
7
+ libtmux-based projects.
8
+ """
2
9
3
10
from __future__ import annotations
4
11
30
37
31
38
32
39
class RandomStrSequence :
33
- """Factory to generate random string."""
40
+ """Generate random string values (8 chars each) from a given character set.
41
+
42
+ Examples
43
+ --------
44
+ >>> rng = RandomStrSequence()
45
+ >>> next(rng)
46
+ '...'
47
+ >>> len(next(rng))
48
+ 8
49
+ >>> type(next(rng))
50
+ <class 'str'>
51
+ """
34
52
35
53
def __init__ (
36
54
self ,
37
55
characters : str = "abcdefghijklmnopqrstuvwxyz0123456789_" ,
38
56
) -> None :
39
- """Create a random letter / number generator. 8 chars in length.
40
-
41
- >>> rng = RandomStrSequence()
42
- >>> next(rng)
43
- '...'
44
- >>> len(next(rng))
45
- 8
46
- >>> type(next(rng))
47
- <class 'str'>
48
- """
49
57
self .characters : str = characters
50
58
51
59
def __iter__ (self ) -> RandomStrSequence :
52
- """Return self."""
60
+ """Return self as iterator ."""
53
61
return self
54
62
55
63
def __next__ (self ) -> str :
56
- """Return next random string."""
64
+ """Return next random 8-character string."""
57
65
return "" .join (random .sample (self .characters , k = 8 ))
58
66
59
67
@@ -70,22 +78,21 @@ def retry_until(
70
78
interval : float = RETRY_INTERVAL_SECONDS ,
71
79
raises : bool | None = True ,
72
80
) -> bool :
73
- """
74
- Retry a function until a condition meets or the specified time passes.
81
+ r"""Retry a function until it returns True or time expires.
75
82
76
83
Parameters
77
84
----------
78
85
fun : callable
79
- A function that will be called repeatedly until it returns `` True`` or
80
- the specified time passes.
81
- seconds : float
82
- Seconds to retry . Defaults to ``8``, which is configurable via
83
- `` RETRY_TIMEOUT_SECONDS`` environment variables .
84
- interval : float
85
- Time in seconds to wait between calls. Defaults to `` 0.05`` and is
86
- configurable via `` RETRY_INTERVAL_SECONDS`` environment variable .
87
- raises : bool
88
- Whether or not to raise an exception on timeout. Defaults to `` True`` .
86
+ A function that will be called repeatedly until it returns True or the
87
+ specified time passes.
88
+ seconds : float, optional
89
+ Time limit for retries . Defaults to 8 seconds or the environment
90
+ variable ` RETRY_TIMEOUT_SECONDS`.
91
+ interval : float, optional
92
+ Time in seconds to wait between calls. Defaults to 0.05 or
93
+ ` RETRY_INTERVAL_SECONDS`.
94
+ raises : bool, optional
95
+ Whether to raise :exc:`WaitTimeout` on timeout. Defaults to True.
89
96
90
97
Examples
91
98
--------
@@ -100,11 +107,11 @@ def retry_until(
100
107
101
108
>>> assert retry_until(fn, raises=False)
102
109
"""
103
- ini = time .time ()
110
+ start_time = time .time ()
104
111
105
112
while not fun ():
106
- end = time .time ()
107
- if end - ini >= seconds :
113
+ now = time .time ()
114
+ if now - start_time >= seconds :
108
115
if raises :
109
116
raise WaitTimeout
110
117
return False
@@ -114,20 +121,19 @@ def retry_until(
114
121
115
122
def get_test_session_name (server : Server , prefix : str = TEST_SESSION_PREFIX ) -> str :
116
123
"""
117
- Faker to create a session name that doesn't exist.
124
+ Generate a unique session name that does not exist on the server .
118
125
119
126
Parameters
120
127
----------
121
- server : :class:`libtmux. Server`
122
- libtmux server
128
+ server : Server
129
+ The tmux server instance.
123
130
prefix : str
124
- prefix for sessions (e.g. ``libtmux_``). Defaults to
125
- ``TEST_SESSION_PREFIX``.
131
+ Prefix for the generated session name. Defaults to 'libtmux_'.
126
132
127
133
Returns
128
134
-------
129
135
str
130
- Random session name guaranteed to not collide with current ones .
136
+ Random session name guaranteed not to collide with existing sessions .
131
137
132
138
Examples
133
139
--------
@@ -150,22 +156,19 @@ def get_test_window_name(
150
156
prefix : str | None = TEST_SESSION_PREFIX ,
151
157
) -> str :
152
158
"""
153
- Faker to create a window name that doesn't exist.
159
+ Generate a unique window name that does not exist in the given session .
154
160
155
161
Parameters
156
162
----------
157
- session : :class:`libtmux.Session`
158
- libtmux session
159
- prefix : str
160
- prefix for windows (e.g. ``libtmux_``). Defaults to
161
- ``TEST_SESSION_PREFIX``.
162
-
163
- ATM we reuse the test session prefix here.
163
+ session : Session
164
+ The tmux session instance.
165
+ prefix : str, optional
166
+ Prefix for the generated window name. Defaults to 'libtmux_'.
164
167
165
168
Returns
166
169
-------
167
170
str
168
- Random window name guaranteed to not collide with current ones .
171
+ Random window name guaranteed not to collide with existing windows .
169
172
170
173
Examples
171
174
--------
@@ -191,28 +194,25 @@ def temp_session(
191
194
** kwargs : t .Any ,
192
195
) -> Generator [Session , t .Any , t .Any ]:
193
196
"""
194
- Return a context manager with a temporary session.
195
-
196
- If no ``session_name`` is entered, :func:`get_test_session_name` will make
197
- an unused session name.
197
+ Provide a context manager for a temporary session, killed on exit.
198
198
199
- The session will destroy itself upon closing with :meth:`Session.session()`.
199
+ If no ``session_name`` is specified, :func:`get_test_session_name` will
200
+ generate an unused one. The session is destroyed upon exiting the context
201
+ manager.
200
202
201
203
Parameters
202
204
----------
203
- server : :class:`libtmux.Server`
204
-
205
- Other Parameters
206
- ----------------
205
+ server : Server
206
+ The tmux server instance.
207
207
args : list
208
- Arguments passed into :meth:`Server.new_session`
208
+ Additional positional arguments for :meth:`Server.new_session`.
209
209
kwargs : dict
210
- Keyword arguments passed into :meth:`Server.new_session`
210
+ Keyword arguments for :meth:`Server.new_session`.
211
211
212
212
Yields
213
213
------
214
- :class:`libtmux. Session`
215
- Temporary session
214
+ Session
215
+ The newly created temporary session.
216
216
217
217
Examples
218
218
--------
@@ -242,37 +242,32 @@ def temp_window(
242
242
** kwargs : t .Any ,
243
243
) -> Generator [Window , t .Any , t .Any ]:
244
244
"""
245
- Return a context manager with a temporary window.
245
+ Provide a context manager for a temporary window, killed on exit .
246
246
247
- The window will destroy itself upon closing with :meth:`window.
248
- kill()`.
249
-
250
- If no ``window_name`` is entered, :func:`get_test_window_name` will make
251
- an unused window name.
247
+ If no ``window_name`` is specified, :func:`get_test_window_name` will
248
+ generate an unused one. The window is destroyed upon exiting the context
249
+ manager.
252
250
253
251
Parameters
254
252
----------
255
- session : :class:`libtmux.Session`
256
-
257
- Other Parameters
258
- ----------------
253
+ session : Session
254
+ The tmux session instance.
259
255
args : list
260
- Arguments passed into :meth:`Session.new_window`
256
+ Additional positional arguments for :meth:`Session.new_window`.
261
257
kwargs : dict
262
- Keyword arguments passed into :meth:`Session.new_window`
258
+ Keyword arguments for :meth:`Session.new_window`.
263
259
264
260
Yields
265
261
------
266
- :class:`libtmux. Window`
267
- temporary window
262
+ Window
263
+ The newly created temporary window.
268
264
269
265
Examples
270
266
--------
271
267
>>> with temp_window(session) as window:
272
268
... window
273
269
Window(@2 2:... Session($1 libtmux_...))
274
270
275
-
276
271
>>> with temp_window(session) as window:
277
272
... window.split()
278
273
Pane(%4 Window(@3 2:libtmux_..., Session($1 libtmux_...)))
@@ -283,8 +278,6 @@ def temp_window(
283
278
window_name = kwargs .pop ("window_name" )
284
279
285
280
window = session .new_window (window_name , * args , ** kwargs )
286
-
287
- # Get ``window_id`` before returning it, it may be killed within context.
288
281
window_id = window .window_id
289
282
assert window_id is not None
290
283
assert isinstance (window_id , str )
@@ -298,21 +291,19 @@ def temp_window(
298
291
299
292
300
293
class EnvironmentVarGuard :
301
- """Mock environmental variables safely .
294
+ """Safely mock environmental variables within a context manager .
302
295
303
- Helps rotect the environment variable properly. Can be used as context
304
- manager.
296
+ Ensures any changes to environment variables are reverted upon exit.
305
297
306
298
Notes
307
299
-----
308
- Vendorized to fix issue with Anaconda Python 2 not including test module,
309
- see #121 [1]_
300
+ This is vendorized to address issues where some Python distributions do
301
+ not include test modules such as test_support.
310
302
311
303
References
312
304
----------
313
- .. [1] Just installed, "ImportError: cannot import name test_support".
314
- GitHub issue for tmuxp. https://github.com/tmux-python/tmuxp/issues/121.
315
- Created October 12th, 2015. Accessed April 7th, 2018.
305
+ #. "ImportError: cannot import name test_support" found in certain Python
306
+ distributions, see issue #121 in the tmuxp project.
316
307
"""
317
308
318
309
def __init__ (self ) -> None :
@@ -321,21 +312,21 @@ def __init__(self) -> None:
321
312
self ._reset : dict [str , str ] = {}
322
313
323
314
def set (self , envvar : str , value : str ) -> None :
324
- """Set environment variable."""
315
+ """Set an environment variable, preserving prior state ."""
325
316
if envvar not in self ._environ :
326
317
self ._unset .add (envvar )
327
318
else :
328
319
self ._reset [envvar ] = self ._environ [envvar ]
329
320
self ._environ [envvar ] = value
330
321
331
322
def unset (self , envvar : str ) -> None :
332
- """Unset environment variable."""
323
+ """Unset an environment variable, preserving prior state ."""
333
324
if envvar in self ._environ :
334
325
self ._reset [envvar ] = self ._environ [envvar ]
335
326
del self ._environ [envvar ]
336
327
337
328
def __enter__ (self ) -> Self :
338
- """Return context for for context manager."""
329
+ """Enter context manager."""
339
330
return self
340
331
341
332
def __exit__ (
@@ -344,7 +335,7 @@ def __exit__(
344
335
exc_value : BaseException | None ,
345
336
exc_tb : types .TracebackType | None ,
346
337
) -> None :
347
- """Cleanup to run after context manager finishes ."""
338
+ """Exit context manager, reverting environment changes ."""
348
339
for envvar , value in self ._reset .items ():
349
340
self ._environ [envvar ] = value
350
341
for unset in self ._unset :
0 commit comments