From 085bdb7defbe223e6c9f38c0410627d848a7d5d0 Mon Sep 17 00:00:00 2001 From: Avasam Date: Wed, 24 Jun 2026 14:27:44 -0400 Subject: [PATCH 1/3] Manual Ruff fixes --- docs/source/conf.py | 3 +- ruff.toml | 13 ++---- src/pymonctl/__init__.py | 17 ++++---- src/pymonctl/_main.py | 58 ++++++++++++++++--------- src/pymonctl/_pymonctl_linux.py | 41 +++++++++--------- src/pymonctl/_pymonctl_macos.py | 45 ++++++++++---------- src/pymonctl/_pymonctl_win.py | 75 +++++++++++++++++++-------------- src/pymonctl/_structs.py | 48 ++++++++++----------- tests/test_pymonctl.py | 2 +- typings/Quartz/__init__.pyi | 2 +- 10 files changed, 165 insertions(+), 139 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 3f6ca99..df82bd1 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -8,6 +8,7 @@ import re import time +from urllib.request import urlretrieve project = 'PyMonCtl' year = time.strftime("%Y") @@ -42,8 +43,6 @@ # -- Copy the modules documentation ------------------------------------------ # https://stackoverflow.com/questions/66495200/is-it-possible-to-include-external-rst-files-in-my-documentation -from urllib.request import urlretrieve - urlretrieve( "https://raw.githubusercontent.com/kalmat/pymonctl/master/README.md", "index.md" diff --git a/ruff.toml b/ruff.toml index d32d023..3dc79f7 100644 --- a/ruff.toml +++ b/ruff.toml @@ -43,19 +43,12 @@ ignore = [ # Anyway Python 3.11 introduced "zero cost" exception handling "PERF203", # try-except-in-loop, + # TODO: Add and configure isort (I) first + "RUF022", + # TODO: Consider later "UP031", # printf-string-formatting "RUF059", # unused-unpacked-variable - - # TODO: Not autofixable, address in a separate PR ! - "E402", - "E722", - "F401", - "PERF401", - "PYI063", - "RUF003", - "RUF012", - "RUF022", ] # F401 would remove imports not marked as explicit re-exports, which may break API boundaries extend-unsafe-fixes = ["F401"] diff --git a/src/pymonctl/__init__.py b/src/pymonctl/__init__.py index c8592b9..a017d27 100644 --- a/src/pymonctl/__init__.py +++ b/src/pymonctl/__init__.py @@ -1,6 +1,15 @@ #!/usr/bin/python from importlib.metadata import version as _importlib_version +from ._main import (getAllMonitors, getAllMonitorsDict, getMonitorsCount, getPrimary, + findMonitorsAtPoint, findMonitorsAtPointInfo, findMonitorWithName, findMonitorWithNameInfo, + saveSetup, restoreSetup, arrangeMonitors, getMousePos, Monitor, + enableUpdateInfo, disableUpdateInfo, isUpdateInfoEnabled, isWatchdogEnabled, updateWatchdogInterval, + plugListenerRegister, plugListenerUnregister, isPlugListenerRegistered, + changeListenerRegister, changeListenerUnregister, isChangeListenerRegistered, + DisplayMode, ScreenValue, Size, Point, Box, Rect, Position, Orientation + ) + __all__ = [ "getAllMonitors", "getAllMonitorsDict", "getMonitorsCount", "getPrimary", "findMonitorsAtPoint", "findMonitorsAtPointInfo", "findMonitorWithName", "findMonitorWithNameInfo", @@ -19,11 +28,3 @@ def version(numberOnly: bool = True) -> str: return ("" if numberOnly else "PyMonCtl-")+__version__ -from ._main import (getAllMonitors, getAllMonitorsDict, getMonitorsCount, getPrimary, - findMonitorsAtPoint, findMonitorsAtPointInfo, findMonitorWithName, findMonitorWithNameInfo, - saveSetup, restoreSetup, arrangeMonitors, getMousePos, Monitor, - enableUpdateInfo, disableUpdateInfo, isUpdateInfoEnabled, isWatchdogEnabled, updateWatchdogInterval, - plugListenerRegister, plugListenerUnregister, isPlugListenerRegistered, - changeListenerRegister, changeListenerUnregister, isChangeListenerRegistered, - DisplayMode, ScreenValue, Size, Point, Box, Rect, Position, Orientation - ) diff --git a/src/pymonctl/_main.py b/src/pymonctl/_main.py index d2c9a17..a7e2fc5 100644 --- a/src/pymonctl/_main.py +++ b/src/pymonctl/_main.py @@ -212,11 +212,7 @@ def saveSetup() -> list[tuple[Monitor, ScreenValue]]: :return: list of tuples containing all necessary info to restore saved setup as required by restoreSetup() """ - result: list[tuple[Monitor, ScreenValue]] = [] - monDict: dict[str, ScreenValue] = getAllMonitorsDict() - for monName in monDict.keys(): - result.append((Monitor(monDict[monName]["id"]), monDict[monName])) - return result + return [(Monitor(screenValue["id"]), screenValue) for screenValue in getAllMonitorsDict().values()] def restoreSetup(setup: list[tuple[Monitor, ScreenValue]]): @@ -234,7 +230,7 @@ def restoreSetup(setup: list[tuple[Monitor, ScreenValue]]): if not monitor.isAttached: try: monitor.attach() - except: + except Exception: continue if monitor.isAttached: if monitor.isSuspended or not monitor.isOn: @@ -744,7 +740,7 @@ def getMonitors(self) -> list[Monitor]: for screen in self._screens.keys(): try: monitors.append(Monitor(self._screens[screen]["id"])) - except: + except Exception: pass return monitors @@ -827,7 +823,7 @@ def plugListenerUnregister(monitorCountChanged: Callable[[list[str], dict[str, S try: objIndex = _plugListeners.index(monitorCountChanged) _plugListeners.pop(objIndex) - except: + except Exception: pass global _changeListeners global _updateRequested @@ -867,7 +863,7 @@ def changeListenerUnregister(monitorPropsChanged: Callable[[list[str], dict[str, try: objIndex = _changeListeners.index(monitorPropsChanged) _changeListeners.pop(objIndex) - except: + except Exception: pass global _plugListeners global _updateRequested @@ -1003,17 +999,41 @@ def _getRelativePosition(monitor, relativeTo) -> tuple[int, int]: if sys.platform == "darwin": - from ._pymonctl_macos import (_getAllMonitors, _getAllMonitorsDict, _getMonitorsCount, _getPrimary, - _findMonitor, _arrangeMonitors, _getMousePos as getMousePos, MacOSMonitor as Monitor - ) + from ._pymonctl_macos import MacOSMonitor as Monitor + from ._pymonctl_macos import ( + _arrangeMonitors, + _findMonitor, + _getAllMonitors, + _getAllMonitorsDict, + _getMonitorsCount, + _getMousePos, + _getPrimary, + ) elif sys.platform == "win32": - from ._pymonctl_win import (_getAllMonitors, _getAllMonitorsDict, _getMonitorsCount, _getPrimary, - _findMonitor, _arrangeMonitors, _getMousePos as getMousePos, Win32Monitor as Monitor - ) + from ._pymonctl_win import Win32Monitor as Monitor + from ._pymonctl_win import ( + _arrangeMonitors, + _findMonitor, + _getAllMonitors, + _getAllMonitorsDict, + _getMonitorsCount, + _getMousePos, + _getPrimary, + ) elif sys.platform == "linux": - from ._pymonctl_linux import (_getAllMonitors, _getAllMonitorsDict, _getAllMonitorsDictThread, _getMonitorsData, - _getMonitorsCount, _getPrimary, _findMonitor, _arrangeMonitors, _getMousePos as getMousePos, - LinuxMonitor as Monitor - ) + from ._pymonctl_linux import LinuxMonitor as Monitor + from ._pymonctl_linux import ( + _arrangeMonitors, + _findMonitor, + _getAllMonitors, + _getAllMonitorsDict, + _getAllMonitorsDictThread, + _getMonitorsCount, + _getMonitorsData, + _getMousePos, + _getPrimary, + ) else: raise NotImplementedError('PyMonCtl currently does not support this platform. If you think you can help, please contribute! https://github.com/Kalmat/PyMonCtl') + +getMousePos = _getMousePos diff --git a/src/pymonctl/_pymonctl_linux.py b/src/pymonctl/_pymonctl_linux.py index f756d34..8e7d430 100644 --- a/src/pymonctl/_pymonctl_linux.py +++ b/src/pymonctl/_pymonctl_linux.py @@ -3,7 +3,8 @@ import sys -assert sys.platform == "linux" +if sys.platform != "linux": + raise OSError(f"Cannot import {__name__} on {sys.platform}") import math import os @@ -107,11 +108,11 @@ def _getMonitorsCount() -> int: def _findMonitor(x: int, y: int) -> list[LinuxMonitor]: - monitors = [] - for monitor in _XgetMonitors(): - if _pointInBox(x, y, monitor.x, monitor.y, monitor.width_in_pixels, monitor.height_in_pixels): - monitors.append(LinuxMonitor(monitor.crtcs[0])) - return monitors + return [ + LinuxMonitor(monitor.crtcs[0]) + for monitor in _XgetMonitors() + if _pointInBox(x, y, monitor.x, monitor.y, monitor.width_in_pixels, monitor.height_in_pixels) + ] def _getPrimary() -> LinuxMonitor: @@ -270,7 +271,7 @@ def setPosition(self, relativePos: int | Position | Point | tuple[int, int], rel try: index = monKeys.index(self.name) monKeys.pop(index) - except: + except Exception: return arrangement[self.name] = {"relativePos": relativePos, "relativeTo": None} xOffset = monitor.width_in_pixels @@ -429,7 +430,7 @@ def brightness(self) -> int | None: if ret: try: value = int(float(ret) * 100) - except: + except Exception: pass return value @@ -449,7 +450,7 @@ def contrast(self) -> int | None: try: r, g, b = ret.split(":") value = int((((1 / (float(r) or 1)) + (1 / (float(g) or 1)) + (1 / (float(b) or 1))) / 3) * 100) - except: + except Exception: pass return value @@ -609,7 +610,7 @@ def detach(self, permanent: bool = False): try: # randr.set_crtc_config() fails in Cinnamon randr.set_crtc_config(self.display, crtc, Xlib.X.CurrentTime, crtcInfo.x, crtcInfo.y, 0, crtcInfo.rotation, []) - except: + except Exception: cmd = "xrandr --output %s --mode %sx%s" % (self.name, 0, 0) _, _ = _runProc(cmd) @@ -641,7 +642,7 @@ def _GNOME_isScalingGlobal() -> bool | None: return bool("scale-monitor-framebuffer" not in proc.stdout) else: return bool("x11-randr-fractional-scaling" not in proc.stdout) - except: + except Exception: pass return None @@ -657,7 +658,7 @@ def _GNOME_setGlobalScaling(setGlobal=True): proc = subprocess.run("grep -sl mutter /proc/*/maps", text=True, shell=True, capture_output=True) if "/maps" in proc.stdout: cmd = '''gsettings set org.gnome.mutter experimental-features "['scale-monitor-framebuffer']"''' - except: + except Exception: pass else: cmd = '''gsettings set org.gnome.mutter experimental-features "['x11-randr-fractional-scaling']"''' @@ -671,7 +672,7 @@ def _GNOME_getScalingFactor() -> int | None: if "WindowScalingFactor" in ret: try: return int(ret.split("WindowScalingFactor': <")[1][0]) - except: + except Exception: pass return None @@ -697,7 +698,7 @@ def _GNOME_getScalingFactor() -> int | None: # # try: # import dbus -# except: +# except Exception: # return {}, {}, {} # # namespace = "org.gnome.Mutter.DisplayConfig" @@ -743,7 +744,7 @@ def _GNOME_getScalingFactor() -> int | None: # # try: # import dbus -# except: +# except Exception: # return # # namespace = "org.gnome.Mutter.DisplayConfig" @@ -795,7 +796,7 @@ def _scale(name: str) -> tuple[float, float] | None: h = int(b) r = float(lines[1].replace("+", "").replace("*", "")) value = DisplayMode(w, h, r) - except: + except Exception: pass if value: monitors = _XgetMonitors(name) @@ -818,7 +819,7 @@ def _runProc(cmd: str): # Some commands will take some time to be executed and return required value proc = subprocess.run(cmd, text=True, shell=True, capture_output=True) #, timeout=3) return proc.returncode, proc.stdout - except: + except Exception: pass return -1, "" @@ -846,7 +847,7 @@ def _getMonitorsData(handle: int | None = None) -> ( display, screen, root = rootData try: mons = randr.get_monitors(root).monitors - except: + except Exception: # In Cinnamon randr extension has no get_monitors() method (?!?!?!?) mons = _RgetAllMonitors() stopSearching = True @@ -886,7 +887,7 @@ def _XgetAllMonitors(name: str = ""): display, screen, root = rootData try: mons = randr.get_monitors(root).monitors - except: + except Exception: # In Cinnamon randr extension has no get_monitors() method (?!?!?!?) mons = _RgetAllMonitors() stopSearching = True @@ -941,7 +942,7 @@ def _RgetMonitorsInfo(activeOnly: bool = True): y = parts[2] w, h = parts[0].split("x") monInfo.append((name, primary, int(x), int(y), int(w), int(h))) - except: + except Exception: pass return monInfo diff --git a/src/pymonctl/_pymonctl_macos.py b/src/pymonctl/_pymonctl_macos.py index be95bec..2d75144 100644 --- a/src/pymonctl/_pymonctl_macos.py +++ b/src/pymonctl/_pymonctl_macos.py @@ -6,7 +6,9 @@ import ctypes import sys -assert sys.platform == "darwin" + +if sys.platform != "darwin": + raise OSError(f"Cannot import {__name__} on {sys.platform}") import subprocess import threading @@ -22,11 +24,8 @@ def _getAllMonitors() -> list[MacOSMonitor]: - monitors = [] v, ids, cnt = CG.CGGetOnlineDisplayList(10, None, None) # --> How to get display name from this? - for displayId in ids: - monitors.append(MacOSMonitor(displayId)) - return monitors + return [MacOSMonitor(displayId) for displayId in ids] def _getAllMonitorsDict() -> dict[str, ScreenValue]: @@ -36,7 +35,7 @@ def _getAllMonitorsDict() -> dict[str, ScreenValue]: try: name = screen.localizedName() - except: + except Exception: # In older macOS, screen doesn't have localizedName() method name = "Display" + "_" + str(displayId) is_primary = Quartz.CGDisplayIsMain(displayId) == 1 @@ -244,7 +243,7 @@ def setPosition(self, relativePos: int | Position | Point | tuple[int, int], rel try: index = monKeys.index(self.name) monKeys.pop(index) - except: + except Exception: return arrangement[self.name] = {"relativePos": Position.PRIMARY, "relativeTo": None} xOffset = self.screen.frame().size.width @@ -377,7 +376,7 @@ def setOrientation(self, orientation: int | Orientation | None): try: ret = self._iokit.IOServiceRequestProbe(self._ioservice, options) - except: + except Exception: ret = 1 if ret != 0: self._useIOOrientation = False @@ -406,7 +405,7 @@ def brightness(self) -> int | None: value = ctypes.c_float() try: ret = self._ds.DisplayServicesGetBrightness(self.handle, ctypes.byref(value)) - except: + except Exception: ret = 1 if ret == 0: res = value.value @@ -421,7 +420,7 @@ def brightness(self) -> int | None: value = ctypes.c_double() try: ret = self._cd.CoreDisplay_Display_GetUserBrightness(self.handle, ctypes.byref(value)) - except: + except Exception: ret = 1 if ret == 0: res = value.value @@ -437,7 +436,7 @@ def brightness(self) -> int | None: value = ctypes.c_float() try: ret = self._iokit.IODisplayGetFloatParameter(self._ioservice, 0, kDisplayBrightnessKey, ctypes.byref(value)) - except: + except Exception: ret = 1 if ret == 0: res = value.value @@ -463,7 +462,7 @@ def setBrightness(self, brightness: int | None): ret = 0 if self._ds.DisplayServicesCanChangeBrightness(self.handle): ret = self._ds.DisplayServicesSetBrightness(self.handle, value) - except: + except Exception: ret = 1 if ret != 0: self._useDS = False @@ -476,7 +475,7 @@ def setBrightness(self, brightness: int | None): value = ctypes.c_double(brightness / 100) try: ret = self._cd.CoreDisplay_Display_SetUserBrightness(self.handle, value) - except: + except Exception: ret = 1 if ret != 0: self._useCD = False @@ -490,7 +489,7 @@ def setBrightness(self, brightness: int | None): value = ctypes.c_float(brightness / 100) try: ret = self._iokit.IODisplaySetFloatParameter(self._ioservice, 0, kDisplayBrightnessKey, value) - except: + except Exception: ret = 1 if ret != 0: self._useIOBrightness = False @@ -506,7 +505,7 @@ def contrast(self) -> int | None: CG.CGGetDisplayTransferByFormula(self.handle, None, None, None, None, None, None, None, None, None)) if ret == 0: contrast = int((float(redGamma) + float(greenGamma) + float(blueGamma)) / 3 * 100) - except: + except Exception: pass return contrast @@ -606,7 +605,7 @@ def turnOn(self): cmd = "caffeinate -u -t 2" try: _ = subprocess.run(cmd, text=True, shell=True, capture_output=True, timeout=1) - except: + except Exception: pass def turnOff(self): @@ -617,11 +616,11 @@ def isOn(self) -> bool | None: return bool(CG.CGDisplayIsActive(self.handle) == 1) def suspend(self): - # Also injecting: Control–Shift–Media_Eject + # Also injecting: Control-Shift-Media_Eject cmd = "pmset displaysleepnow" try: _ = subprocess.run(cmd, text=True, shell=True, capture_output=True, timeout=1) - except: + except Exception: pass @property @@ -649,7 +648,7 @@ def _getName(displayId: int, screen: AppKit.NSScreen | None = None): break try: scrName = cast("AppKit.NSScreen", screen).localizedName() + "_" + str(displayId) - except: + except Exception: # In older macOS, screen doesn't have localizedName() method scrName = "Display" + "_" + str(displayId) return scrName @@ -709,7 +708,7 @@ def _loadDisplayServices(): # Display Services Framework can be used in modern systems. It takes A LOT to load try: ds: ctypes.CDLL = ctypes.cdll.LoadLibrary('/System/Library/PrivateFrameworks/DisplayServices.framework/DisplayServices') - except: + except Exception: return None return ds @@ -723,7 +722,7 @@ def _loadCoreDisplay(): cd: ctypes.CDLL = ctypes.cdll.LoadLibrary(lib) cd.CoreDisplay_Display_SetUserBrightness.argtypes = [ctypes.c_int, ctypes.c_double] cd.CoreDisplay_Display_GetUserBrightness.argtypes = [ctypes.c_int, ctypes.c_void_p] - except: + except Exception: return None return cd @@ -760,7 +759,7 @@ class _CFString(ctypes.Structure): try: service: int = Quartz.CGDisplayIOServicePort(displayID) - except: + except Exception: service = 0 # Check if this works in an actual macOS (preferably in several versions) @@ -798,7 +797,7 @@ class _CFString(ctypes.Structure): if service: return iokit, CF, service - except: + except Exception: pass return None, None, None diff --git a/src/pymonctl/_pymonctl_win.py b/src/pymonctl/_pymonctl_win.py index 38e26ec..4537373 100644 --- a/src/pymonctl/_pymonctl_win.py +++ b/src/pymonctl/_pymonctl_win.py @@ -2,7 +2,9 @@ from __future__ import annotations import sys -assert sys.platform == "win32" + +if sys.platform != "win32": + raise OSError(f"Cannot import {__name__} on {sys.platform}") import gc import platform @@ -44,7 +46,7 @@ def _getAllMonitors() -> list[Win32Monitor]: hMon = mon[0].handle try: monitors.append(Win32Monitor(hMon)) - except: + except Exception: pass return monitors @@ -68,10 +70,12 @@ def _getAllMonitorsDict() -> dict[str, ScreenValue]: ctypes.windll.shcore.GetDpiForMonitor(hMon, 0, ctypes.byref(dpiX), ctypes.byref(dpiY)) try: settings = win32api.EnumDisplaySettings(monName, win32con.ENUM_CURRENT_SETTINGS) - except: + except Exception: try: - settings = win32api.EnumDisplaySettings(monName, win32con.ENUM_REGISTRY_SETTINGS) - except: + settings = win32api.EnumDisplaySettings( + monName, win32con.ENUM_REGISTRY_SETTINGS + ) + except Exception: continue rot = Orientation(settings.DisplayOrientation) @@ -104,7 +108,7 @@ def _findMonitor(x: int, y: int) -> list[Win32Monitor]: if hMon and hasattr(hMon, "handle"): try: return [Win32Monitor(hMon.handle)] - except: + except Exception: pass return [] @@ -218,7 +222,7 @@ def __init__(self, handle: int | None = None) -> None: self._isWindows11 = False try: self._isWindows11 = bool(int(platform.win32_ver()[1].rsplit(".", 1)[1]) >= 22000) - except: + except Exception: self._isWindows11 = False @property @@ -261,7 +265,7 @@ def setPosition(self, relativePos: int | Position | Point | tuple[int, int], rel try: index = monKeys.index(self.name) monKeys.pop(index) - except: + except Exception: return arrangement[self.name] = {"relativePos": Position.PRIMARY, "relativeTo": None} x, y, r, b = monitors[self.name]["monitor"]["Monitor"] @@ -392,7 +396,7 @@ def setScale(self, scale: tuple[float, float] | None, applyGlobally: bool = True else: try: targetScale = _DPI_VALUES.index(scaleValue) - except: + except Exception: for i, value in enumerate(_DPI_VALUES): targetScale = i if value > scaleValue: @@ -419,10 +423,12 @@ def orientation(self) -> int | Orientation | None: settings = None try: settings = win32api.EnumDisplaySettings(self.name, win32con.ENUM_CURRENT_SETTINGS) - except: + except Exception: try: - settings = win32api.EnumDisplaySettings(self.name, win32con.ENUM_REGISTRY_SETTINGS) - except: + settings = win32api.EnumDisplaySettings( + self.name, win32con.ENUM_REGISTRY_SETTINGS + ) + except Exception: pass if settings: return Orientation(settings.DisplayOrientation) @@ -433,10 +439,12 @@ def setOrientation(self, orientation: int | Orientation | None): # In most cases an empty struct is required, but in this case we need to retrieve Display Settings first try: settings = win32api.EnumDisplaySettings(self.name, win32con.ENUM_CURRENT_SETTINGS) - except: + except Exception: try: - settings = win32api.EnumDisplaySettings(self.name, win32con.ENUM_REGISTRY_SETTINGS) - except: + settings = win32api.EnumDisplaySettings( + self.name, win32con.ENUM_REGISTRY_SETTINGS + ) + except Exception: return if (settings.DisplayOrientation + orientation) % 2 == 1: settings.PelsWidth, settings.PelsHeight = settings.PelsHeight, settings.PelsWidth @@ -451,10 +459,12 @@ def frequency(self) -> float | None: settings = None try: settings = win32api.EnumDisplaySettings(self.name, win32con.ENUM_CURRENT_SETTINGS) - except: + except Exception: try: - settings = win32api.EnumDisplaySettings(self.name, win32con.ENUM_REGISTRY_SETTINGS) - except: + settings = win32api.EnumDisplaySettings( + self.name, win32con.ENUM_REGISTRY_SETTINGS + ) + except Exception: pass if settings: return settings.DisplayFrequency @@ -466,10 +476,12 @@ def colordepth(self) -> int | None: settings = None try: settings = win32api.EnumDisplaySettings(self.name, win32con.ENUM_CURRENT_SETTINGS) - except: + except Exception: try: - settings = win32api.EnumDisplaySettings(self.name, win32con.ENUM_REGISTRY_SETTINGS) - except: + settings = win32api.EnumDisplaySettings( + self.name, win32con.ENUM_REGISTRY_SETTINGS + ) + except Exception: pass if settings: return settings.BitsPerPel @@ -540,10 +552,12 @@ def mode(self) -> DisplayMode | None: settings = None try: settings = win32api.EnumDisplaySettings(self.name, win32con.ENUM_CURRENT_SETTINGS) - except: + except Exception: try: - settings = win32api.EnumDisplaySettings(self.name, win32con.ENUM_REGISTRY_SETTINGS) - except: + settings = win32api.EnumDisplaySettings( + self.name, win32con.ENUM_REGISTRY_SETTINGS + ) + except Exception: pass if settings: return DisplayMode(settings.PelsWidth, settings.PelsHeight, settings.DisplayFrequency) @@ -578,7 +592,7 @@ def allModes(self) -> list[DisplayMode]: try: winSettings = win32api.EnumDisplaySettings(self.name, i) modes.append(DisplayMode(winSettings.PelsWidth, winSettings.PelsHeight, winSettings.DisplayFrequency)) - except: + except Exception: break i += 1 return modes @@ -795,7 +809,7 @@ def _win32getAllMonitorsDict(): try: monitorInfo = win32api.GetMonitorInfo(hMon) monitors[monitorInfo["Device"]] = {"hMon": hMon, "monitor": monitorInfo} - except: + except Exception: pass return monitors @@ -818,7 +832,7 @@ def _findNewHandles(): if instance.name == monInfo.get("Device", ""): instance.handle = hMon break - except: + except Exception: stopSearching = False break if stopSearching: @@ -830,7 +844,7 @@ def _getMonitorInfo(handle: int): try: monitorInfo = win32api.GetMonitorInfo(handle) return monitorInfo - except: + except Exception: pass return None @@ -849,8 +863,7 @@ class _PHYSICAL_MONITOR(ctypes.Structure): physical_array = (_PHYSICAL_MONITOR * count.value)() ret = ctypes.windll.dxva2.GetPhysicalMonitorsFromHMONITOR(hMon, count.value, physical_array) if ret: - for physical in physical_array: - handles.append(physical.handle) + handles.extend([physical.handle for physical in physical_array]) return handles @@ -858,7 +871,7 @@ def _win32destroyPhysicalMonitors(hDevices): for hDevice in hDevices: try: ctypes.windll.dxva2.DestroyPhysicalMonitor(hDevice) - except: + except Exception: pass diff --git a/src/pymonctl/_structs.py b/src/pymonctl/_structs.py index 39d7a93..493506b 100644 --- a/src/pymonctl/_structs.py +++ b/src/pymonctl/_structs.py @@ -3,7 +3,7 @@ import sys from enum import IntEnum -from typing import NamedTuple +from typing import ClassVar, NamedTuple from typing_extensions import TypedDict @@ -112,14 +112,14 @@ class Orientation(IntEnum): # ==================================== PathsInfo class _DUMMYSTRUCTNAME(ctypes.Structure): - _fields_ = [ + _fields_: ClassVar = [ ('cloneGroupId', ctypes.c_uint32), ('sourceModeInfoIdx', ctypes.c_uint32) ] class _DUMMYUNIONNAME(ctypes.Union): - _fields_ = [ + _fields_: ClassVar = [ ('modeInfoIdx', ctypes.c_uint32), ('dummyStructName', _DUMMYSTRUCTNAME) ] @@ -127,14 +127,14 @@ class _DUMMYUNIONNAME(ctypes.Union): class _LUID(ctypes.Structure): - _fields_ = [ + _fields_: ClassVar = [ ('lowPart', ctypes.wintypes.DWORD), ('highPart', ctypes.wintypes.LONG) ] class _DISPLAYCONFIG_PATH_SOURCE_INFO(ctypes.Structure): - _fields_ = [ + _fields_: ClassVar = [ ('adapterId', _LUID), ('id', ctypes.c_uint32), ('dummyUnionName', _DUMMYUNIONNAME), @@ -143,14 +143,14 @@ class _DISPLAYCONFIG_PATH_SOURCE_INFO(ctypes.Structure): class _DISPLAYCONFIG_RATIONAL(ctypes.Structure): - _fields_ = [ + _fields_: ClassVar = [ ('numerator', ctypes.c_uint32), ('denominator', ctypes.c_uint32) ] class _DISPLAYCONFIG_PATH_TARGET_INFO(ctypes.Structure): - _fields_ = [ + _fields_: ClassVar = [ ('adapterId', _LUID), ('id', ctypes.c_uint32), ('dummyUnionName', _DUMMYUNIONNAME), @@ -165,7 +165,7 @@ class _DISPLAYCONFIG_PATH_TARGET_INFO(ctypes.Structure): class _DISPLAYCONFIG_PATH_INFO(ctypes.Structure): - _fields_ = [ + _fields_: ClassVar = [ ('sourceInfo', _DISPLAYCONFIG_PATH_SOURCE_INFO), ('targetInfo', _DISPLAYCONFIG_PATH_TARGET_INFO), ('flags', ctypes.c_uint32) @@ -175,14 +175,14 @@ class _DISPLAYCONFIG_PATH_INFO(ctypes.Structure): # ==================================== ModesInfo class _DISPLAYCONFIG_2DREGION(ctypes.Structure): - _fields_ = [ + _fields_: ClassVar = [ ('cx', ctypes.c_uint32), ('cy', ctypes.c_uint32) ] class _ADDITIONAL_SIGNAL_INFO(ctypes.Structure): - _fields_ = [ + _fields_: ClassVar = [ ('videoStandard', ctypes.c_uint32), ('vSyncFreqDivider', ctypes.c_uint32), ('reserved', ctypes.c_uint32) @@ -190,14 +190,14 @@ class _ADDITIONAL_SIGNAL_INFO(ctypes.Structure): class _DUMMYUNIONNAME_MODE_SIGNAL(ctypes.Union): - _fields_ = [ + _fields_: ClassVar = [ ('additionalSignalInfo', _ADDITIONAL_SIGNAL_INFO), ('videoStandard', ctypes.c_uint32) ] class _DISPLAYCONFIG_VIDEO_SIGNAL_INFO(ctypes.Structure): - _fields_ = [ + _fields_: ClassVar = [ ('pixelRate', ctypes.c_uint64), ('hSyncFreq', _DISPLAYCONFIG_RATIONAL), ('vSyncFreq', _DISPLAYCONFIG_RATIONAL), @@ -209,20 +209,20 @@ class _DISPLAYCONFIG_VIDEO_SIGNAL_INFO(ctypes.Structure): class _DISPLAYCONFIG_TARGET_MODE(ctypes.Structure): - _fields_ = [ + _fields_: ClassVar = [ ('targetVideoSignalInfo', _DISPLAYCONFIG_VIDEO_SIGNAL_INFO) ] class _POINTL(ctypes.Structure): - _fields_ = [ + _fields_: ClassVar = [ ('x', ctypes.wintypes.LONG), ('y', ctypes.wintypes.LONG) ] class _DISPLAYCONFIG_SOURCE_MODE(ctypes.Structure): - _fields_ = [ + _fields_: ClassVar = [ ('width', ctypes.c_uint32), ('height', ctypes.c_uint32), ('pixelFormat', ctypes.c_uint32), @@ -231,7 +231,7 @@ class _DISPLAYCONFIG_SOURCE_MODE(ctypes.Structure): class _RECTL(ctypes.Structure): - _fields_ = [ + _fields_: ClassVar = [ ('left', ctypes.c_uint32), ('top', ctypes.c_uint32), ('right', ctypes.c_uint32), @@ -240,7 +240,7 @@ class _RECTL(ctypes.Structure): class _DISPLAYCONFIG_DESKTOP_IMAGE_INFO(ctypes.Structure): - _fields_ = [ + _fields_: ClassVar = [ ('pathSourceSize', _POINTL), ('desktopImageRegion', _RECTL), ('desktopImageClip', _RECTL) @@ -248,7 +248,7 @@ class _DISPLAYCONFIG_DESKTOP_IMAGE_INFO(ctypes.Structure): class _DUMMYUNIONNAME_MODE(ctypes.Union): - _fields_ = [ + _fields_: ClassVar = [ ('targetMode', _DISPLAYCONFIG_TARGET_MODE), ('sourceMode', _DISPLAYCONFIG_SOURCE_MODE), ('desktopImageInfo', _DISPLAYCONFIG_DESKTOP_IMAGE_INFO) @@ -256,7 +256,7 @@ class _DUMMYUNIONNAME_MODE(ctypes.Union): class _DISPLAYCONFIG_MODE_INFO(ctypes.Structure): - _fields_ = [ + _fields_: ClassVar = [ ('infoType', ctypes.c_uint32), ('id', ctypes.c_uint32), ('adapterId', _LUID), @@ -275,7 +275,7 @@ class _DISPLAYCONFIG_MODE_INFO(ctypes.Structure): class _DISPLAYCONFIG_DEVICE_INFO_HEADER(ctypes.Structure): - _fields_ = [ + _fields_: ClassVar = [ ('type', ctypes.c_uint32), ('size', ctypes.c_uint32), ('adapterId', _LUID), @@ -287,7 +287,7 @@ class _DISPLAYCONFIG_DEVICE_INFO_HEADER(ctypes.Structure): class _DISPLAYCONFIG_SOURCE_DPI_SCALE_GET(ctypes.Structure): - _fields_ = [ + _fields_: ClassVar = [ ('header', _DISPLAYCONFIG_DEVICE_INFO_HEADER), ('minScaleRel', ctypes.c_uint32), ('curScaleRel', ctypes.c_uint32), @@ -299,7 +299,7 @@ class _DISPLAYCONFIG_SOURCE_DPI_SCALE_GET(ctypes.Structure): class _DISPLAYCONFIG_SOURCE_DPI_SCALE_SET(ctypes.Structure): - _fields_ = [ + _fields_: ClassVar = [ ('header', _DISPLAYCONFIG_DEVICE_INFO_HEADER), ('scaleRel', ctypes.c_uint32) ] @@ -309,7 +309,7 @@ class _DISPLAYCONFIG_SOURCE_DPI_SCALE_SET(ctypes.Structure): class _DISPLAY_CONFIG_TARGET_DEVICE_NAME(ctypes.Structure): - _fields_ = [ + _fields_: ClassVar = [ ('header', _DISPLAYCONFIG_DEVICE_INFO_HEADER), ('flags', ctypes.c_uint32), ('outputTechnology', ctypes.c_uint32), @@ -325,7 +325,7 @@ class _DISPLAY_CONFIG_TARGET_DEVICE_NAME(ctypes.Structure): class _DISPLAYCONFIG_SOURCE_DEVICE_NAME(ctypes.Structure): - _fields_ = [ + _fields_: ClassVar = [ ('header', _DISPLAYCONFIG_DEVICE_INFO_HEADER), ('viewGdiDeviceName', ctypes.wintypes.WCHAR * 32) ] diff --git a/tests/test_pymonctl.py b/tests/test_pymonctl.py index 6e5ccd5..5c0c5c4 100644 --- a/tests/test_pymonctl.py +++ b/tests/test_pymonctl.py @@ -39,7 +39,7 @@ def changedCB(names: list[str], info: dict[str, pmc.ScreenValue]) -> None: try: initArrangement = pmc.saveSetup() print("INITIAL POSITIONS:", initArrangement) -except: +except Exception: for monitor in monitorsPlugged: initDict[monitor.name] = {"relativePos": cast("pmc.Point", monitor.position)} if monitor.isPrimary: diff --git a/typings/Quartz/__init__.pyi b/typings/Quartz/__init__.pyi index 862d4c2..0473929 100644 --- a/typings/Quartz/__init__.pyi +++ b/typings/Quartz/__init__.pyi @@ -19,4 +19,4 @@ from Quartz.QuartzCore import * from Quartz.QuartzFilters import * from Quartz.QuickLookUI import * -def __getattr__(__name: str) -> Any: ... +def __getattr__(name: str, /) -> Any: ... From 703bc9b14f147a5b88da97e2ea0d2e8c14773544 Mon Sep 17 00:00:00 2001 From: Avasam Date: Wed, 24 Jun 2026 14:32:05 -0400 Subject: [PATCH 2/3] Reduce changes --- src/pymonctl/_main.py | 43 +++++++++-------------------------- src/pymonctl/_pymonctl_win.py | 24 +++++-------------- 2 files changed, 17 insertions(+), 50 deletions(-) diff --git a/src/pymonctl/_main.py b/src/pymonctl/_main.py index a7e2fc5..32f7844 100644 --- a/src/pymonctl/_main.py +++ b/src/pymonctl/_main.py @@ -998,41 +998,20 @@ def _getRelativePosition(monitor, relativeTo) -> tuple[int, int]: return x, y + if sys.platform == "darwin": - from ._pymonctl_macos import MacOSMonitor as Monitor - from ._pymonctl_macos import ( - _arrangeMonitors, - _findMonitor, - _getAllMonitors, - _getAllMonitorsDict, - _getMonitorsCount, - _getMousePos, - _getPrimary, - ) + from ._pymonctl_macos import (_getAllMonitors, _getAllMonitorsDict, _getMonitorsCount, _getPrimary, + _findMonitor, _arrangeMonitors, _getMousePos, MacOSMonitor as Monitor + ) elif sys.platform == "win32": - from ._pymonctl_win import Win32Monitor as Monitor - from ._pymonctl_win import ( - _arrangeMonitors, - _findMonitor, - _getAllMonitors, - _getAllMonitorsDict, - _getMonitorsCount, - _getMousePos, - _getPrimary, - ) + from ._pymonctl_win import (_getAllMonitors, _getAllMonitorsDict, _getMonitorsCount, _getPrimary, + _findMonitor, _arrangeMonitors, _getMousePos, Win32Monitor as Monitor + ) elif sys.platform == "linux": - from ._pymonctl_linux import LinuxMonitor as Monitor - from ._pymonctl_linux import ( - _arrangeMonitors, - _findMonitor, - _getAllMonitors, - _getAllMonitorsDict, - _getAllMonitorsDictThread, - _getMonitorsCount, - _getMonitorsData, - _getMousePos, - _getPrimary, - ) + from ._pymonctl_linux import (_getAllMonitors, _getAllMonitorsDict, _getAllMonitorsDictThread, _getMonitorsData, + _getMonitorsCount, _getPrimary, _findMonitor, _arrangeMonitors, _getMousePos, + LinuxMonitor as Monitor + ) else: raise NotImplementedError('PyMonCtl currently does not support this platform. If you think you can help, please contribute! https://github.com/Kalmat/PyMonCtl') diff --git a/src/pymonctl/_pymonctl_win.py b/src/pymonctl/_pymonctl_win.py index 4537373..58900a0 100644 --- a/src/pymonctl/_pymonctl_win.py +++ b/src/pymonctl/_pymonctl_win.py @@ -72,9 +72,7 @@ def _getAllMonitorsDict() -> dict[str, ScreenValue]: settings = win32api.EnumDisplaySettings(monName, win32con.ENUM_CURRENT_SETTINGS) except Exception: try: - settings = win32api.EnumDisplaySettings( - monName, win32con.ENUM_REGISTRY_SETTINGS - ) + settings = win32api.EnumDisplaySettings(monName, win32con.ENUM_REGISTRY_SETTINGS) except Exception: continue @@ -425,9 +423,7 @@ def orientation(self) -> int | Orientation | None: settings = win32api.EnumDisplaySettings(self.name, win32con.ENUM_CURRENT_SETTINGS) except Exception: try: - settings = win32api.EnumDisplaySettings( - self.name, win32con.ENUM_REGISTRY_SETTINGS - ) + settings = win32api.EnumDisplaySettings(self.name, win32con.ENUM_REGISTRY_SETTINGS) except Exception: pass if settings: @@ -441,9 +437,7 @@ def setOrientation(self, orientation: int | Orientation | None): settings = win32api.EnumDisplaySettings(self.name, win32con.ENUM_CURRENT_SETTINGS) except Exception: try: - settings = win32api.EnumDisplaySettings( - self.name, win32con.ENUM_REGISTRY_SETTINGS - ) + settings = win32api.EnumDisplaySettings(self.name, win32con.ENUM_REGISTRY_SETTINGS) except Exception: return if (settings.DisplayOrientation + orientation) % 2 == 1: @@ -461,9 +455,7 @@ def frequency(self) -> float | None: settings = win32api.EnumDisplaySettings(self.name, win32con.ENUM_CURRENT_SETTINGS) except Exception: try: - settings = win32api.EnumDisplaySettings( - self.name, win32con.ENUM_REGISTRY_SETTINGS - ) + settings = win32api.EnumDisplaySettings(self.name, win32con.ENUM_REGISTRY_SETTINGS) except Exception: pass if settings: @@ -478,9 +470,7 @@ def colordepth(self) -> int | None: settings = win32api.EnumDisplaySettings(self.name, win32con.ENUM_CURRENT_SETTINGS) except Exception: try: - settings = win32api.EnumDisplaySettings( - self.name, win32con.ENUM_REGISTRY_SETTINGS - ) + settings = win32api.EnumDisplaySettings(self.name, win32con.ENUM_REGISTRY_SETTINGS) except Exception: pass if settings: @@ -554,9 +544,7 @@ def mode(self) -> DisplayMode | None: settings = win32api.EnumDisplaySettings(self.name, win32con.ENUM_CURRENT_SETTINGS) except Exception: try: - settings = win32api.EnumDisplaySettings( - self.name, win32con.ENUM_REGISTRY_SETTINGS - ) + settings = win32api.EnumDisplaySettings(self.name, win32con.ENUM_REGISTRY_SETTINGS) except Exception: pass if settings: From 68f16dcf46f2f28eb59193068b12251e4ed8102a Mon Sep 17 00:00:00 2001 From: Avasam Date: Wed, 24 Jun 2026 19:51:34 -0400 Subject: [PATCH 3/3] Some spotted improvements --- src/pymonctl/_pymonctl_linux.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pymonctl/_pymonctl_linux.py b/src/pymonctl/_pymonctl_linux.py index 8e7d430..077222b 100644 --- a/src/pymonctl/_pymonctl_linux.py +++ b/src/pymonctl/_pymonctl_linux.py @@ -378,9 +378,9 @@ def dpi(self) -> tuple[float, float] | None: monitors = _XgetMonitors(self.name) if monitors: monitor = monitors[0] - _x, _y, w, h = monitor.x, monitor.y, monitor.width_in_pixels, monitor.height_in_pixels if monitor.width_in_millimeters != 0 and monitor.height_in_millimeters != 0: - dpiX, dpiY = round((w * 25.4) / monitor.width_in_millimeters), round((h * 25.4) / monitor.height_in_millimeters) + dpiX = round((monitor.width_in_pixels * 25.4) / monitor.width_in_millimeters), + dpiY = round((monitor.height_in_pixels * 25.4) / monitor.height_in_millimeters) else: dpiX, dpiY = 0.0, 0.0 return dpiX, dpiY @@ -1002,7 +1002,7 @@ def _XgetMonitorData(handle: int | None = None) -> tuple[Xlib.display.Display, S for monitorData in _XgetAllMonitors(): display, screen, root, monitor, monName = monitorData output = monitor.crtcs[0] - if (handle and handle == output) or (not handle and monitor.primary == 1): + if (handle == output if handle else monitor.primary == 1): return display, screen, root, monitor, output, monName return None