Skip to content

Commit 8a7bbc2

Browse files
jholveckBoboTiG
andauthored
feat: move to a strategy implementation design. (#494)
* Move to a strategy implementation design. See also BoboTiG/python-mss issue #486. The user will always work with a single class: mss.MSS. Differences in implementation, such as platform or capture strategy, are hidden in an internal implementation object held by the mss.MSS object. This allows us to change the implementation, with arbitrary class hierarchies, without worrying about preserving compatibility with internal class names. This deprecates the existing `mss` factory function, although it can easily be kept for as long as needed to give users time to adapt. It also deprecates the existing `mss.{platform}.MSS` types. These are exposed to the user, so somebody calling `mss.{platform}.MSS()` in 10.x can still reasonably expect to get a `mss.{platform}.MSS` object back. However, in 11.0, we can remove the type entirely, and either remove those symbols, or make them deprecated aliases for `mss.MSS`. Where possible, deprecated functionality emits a `DeprecationWarning`. However, note that these are ignored by default, unless triggered by code in `__main__`. Many of the API docs are removed, since this change removes much of the API surface. However, they are still in available for backwards-compatibility. This change adds tests for everything that was in the 10.1 docs, examples, etc, at least at a basic level: for instance, it tests that `mss.linux.MSS` still works as both a constructor and a type (for `isinstance`), and that `mss.linux.ZPIXMAP` still exists (it was listed in the 10.1 docs). The existing code, tests, and docs are changed to use `mss.MSS`. * Add CHANGELOG / CHANGES entries * Allow and test all kwargs on all platforms. The mss_impl fixture would add an implicit display= argument, regardless of platform. The code at that time would ignore it, but we should be (and in the previous commit, were) more strict. Change mss_impl to only use display= if appropriate, so we can be more strict in the future. In 10.1, these were allowed at all times, and ignored if the platform didn't use them. Emulate this behavior in mss.MSS (and mss.mss), with DeprecationWarnings, and test. * Don't explicitly pass display in one of the tests. I'm pretty sure it's unnecessary there. Not sure why it was being done. * Comment fixes * List the keyword args for mss.MSS explicitly, instead of using **kwargs. This lets IDEs and code checkers know what is acceptable. This lets them autocomplete, and identify incorrect options in user code. * Move the shm_fallback_reason to a more general performance_status property. * Warn and ignore for --with-cursor in command line on non-Linux. * Put the --with-cursor warning on stderr, not stdout * Allow system-specific kwargs on multiple systems Co-authored-by: Mickaël Schoentgen <contact@tiger-222.fr> * Restore a TODO that was accidentally removed earlier * Formatting fix --------- Co-authored-by: Mickaël Schoentgen <contact@tiger-222.fr>
1 parent 4cf1a06 commit 8a7bbc2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+983
-554
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ See Git commit messages for full history.
44

55
## v10.2.0.dev0
66
(2026-xx-xx)
7+
- Introduce a new API, mss.MSS, that we can keep stable as we continue to improve MSS. The previous documented API is deprecated, but still available, in 10.2. Some parts of the existing API (such as certain type names and internal variables) may be removed in 11.0, but the most important parts will remain available for as long as can be reasonably supported. (#486, #494)
78
- Add Versioning chapter to docs (#496)
89
- Add `is_primary`, `name`, and `unique_id` keys to Monitor dicts for primary monitor detection, device names, and stable per-monitor identification (#153)
910
- Add `primary_monitor` property to MSS base class for easy access to the primary monitor (#153)

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## 10.2.0 (2026-xx-xx)
44

55
### base.py
6+
- (This affected almost every file in some respect, but base.py was the most affected.) Introduced a new API, mss.MSS. This class can be used instead of the previous various MSSBase subclasses, so that the user can work with a consistent class regardless of implementation details. The methods implemented by MSSBase subclasses were renamed, and moved to MSSImplementation subclasses. The mss.MSS class now holds an MSSImplementation instance as an instance variable. (#486, #494)
67
- Added `primary_monitor` property to return the primary monitor (or first monitor as fallback).
78

89
### models.py

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111
> [![Patreon](https://img.shields.io/badge/Patreon-F96854?style=for-the-badge&logo=patreon&logoColor=white)](https://www.patreon.com/mschoentgen)
1212
1313
```python
14-
from mss import mss
14+
from mss import MSS
1515

1616
# The simplest use, save a screenshot of the 1st monitor
17-
with mss() as sct:
17+
with MSS() as sct:
1818
sct.shot()
1919
```
2020

demos/cat-detector.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ def main() -> None:
240240
model_labels = weights.meta["categories"]
241241
cat_label = model_labels.index("cat")
242242

243-
with mss.mss() as sct:
243+
with mss.MSS() as sct:
244244
monitor = sct.monitors[1]
245245

246246
# Compute the minimum size, in square pixels, that we'll consider reliable.

demos/tinytv-stream-simple.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def main() -> None:
7979
# Note that we use the same MSS object the whole time. We don't try to keep creating a new MSS object each
8080
# time we take a new screenshot. That's because the MSS object has a lot of stuff that it sets up and
8181
# remembers, and creating a new MSS object each time would mean that it has to repeat that setup constantly.
82-
with mss.mss() as sct:
82+
with mss.MSS() as sct:
8383
# It's time to get the monitor that we're going to capture. In this demo, we just capture the first
8484
# monitor. (We could also use monitors[0] for all the monitors combined.)
8585
monitor = sct.monitors[1]

demos/tinytv-stream.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ def capture_image(
342342
'width', 'height'.
343343
:yields: PIL Image objects from the captured monitor.
344344
"""
345-
with mss.mss() as sct:
345+
with mss.MSS() as sct:
346346
rect = capture_area if capture_area is not None else sct.monitors[monitor]
347347
LOGGER.debug("Capture area: %i,%i, %ix%i", rect["left"], rect["top"], rect["width"], rect["height"])
348348

demos/video-capture-simple.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def main() -> None:
6868
# If we don't enable PyAV's own logging, a lot of important error messages from libav won't be shown.
6969
av.logging.set_level(av.logging.VERBOSE)
7070

71-
with mss.mss() as sct:
71+
with mss.MSS() as sct:
7272
monitor = sct.monitors[1]
7373

7474
# Because of how H.264 video stores color information, libx264 requires the video size to be a multiple of

demos/video-capture.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@
164164

165165
def video_capture(
166166
fps: int,
167-
sct: mss.base.MSSBase,
167+
sct: mss.MSS,
168168
monitor: mss.models.Monitor,
169169
shutdown_requested: Event,
170170
) -> Generator[tuple[mss.screenshot.ScreenShot, float], None, None]:
@@ -434,7 +434,7 @@ def main() -> None:
434434
duration_secs = args.duration_secs
435435
region_crop_to_multiple_of_two = args.region_crop_to_multiple_of_two
436436

437-
with mss.mss() as sct:
437+
with mss.MSS() as sct:
438438
if args.region:
439439
left, top, right, bottom = args.region
440440
monitor = {

docs/source/api.rst

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -7,67 +7,7 @@ Core Package
77

88
.. automodule:: mss
99

10-
Screenshot Objects
11-
==================
12-
13-
.. automodule:: mss.screenshot
14-
15-
Base Classes
16-
============
17-
18-
.. automodule:: mss.base
19-
20-
Tools
21-
=====
22-
23-
.. automodule:: mss.tools
24-
25-
Exceptions
26-
==========
27-
28-
.. automodule:: mss.exception
29-
3010
Data Models
3111
===========
3212

3313
.. automodule:: mss.models
34-
35-
Platform Backends
36-
=================
37-
38-
macOS Backend
39-
-------------
40-
41-
.. automodule:: mss.darwin
42-
43-
GNU/Linux Dispatcher
44-
--------------------
45-
46-
.. automodule:: mss.linux
47-
48-
GNU/Linux Xlib Backend
49-
----------------------
50-
51-
.. automodule:: mss.linux.xlib
52-
53-
GNU/Linux XCB Base
54-
------------------
55-
56-
.. automodule:: mss.linux.base
57-
58-
GNU/Linux XCB XGetImage Backend
59-
-------------------------------
60-
61-
.. automodule:: mss.linux.xgetimage
62-
63-
GNU/Linux XCB XShmGetImage Backend
64-
----------------------------------
65-
66-
.. automodule:: mss.linux.xshmgetimage
67-
68-
Windows Backend
69-
---------------
70-
71-
.. automodule:: mss.windows
72-
73-

docs/source/conf.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@
99
import ctypes
1010

1111
# Monkey-patch PROT_READ into mmap if missing (Windows), so that we can
12-
# import mss.linux.xshmgetimage while building the documentation.
12+
# import the Linux shared-memory backend implementation while building the
13+
# documentation.
1314
import mmap
1415

1516
if not hasattr(mmap, "PROT_READ"):
16-
mmap.PROT_READ = 1 # type:ignore[attr-defined]
17+
mmap.PROT_READ = 1
1718

1819
import mss
1920

0 commit comments

Comments
 (0)