xvfbwrapper 0.2.33__tar.gz → 0.2.35__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {xvfbwrapper-0.2.33/xvfbwrapper.egg-info → xvfbwrapper-0.2.35}/PKG-INFO +15 -10
- {xvfbwrapper-0.2.33 → xvfbwrapper-0.2.35}/README.md +13 -9
- {xvfbwrapper-0.2.33 → xvfbwrapper-0.2.35}/pyproject.toml +3 -1
- {xvfbwrapper-0.2.33 → xvfbwrapper-0.2.35}/test_xvfb.py +11 -32
- {xvfbwrapper-0.2.33 → xvfbwrapper-0.2.35}/tox.ini +5 -7
- {xvfbwrapper-0.2.33 → xvfbwrapper-0.2.35/xvfbwrapper.egg-info}/PKG-INFO +15 -10
- {xvfbwrapper-0.2.33 → xvfbwrapper-0.2.35}/xvfbwrapper.py +8 -7
- {xvfbwrapper-0.2.33 → xvfbwrapper-0.2.35}/LICENSE +0 -0
- {xvfbwrapper-0.2.33 → xvfbwrapper-0.2.35}/MANIFEST.in +0 -0
- {xvfbwrapper-0.2.33 → xvfbwrapper-0.2.35}/setup.cfg +0 -0
- {xvfbwrapper-0.2.33 → xvfbwrapper-0.2.35}/xvfbwrapper.egg-info/SOURCES.txt +0 -0
- {xvfbwrapper-0.2.33 → xvfbwrapper-0.2.35}/xvfbwrapper.egg-info/dependency_links.txt +0 -0
- {xvfbwrapper-0.2.33 → xvfbwrapper-0.2.35}/xvfbwrapper.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xvfbwrapper
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.35
|
|
4
4
|
Summary: Manage headless displays with Xvfb (X virtual framebuffer)
|
|
5
5
|
Author: Corey Goldberg
|
|
6
6
|
Maintainer: Corey Goldberg
|
|
@@ -23,6 +23,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
23
23
|
Classifier: Programming Language :: Python :: 3.12
|
|
24
24
|
Classifier: Programming Language :: Python :: 3.13
|
|
25
25
|
Classifier: Programming Language :: Python :: 3.14
|
|
26
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
26
27
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
27
28
|
Requires-Python: >=3.10
|
|
28
29
|
Description-Content-Type: text/markdown
|
|
@@ -63,13 +64,21 @@ See the [module API documentation][api-docs] for more information.
|
|
|
63
64
|
</td>
|
|
64
65
|
</tr>
|
|
65
66
|
<tr>
|
|
66
|
-
<td>
|
|
67
|
+
<td>Tests (CI)</td>
|
|
67
68
|
<td>
|
|
68
69
|
<a href="https://github.com/cgoldberg/xvfbwrapper/actions/workflows/test.yml">
|
|
69
70
|
<img src="https://github.com/cgoldberg/xvfbwrapper/actions/workflows/test.yml/badge.svg">
|
|
70
71
|
</a>
|
|
71
72
|
</td>
|
|
72
73
|
</tr>
|
|
74
|
+
<tr>
|
|
75
|
+
<td>API Docs (CI)</td>
|
|
76
|
+
<td>
|
|
77
|
+
<a href="https://github.com/cgoldberg/xvfbwrapper/actions/workflows/docs.yml">
|
|
78
|
+
<img src="https://github.com/cgoldberg/xvfbwrapper/actions/workflows/docs.yml/badge.svg">
|
|
79
|
+
</a>
|
|
80
|
+
</td>
|
|
81
|
+
</tr>
|
|
73
82
|
<tr>
|
|
74
83
|
<td>Supported Python Versions</td>
|
|
75
84
|
<td>
|
|
@@ -217,12 +226,10 @@ xvfb.start() # Xvfb will be called with the `ttyxx -nocursor +extension RANDR`
|
|
|
217
226
|
|
|
218
227
|
#### Multithreaded execution:
|
|
219
228
|
|
|
220
|
-
To run several Xvfb displays at the same time, you can use the `environ`
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
`
|
|
224
|
-
environment, you must use the copy method of `os.environ` and not simply
|
|
225
|
-
assign a new variable to `os.environ`:
|
|
229
|
+
To run several Xvfb displays at the same time, you can use the `environ` keyword
|
|
230
|
+
when starting the `Xvfb` instances. This provides isolation between processes or
|
|
231
|
+
threads. If you wish to inherit your current environment, you must use the copy
|
|
232
|
+
method of `os.environ` and not simply assign a new variable to `os.environ`:
|
|
226
233
|
|
|
227
234
|
```python
|
|
228
235
|
import os
|
|
@@ -285,8 +292,6 @@ if __name__ == "__main__":
|
|
|
285
292
|
|
|
286
293
|
## Development
|
|
287
294
|
|
|
288
|
-
- Git: [github.com/cgoldberg/xvfbwrapper.git][github-repo]
|
|
289
|
-
|
|
290
295
|
- Create a virtual env and install required testing packages:
|
|
291
296
|
|
|
292
297
|
```
|
|
@@ -32,13 +32,21 @@ See the [module API documentation][api-docs] for more information.
|
|
|
32
32
|
</td>
|
|
33
33
|
</tr>
|
|
34
34
|
<tr>
|
|
35
|
-
<td>
|
|
35
|
+
<td>Tests (CI)</td>
|
|
36
36
|
<td>
|
|
37
37
|
<a href="https://github.com/cgoldberg/xvfbwrapper/actions/workflows/test.yml">
|
|
38
38
|
<img src="https://github.com/cgoldberg/xvfbwrapper/actions/workflows/test.yml/badge.svg">
|
|
39
39
|
</a>
|
|
40
40
|
</td>
|
|
41
41
|
</tr>
|
|
42
|
+
<tr>
|
|
43
|
+
<td>API Docs (CI)</td>
|
|
44
|
+
<td>
|
|
45
|
+
<a href="https://github.com/cgoldberg/xvfbwrapper/actions/workflows/docs.yml">
|
|
46
|
+
<img src="https://github.com/cgoldberg/xvfbwrapper/actions/workflows/docs.yml/badge.svg">
|
|
47
|
+
</a>
|
|
48
|
+
</td>
|
|
49
|
+
</tr>
|
|
42
50
|
<tr>
|
|
43
51
|
<td>Supported Python Versions</td>
|
|
44
52
|
<td>
|
|
@@ -186,12 +194,10 @@ xvfb.start() # Xvfb will be called with the `ttyxx -nocursor +extension RANDR`
|
|
|
186
194
|
|
|
187
195
|
#### Multithreaded execution:
|
|
188
196
|
|
|
189
|
-
To run several Xvfb displays at the same time, you can use the `environ`
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
`
|
|
193
|
-
environment, you must use the copy method of `os.environ` and not simply
|
|
194
|
-
assign a new variable to `os.environ`:
|
|
197
|
+
To run several Xvfb displays at the same time, you can use the `environ` keyword
|
|
198
|
+
when starting the `Xvfb` instances. This provides isolation between processes or
|
|
199
|
+
threads. If you wish to inherit your current environment, you must use the copy
|
|
200
|
+
method of `os.environ` and not simply assign a new variable to `os.environ`:
|
|
195
201
|
|
|
196
202
|
```python
|
|
197
203
|
import os
|
|
@@ -254,8 +260,6 @@ if __name__ == "__main__":
|
|
|
254
260
|
|
|
255
261
|
## Development
|
|
256
262
|
|
|
257
|
-
- Git: [github.com/cgoldberg/xvfbwrapper.git][github-repo]
|
|
258
|
-
|
|
259
263
|
- Create a virtual env and install required testing packages:
|
|
260
264
|
|
|
261
265
|
```
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "xvfbwrapper"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.35"
|
|
8
8
|
description = "Manage headless displays with Xvfb (X virtual framebuffer)"
|
|
9
9
|
license = "MIT"
|
|
10
10
|
license-files = ["LICENSE"]
|
|
@@ -28,6 +28,7 @@ classifiers = [
|
|
|
28
28
|
"Programming Language :: Python :: 3.12",
|
|
29
29
|
"Programming Language :: Python :: 3.13",
|
|
30
30
|
"Programming Language :: Python :: 3.14",
|
|
31
|
+
"Programming Language :: Python :: 3.15",
|
|
31
32
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
32
33
|
]
|
|
33
34
|
|
|
@@ -63,6 +64,7 @@ py-modules = ["xvfbwrapper"]
|
|
|
63
64
|
|
|
64
65
|
[tool.pytest]
|
|
65
66
|
addopts = ["-v"]
|
|
67
|
+
filterwarnings = ["default"]
|
|
66
68
|
|
|
67
69
|
[tool.ruff]
|
|
68
70
|
line-length = 88
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
|
|
7
7
|
import os
|
|
8
8
|
import re
|
|
9
|
-
import sys
|
|
10
9
|
import tempfile
|
|
11
10
|
import unittest
|
|
12
11
|
from contextlib import suppress
|
|
@@ -206,8 +205,7 @@ class TestXvfb(XvfbCleanTestCase):
|
|
|
206
205
|
unwriteable_dir = "/etc"
|
|
207
206
|
xvfb = Xvfb(tempdir=unwriteable_dir)
|
|
208
207
|
with self.assertRaisesRegex(
|
|
209
|
-
RuntimeError,
|
|
210
|
-
f"Could not access writable temp directory: {unwriteable_dir}",
|
|
208
|
+
RuntimeError, f"Could not access writable temp directory: {unwriteable_dir}"
|
|
211
209
|
):
|
|
212
210
|
xvfb.start()
|
|
213
211
|
self.assertIsNone(xvfb.proc)
|
|
@@ -216,8 +214,7 @@ class TestXvfb(XvfbCleanTestCase):
|
|
|
216
214
|
unknown_dir = "/tmp/some_unknown_path"
|
|
217
215
|
xvfb = Xvfb(tempdir=unknown_dir)
|
|
218
216
|
with self.assertRaisesRegex(
|
|
219
|
-
RuntimeError,
|
|
220
|
-
f"Could not access writable temp directory: {unknown_dir}",
|
|
217
|
+
RuntimeError, f"Could not access writable temp directory: {unknown_dir}"
|
|
221
218
|
):
|
|
222
219
|
xvfb.start()
|
|
223
220
|
self.assertIsNone(xvfb.proc)
|
|
@@ -258,8 +255,7 @@ class TestXvfb(XvfbCleanTestCase):
|
|
|
258
255
|
self.assertEqual(xvfb.new_display, display_num)
|
|
259
256
|
self.assertIsNotNone(xvfb.proc)
|
|
260
257
|
with self.assertRaisesRegex(
|
|
261
|
-
RuntimeError,
|
|
262
|
-
f"Could not lock display: {display_num}",
|
|
258
|
+
RuntimeError, f"Could not lock display: {display_num}"
|
|
263
259
|
):
|
|
264
260
|
xvfb2.start()
|
|
265
261
|
|
|
@@ -303,8 +299,7 @@ class TestXvfb(XvfbCleanTestCase):
|
|
|
303
299
|
"bar",
|
|
304
300
|
]
|
|
305
301
|
with self.assertRaisesRegex(
|
|
306
|
-
RuntimeError,
|
|
307
|
-
f"Xvfb display did not open: {expected_cmd_args}",
|
|
302
|
+
RuntimeError, f"Xvfb display did not open: {expected_cmd_args}"
|
|
308
303
|
):
|
|
309
304
|
xvfb.start()
|
|
310
305
|
self.assertIsNone(xvfb.proc)
|
|
@@ -314,8 +309,7 @@ class TestXvfb(XvfbCleanTestCase):
|
|
|
314
309
|
self.addCleanup(xvfb.stop)
|
|
315
310
|
xvfb.start()
|
|
316
311
|
with self.assertRaisesRegex(
|
|
317
|
-
RuntimeError,
|
|
318
|
-
re.escape(f"Xvfb is already running (PID: {xvfb.proc.pid})"),
|
|
312
|
+
RuntimeError, re.escape(f"Xvfb is already running (PID: {xvfb.proc.pid})")
|
|
319
313
|
):
|
|
320
314
|
xvfb.start()
|
|
321
315
|
self.assertIsNotNone(xvfb.proc)
|
|
@@ -342,21 +336,10 @@ class TestXvfb(XvfbCleanTestCase):
|
|
|
342
336
|
with patch("xvfbwrapper.randint", side_effect=side_effect) as mockrandint:
|
|
343
337
|
self.assertEqual(xvfb._get_next_unused_display(), 11)
|
|
344
338
|
self.assertEqual(mockrandint.call_count, 1)
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
# (like PyPy).
|
|
350
|
-
with self.assertWarns(ResourceWarning):
|
|
351
|
-
self.assertEqual(xvfb2._get_next_unused_display(), 22)
|
|
352
|
-
self.assertEqual(mockrandint.call_count, 3)
|
|
353
|
-
self.assertEqual(xvfb3._get_next_unused_display(), 33)
|
|
354
|
-
self.assertEqual(mockrandint.call_count, 10)
|
|
355
|
-
else:
|
|
356
|
-
self.assertEqual(xvfb2._get_next_unused_display(), 22)
|
|
357
|
-
self.assertEqual(mockrandint.call_count, 3)
|
|
358
|
-
self.assertEqual(xvfb3._get_next_unused_display(), 33)
|
|
359
|
-
self.assertEqual(mockrandint.call_count, 10)
|
|
339
|
+
self.assertEqual(xvfb2._get_next_unused_display(), 22)
|
|
340
|
+
self.assertEqual(mockrandint.call_count, 3)
|
|
341
|
+
self.assertEqual(xvfb3._get_next_unused_display(), 33)
|
|
342
|
+
self.assertEqual(mockrandint.call_count, 10)
|
|
360
343
|
|
|
361
344
|
def test_environ_keyword_isolates_environment_modification(self):
|
|
362
345
|
# Check that start and stop methods modified the environ dict if
|
|
@@ -380,10 +363,7 @@ class TestXvfb(XvfbCleanTestCase):
|
|
|
380
363
|
self.addCleanup(xvfb.stop)
|
|
381
364
|
xvfb.start()
|
|
382
365
|
proc = psutil.Process(xvfb.proc.pid)
|
|
383
|
-
self.assertEqual(
|
|
384
|
-
proc.environ().get("XVFBWRAPPER_TEST_MARKER"),
|
|
385
|
-
marker_value,
|
|
386
|
-
)
|
|
366
|
+
self.assertEqual(proc.environ().get("XVFBWRAPPER_TEST_MARKER"), marker_value)
|
|
387
367
|
|
|
388
368
|
def test_start_failure_without_initial_display_env(self):
|
|
389
369
|
# Provide a custom env *without* DISPLAY so orig_display_var == None
|
|
@@ -404,8 +384,7 @@ class TestXvfb(XvfbCleanTestCase):
|
|
|
404
384
|
with (
|
|
405
385
|
patch.object(xvfb, "_local_display_exists", return_value=False),
|
|
406
386
|
self.assertRaisesRegex(
|
|
407
|
-
RuntimeError,
|
|
408
|
-
f"Xvfb display did not open: {expected_cmd_args}",
|
|
387
|
+
RuntimeError, f"Xvfb display did not open: {expected_cmd_args}"
|
|
409
388
|
),
|
|
410
389
|
):
|
|
411
390
|
xvfb.start()
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
# Tox
|
|
2
|
-
# virtualenvs. This configuration file will run the test suite on all
|
|
3
|
-
# supported python versions. To use it, run "tox" from this directory.
|
|
1
|
+
# Tox configuration - environment and task orchestrator
|
|
4
2
|
#
|
|
5
|
-
#
|
|
6
|
-
# "tox -e <env>" (i.e.: "tox -e py314" or "tox -e lint")
|
|
3
|
+
# Run "tox" from this directory.
|
|
7
4
|
#
|
|
8
|
-
#
|
|
5
|
+
# Run a specific environment with:
|
|
6
|
+
# "tox -e <env>" (e.g. "tox -e lint")
|
|
9
7
|
|
|
10
8
|
|
|
11
9
|
[tox]
|
|
@@ -14,7 +12,7 @@ envlist =
|
|
|
14
12
|
lint
|
|
15
13
|
type
|
|
16
14
|
py310
|
|
17
|
-
|
|
15
|
+
py315
|
|
18
16
|
pypy3
|
|
19
17
|
skip_missing_interpreters = true
|
|
20
18
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xvfbwrapper
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.35
|
|
4
4
|
Summary: Manage headless displays with Xvfb (X virtual framebuffer)
|
|
5
5
|
Author: Corey Goldberg
|
|
6
6
|
Maintainer: Corey Goldberg
|
|
@@ -23,6 +23,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
23
23
|
Classifier: Programming Language :: Python :: 3.12
|
|
24
24
|
Classifier: Programming Language :: Python :: 3.13
|
|
25
25
|
Classifier: Programming Language :: Python :: 3.14
|
|
26
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
26
27
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
27
28
|
Requires-Python: >=3.10
|
|
28
29
|
Description-Content-Type: text/markdown
|
|
@@ -63,13 +64,21 @@ See the [module API documentation][api-docs] for more information.
|
|
|
63
64
|
</td>
|
|
64
65
|
</tr>
|
|
65
66
|
<tr>
|
|
66
|
-
<td>
|
|
67
|
+
<td>Tests (CI)</td>
|
|
67
68
|
<td>
|
|
68
69
|
<a href="https://github.com/cgoldberg/xvfbwrapper/actions/workflows/test.yml">
|
|
69
70
|
<img src="https://github.com/cgoldberg/xvfbwrapper/actions/workflows/test.yml/badge.svg">
|
|
70
71
|
</a>
|
|
71
72
|
</td>
|
|
72
73
|
</tr>
|
|
74
|
+
<tr>
|
|
75
|
+
<td>API Docs (CI)</td>
|
|
76
|
+
<td>
|
|
77
|
+
<a href="https://github.com/cgoldberg/xvfbwrapper/actions/workflows/docs.yml">
|
|
78
|
+
<img src="https://github.com/cgoldberg/xvfbwrapper/actions/workflows/docs.yml/badge.svg">
|
|
79
|
+
</a>
|
|
80
|
+
</td>
|
|
81
|
+
</tr>
|
|
73
82
|
<tr>
|
|
74
83
|
<td>Supported Python Versions</td>
|
|
75
84
|
<td>
|
|
@@ -217,12 +226,10 @@ xvfb.start() # Xvfb will be called with the `ttyxx -nocursor +extension RANDR`
|
|
|
217
226
|
|
|
218
227
|
#### Multithreaded execution:
|
|
219
228
|
|
|
220
|
-
To run several Xvfb displays at the same time, you can use the `environ`
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
`
|
|
224
|
-
environment, you must use the copy method of `os.environ` and not simply
|
|
225
|
-
assign a new variable to `os.environ`:
|
|
229
|
+
To run several Xvfb displays at the same time, you can use the `environ` keyword
|
|
230
|
+
when starting the `Xvfb` instances. This provides isolation between processes or
|
|
231
|
+
threads. If you wish to inherit your current environment, you must use the copy
|
|
232
|
+
method of `os.environ` and not simply assign a new variable to `os.environ`:
|
|
226
233
|
|
|
227
234
|
```python
|
|
228
235
|
import os
|
|
@@ -285,8 +292,6 @@ if __name__ == "__main__":
|
|
|
285
292
|
|
|
286
293
|
## Development
|
|
287
294
|
|
|
288
|
-
- Git: [github.com/cgoldberg/xvfbwrapper.git][github-repo]
|
|
289
|
-
|
|
290
295
|
- Create a virtual env and install required testing packages:
|
|
291
296
|
|
|
292
297
|
```
|
|
@@ -195,16 +195,17 @@ class Xvfb:
|
|
|
195
195
|
"""
|
|
196
196
|
tempfile_path = Path(self._tempdir, f".X{display}-lock")
|
|
197
197
|
try:
|
|
198
|
-
|
|
198
|
+
lock_file = tempfile_path.open("w")
|
|
199
199
|
except PermissionError:
|
|
200
200
|
return False
|
|
201
|
+
try:
|
|
202
|
+
fcntl.flock(lock_file, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
|
203
|
+
except BlockingIOError:
|
|
204
|
+
lock_file.close()
|
|
205
|
+
return False
|
|
201
206
|
else:
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
except BlockingIOError:
|
|
205
|
-
return False
|
|
206
|
-
else:
|
|
207
|
-
return True
|
|
207
|
+
self._lock_display_file = lock_file
|
|
208
|
+
return True
|
|
208
209
|
|
|
209
210
|
def _get_next_unused_display(self) -> int:
|
|
210
211
|
"""Randomly choose a display number and try to acquire a lock for it.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|