From eabc81b1cb2fadaf6fac1515b7fdbe07eb216dda Mon Sep 17 00:00:00 2001 From: Erkan Ozgur Yilmaz Date: Thu, 24 Oct 2024 11:26:47 +0100 Subject: [PATCH] [#414] Removed all the `# noqa: SC100` comments as it is better to adjust linting settings to ignore spell check. --- DisplayCAL/RealDisplaySizeMM.py | 20 +++--- DisplayCAL/config.py | 120 ++++++++++++++++---------------- DisplayCAL/dev/mocks.py | 32 +++++---- DisplayCAL/display_cal.py | 14 ++-- DisplayCAL/edid.py | 24 +++---- DisplayCAL/lib/agw/pygauge.py | 4 +- DisplayCAL/util_os.py | 36 +++++----- DisplayCAL/util_win.py | 36 +++++----- tests/conftest.py | 6 +- tests/test_edid.py | 23 ------ 10 files changed, 147 insertions(+), 168 deletions(-) diff --git a/DisplayCAL/RealDisplaySizeMM.py b/DisplayCAL/RealDisplaySizeMM.py index b3254bfb..f83751df 100644 --- a/DisplayCAL/RealDisplaySizeMM.py +++ b/DisplayCAL/RealDisplaySizeMM.py @@ -255,7 +255,7 @@ def get_display(display_no=0): if _displays is None: return None - # Translate from Argyll display index to enumerated display index using the # noqa: SC100 + # Translate from Argyll display index to enumerated display index using the # coordinates and dimensions from DisplayCAL.config import getcfg, is_virtual_display @@ -286,14 +286,14 @@ def get_wayland_display(x, y, w, h): Given x, y, width and height of display geometry, find matching Wayland display. """ # Note that we apparently CANNOT use width and height because the reported - # values from Argyll code and Mutter can be slightly different, # noqa: SC100 - # e.g. 3660x1941 from Mutter vs 3656x1941 from Argyll when HiDPI is enabled. # noqa: SC100 - # The xrandr output is also interesting in that case: # noqa: SC100 - # $ xrandr # noqa: SC100 + # values from Argyll code and Mutter can be slightly different, + # e.g. 3660x1941 from Mutter vs 3656x1941 from Argyll when HiDPI is enabled. + # The xrandr output is also interesting in that case: + # $ xrandr # Screen 0: minimum 320 x 200, current 3660 x 1941, maximum 8192 x 8192 - # XWAYLAND0 connected 3656x1941+0+0 (normal left inverted right x axis y axis) 0mm x 0mm # noqa: SC100,B950 - # 3656x1941 59.96*+ # noqa: SC100 - # Note the apparent mismatch between first and 2nd/3rd line. # noqa: SC100 + # XWAYLAND0 connected 3656x1941+0+0 (normal left inverted right x axis y axis) 0mm x 0mm,B950 + # 3656x1941 59.96*+ + # Note the apparent mismatch between first and 2nd/3rd line. # Look for active display at x, y instead. # Currently, only support for GNOME 3 / Mutter try: @@ -318,10 +318,10 @@ def get_wayland_display(x, y, w, h): def find_matching_output(res, x, y): """Find the matching output in the resources.""" crtcs = res[1] - # Look for matching CRTC # noqa: SC100 + # Look for matching CRTC for crtc in crtcs: if crtc[2:4] == (x, y) and crtc[6] != -1: - # Found our CRTC # noqa: SC100 + # Found our CRTC crtc_id = crtc[0] # Look for matching output outputs = res[2] diff --git a/DisplayCAL/config.py b/DisplayCAL/config.py index 6adbc2d2..b4d15712 100644 --- a/DisplayCAL/config.py +++ b/DisplayCAL/config.py @@ -77,7 +77,7 @@ or os.path.join(os.path.dirname(__file__), "main.py") ) pypath = exe if isexe else os.path.abspath(pyfile) -# Mac OS X: isapp should only be true for standalone, not 0install # noqa: SC100 +# Mac OS X: isapp should only be true for standalone, not 0install isapp = ( sys.platform == "darwin" and exe.split(os.path.sep)[-3:-1] == ["Contents", "MacOS"] @@ -92,23 +92,23 @@ exe if isexe else os.path.abspath(os.path.dirname(__file__)) ) -# TODO: Modifying ``data_dirs`` here was not an elegant solution, # noqa: SC100 +# TODO: Modifying ``data_dirs`` here was not an elegant solution, # and it is not solving the problem either. data_dirs = [ - # venv/share/DisplayCAL # noqa: SC100 + # venv/share/DisplayCAL os.path.join(os.path.dirname(os.path.dirname(pypath)), "share", "DisplayCAL"), - # venv/lib/python3.x/site-packages/DisplayCAL # noqa: SC100 + # venv/lib/python3.x/site-packages/DisplayCAL pydir, - # venv/share # noqa: SC100 + # venv/share os.path.join(os.path.dirname(pydir), "share"), - # venv/lib/python3.x/site-packages/DisplayCAL-*.egg/share/DisplayCAL # noqa: SC100 + # venv/lib/python3.x/site-packages/DisplayCAL-*.egg/share/DisplayCAL os.path.join(os.path.dirname(pydir), "share", "DisplayCAL"), ] extra_data_dirs = [] -# Search directories on PATH for data directories so Argyll reference files can # noqa: SC100 -# be found automatically if Argyll directory not explicitly configured # noqa: SC100 +# Search directories on PATH for data directories so Argyll reference files can +# be found automatically if Argyll directory not explicitly configured for dir_ in getenvu("PATH", "").split(os.pathsep): dir_parent = os.path.dirname(dir_) if os.path.isdir(os.path.join(dir_parent, "ref")): @@ -122,12 +122,12 @@ datahome = os.path.join(appdata, appbasename) if sys.platform == "win32": if pydir.lower().startswith(exedir.lower()) and pydir != exedir: - # We are installed in a subfolder of the executable directory # noqa: SC100 - # (e.g. C:\Python26\Lib\site-packages\DisplayCAL) # noqa: SC100 + # We are installed in a subfolder of the executable directory + # (e.g. C:\Python26\Lib\site-packages\DisplayCAL) # we need to add the executable directory to the data directories so - # files in subfolders of the executable directory which are not in # noqa: SC100 + # files in subfolders of the executable directory which are not in # Lib\site-packages\DisplayCAL can be found - # (e.g. Scripts\displaycal-apply-profiles) # noqa: SC100 + # (e.g. Scripts\displaycal-apply-profiles) data_dirs.append(exedir) script_ext = ".cmd" scale_adjustment_factor = 1.0 @@ -216,7 +216,7 @@ # Is the device directly connected or e.g. driven via network? # (note that madVR can technically be both, but the endpoint is always directly # connected to a display so we have videoLUT access via madVR's API. -# Only devices which don't support that are considered 'untethered' in this context) # noqa: SC100 +# Only devices which don't support that are considered 'untethered' in this context) untethered_displays = non_argyll_displays + ( "Web$", "Chromecast ", @@ -413,7 +413,7 @@ def load_bitmap(parts, ow, oh, w, h, scale, use_mask): parts[-1] = parts[-1].lower() oname = parts[-1] if "#" in oname: - # Hex format, RRGGBB or RRGGBBAA # noqa: SC100 + # Hex format, RRGGBB or RRGGBBAA oname, color = oname.split("#", 1) parts[-1] = oname else: @@ -434,11 +434,11 @@ def load_bitmap(parts, ow, oh, w, h, scale, use_mask): elif i == 1: if scale < 1.75 or scale == 2: continue - # HighDPI support. Try @4x version # noqa: SC100 + # HighDPI support. Try @4x version parts[-2] = "%ix%i" % (ow, oh) parts[-1] = name4x elif i == 2: - # HighDPI support. Try @2x version # noqa: SC100 + # HighDPI support. Try @2x version parts[-2] = "%ix%i" % (ow, oh) parts[-1] = name2x elif i == 3: @@ -455,10 +455,10 @@ def load_bitmap(parts, ow, oh, w, h, scale, use_mask): elif i == 1: if scale < 1.75 or scale == 2: continue - # HighDPI support. Try @4x version # noqa: SC100 + # HighDPI support. Try @4x version parts[-1] = name4x elif i == 2: - # HighDPI support. Try @2x version # noqa: SC100 + # HighDPI support. Try @2x version parts[-1] = name2x else: # Try original size @@ -483,14 +483,14 @@ def load_bitmap(parts, ow, oh, w, h, scale, use_mask): if scale > 1 and i: rescale = False if i in (1, 2): - # HighDPI support. 4x/2x version, determine scaled size # noqa: SC100 + # HighDPI support. 4x/2x version, determine scaled size w, h = [int(round(v / (2 * (3 - i)) * scale)) for v in bmp.Size] rescale = True elif len(size) == 2: # HighDPI support. Icon rescale = True if rescale and (bmp.Size[0] != w or bmp.Size[1] != h): - # HighDPI support. Rescale # noqa: SC100 + # HighDPI support. Rescale img = bmp.ConvertToImage() if not hasattr(wx, "IMAGE_QUALITY_BILINEAR") or oname == "list-add": # In case bilinear is not supported, @@ -564,7 +564,7 @@ def load_bitmap(parts, ow, oh, w, h, scale, use_mask): alpha = 1.0 img = img.AdjustChannels(R, G, B, alpha) if color: - # Hex format, RRGGBB or RRGGBBAA # noqa: SC100 + # Hex format, RRGGBB or RRGGBBAA R = int(color[0:2], 16) / 255.0 G = int(color[2:4], 16) / 255.0 B = int(color[4:6], 16) / 255.0 @@ -610,7 +610,7 @@ def get_bitmap_as_icon(size, name, scale=True): icon = wx.EmptyIcon() if sys.platform == "darwin" and wx.VERSION >= (2, 9) and size > 128: - # FIXME: wxMac 2.9 doesn't support icon sizes above 128 # noqa: SC100 + # FIXME: wxMac 2.9 doesn't support icon sizes above 128 size = 128 bmp = geticon(size, name, scale) icon.CopyFromBitmap(bmp) @@ -764,7 +764,7 @@ def get_icon_bundle(sizes, name): iconbundle = wx.IconBundle() if not sizes: - # Assume ICO format # noqa: SC100 + # Assume ICO format pth = get_data_path(f"theme/icons/{name}.ico") if pth: ico = wx.Icon(pth) @@ -849,9 +849,9 @@ def get_data_path(relpath, rex=None): and not os.path.exists(curpath) ): # Work-around distribution-specific differences for location of - # Argyll reference files # noqa: SC100 - # Fedora and Ubuntu: /usr/share/color/argyll/ref # noqa: SC100 - # openSUSE: /usr/share/color/argyll # noqa: SC100 + # Argyll reference files + # Fedora and Ubuntu: /usr/share/color/argyll/ref + # openSUSE: /usr/share/color/argyll pth = relpath.split("/", 1)[-1] if pth != "ref": curpath = os.path.join(dir_, pth) @@ -991,9 +991,9 @@ def optionxform(self, optionstr): "app.port": [1, 65535], "gamma": [0.000001, 10], "trc": [0.000001, 10], - # Argyll dispcal uses 20% of ambient (in lux, fixed steradiant of 3.1415) as # noqa: SC100 - # adapting luminance, but we assume it already *is* the adapting luminance. # noqa: SC100 - # To correct for this, scale so that dispcal gets the correct value. # noqa: SC100 + # Argyll dispcal uses 20% of ambient (in lux, fixed steradiant of 3.1415) as + # adapting luminance, but we assume it already *is* the adapting luminance. + # To correct for this, scale so that dispcal gets the correct value. "calibration.ambient_viewcond_adjust.lux": [0.0, sys.maxsize / 5.0], "calibration.black_luminance": [0.000001, 10], "calibration.black_output_offset": [0, 1], @@ -1031,7 +1031,7 @@ def optionxform(self, optionstr): "3dlut.bitdepth.input": [8, 10, 12, 14, 16], "3dlut.bitdepth.output": [8, 10, 12, 14, 16], "3dlut.encoding.input": list(video_encodings), - # collink: xvYCC output encoding is not supported # noqa: SC100 + # collink: xvYCC output encoding is not supported "3dlut.encoding.output": [v for v in video_encodings if v not in ("T", "x", "X")], "3dlut.format": [ "3dl", @@ -1063,11 +1063,11 @@ def optionxform(self, optionstr): "colorimeter_correction.observer": observers, "colorimeter_correction.observer.reference": observers, "colorimeter_correction.type": ["matrix", "spectral"], - # Measurement modes as supported by Argyll -y parameter # noqa: SC100 + # Measurement modes as supported by Argyll -y parameter # 'l' = 'n' (non-refresh-type display, e.g. LCD) # 'c' = 'r' (refresh-type display, e.g. CRT) # We map 'l' and 'c' to "n" and "r" in - # worker.Worker.add_measurement_features if using Argyll >= 1.5 # noqa: SC100 + # worker.Worker.add_measurement_features if using Argyll >= 1.5 # See http://www.argyllcms.com/doc/instruments.html for description of # per-instrument supported modes "measurement_mode": [None, "auto"] + list(string.digits[1:] + string.ascii_letters), @@ -1099,7 +1099,7 @@ def optionxform(self, optionstr): "profile_loader.tray_icon_animation_quality": [0, 1, 2], "synthprofile.black_point_compensation": [0, 1], "synthprofile.trc_gamma_type": ["g", "G"], - # Q = Argyll >= 1.1.0 # noqa: SC100 + # Q = Argyll >= 1.1.0 "tc_algo": ["", "t", "r", "R", "q", "Q", "i", "I"], "tc_vrml_use_D50": [0, 1], "tc_vrml_cie_colorspace": [ @@ -1360,7 +1360,7 @@ def optionxform(self, optionstr): "position.synthiccframe.y": 50, "position.tcgen.x": 50, "position.tcgen.y": 50, - # Force black point compensation due to OS X bugs with non BPC profiles # noqa: SC100 + # Force black point compensation due to OS X bugs with non BPC profiles "profile.black_point_compensation": 0 if sys.platform != "darwin" else 1, "profile.black_point_correction": 0.0, "profile.create_gamut_views": 1, @@ -1391,8 +1391,8 @@ def optionxform(self, optionstr): "profile.b2a.hires.size": -1, "profile.b2a.hires.smooth": 1, "profile.save_path": storage, # directory - # Force profile type to single shaper + matrix due to OS X bugs with cLUT # noqa: SC100 - # profiles and matrix profiles with individual shaper curves # noqa: SC100 + # Force profile type to single shaper + matrix due to OS X bugs with cLUT + # profiles and matrix profiles with individual shaper curves "profile.type": "X" if sys.platform != "darwin" else "S", "profile.update": 0, "profile_loader.buggy_video_drivers": ";".join(["*"]), @@ -1512,7 +1512,7 @@ def optionxform(self, optionstr): "tc_white_patches": 4, "tc.show": 0, # Profile type forced to matrix due to OS X bugs with cLUT profiles. - # Set smallest testchart. # noqa: SC100 + # Set smallest testchart. "testchart.auto_optimize": 4 if sys.platform != "darwin" else 1, "testchart.file": "auto", "testchart.file.backup": "auto", @@ -1558,10 +1558,10 @@ def optionxform(self, optionstr): testchart_defaults = { "s": { None: "auto" - }, # shaper + matrix # noqa: SC100 + }, # shaper + matrix "l": { None: "auto" - }, # lut # noqa: SC100 + }, # lut "g": {None: "auto"}, # gamma + matrix } @@ -1636,7 +1636,7 @@ def getcfg(name, fallback=True, raw=False, cfg=cfg): print(f"Invalid config value for {name}: {value}", end=" ") value = None elif name == "copyright": - # Make sure DisplayCAL and Argyll version are up-to-date # noqa: SC100 + # Make sure DisplayCAL and Argyll version are up-to-date pattern = re.compile( r"(%s(?:\s*v(?:ersion|\.)?)?\s*)\d+(?:\.\d+)*" % appname, re.I ) @@ -1662,7 +1662,7 @@ def getcfg(name, fallback=True, raw=False, cfg=cfg): # Map n and r measurement modes to canonical l and c # the inverse mapping happens per-instrument in # Worker.add_measurement_features(). - # That way we can have compatibility with old and current Argyll CMS # noqa: SC100 + # That way we can have compatibility with old and current Argyll CMS value = {"n": "l", "r": "c"}.get(value, value) if value is None: if hasdef and fallback: @@ -1682,12 +1682,12 @@ def getcfg(name, fallback=True, raw=False, cfg=cfg): and (name != "testchart.file" or value != "auto") and (not os.path.isabs(value) or not os.path.exists(value)) ): - # colorimeter_correction_matrix_file is special because it's not (only) a path # noqa: SC100 + # colorimeter_correction_matrix_file is special because it's not (only) a path if debug: print(f"{name} does not exist: {value}", end=" ") - # Normalize path (important, this turns altsep into sep under Windows) # noqa: SC100 + # Normalize path (important, this turns altsep into sep under Windows) value = os.path.normpath(value) - # Check if this is a relative path covered by data_dirs # noqa: SC100 + # Check if this is a relative path covered by data_dirs if ( value.split(os.path.sep)[-3:-2] == [appname] or not os.path.isabs(value) ) and ( @@ -1777,7 +1777,7 @@ def get_standard_profiles(paths_only=False): if not standard_profiles: from DisplayCAL import ICCProfile as ICCP - # Reference profiles (Argyll + DisplayCAL) # noqa: SC100 + # Reference profiles (Argyll + DisplayCAL) ref_icc = get_data_path("ref", r"\.ic[cm]$") or [] # Other profiles installed on the system other_icc = [] @@ -2033,7 +2033,7 @@ def initcfg(module=None, cfg=cfg, force_load=False): # Set default preset setcfg("calibration.file", defaults["calibration.file"], cfg=cfg) - # Read cfg # noqa: SC100 + # Read cfg cfgnames = [appbasename] if module: cfgnames.append(cfgbasename) @@ -2065,7 +2065,7 @@ def initcfg(module=None, cfg=cfg, force_load=False): msg = "Reloading" else: msg = "Loading" - # logger.debug(msg, cfgfile) # noqa: SC100 + # logger.debug(msg, cfgfile) print(msg, cfgfile) # Make user config take precedence break @@ -2103,7 +2103,7 @@ def initcfg(module=None, cfg=cfg, force_load=False): def set_default_app_dpi(): """Set application DPI.""" - # Only call this after creating the wx.App object! # noqa: SC100 + # Only call this after creating the wx.App object! global dpiset if not dpiset and not getcfg("app.dpi", False): # HighDPI support @@ -2118,7 +2118,7 @@ def set_default_app_dpi(): from DisplayCAL.util_os import which txt_scale = None - # XDG_CURRENT_DESKTOP delimiter is colon (':') # noqa: SC100 + # XDG_CURRENT_DESKTOP delimiter is colon (':') desktop = os.getenv("XDG_CURRENT_DESKTOP", "").split(":") if "gtk2" in wx.PlatformInfo: txt_scale = get_hidpi_scaling_factor() @@ -2164,7 +2164,7 @@ def get_hidpi_scaling_factor(): p = sp.Popen( ["xrdb", "-query"], stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE ) - # Format: 'Xft.dpi: 192' # noqa: SC100 + # Format: 'Xft.dpi: 192' stdout, stderr = p.communicate() for line in stdout.splitlines(): line = line.decode() @@ -2176,19 +2176,19 @@ def get_hidpi_scaling_factor(): except ValueError: pass factor = None - # XDG_CURRENT_DESKTOP delimiter is colon (':') # noqa: SC100 + # XDG_CURRENT_DESKTOP delimiter is colon (':') desktop = os.getenv("XDG_CURRENT_DESKTOP", "").split(":") if desktop[0] == "KDE": # Two env-vars exist: QT_SCALE_FACTOR and QT_SCREEN_SCALE_FACTORS. # According to documentation[1], the latter is 'mainly useful for debugging' - # that's not how it is used by KDE though. # noqa: SC100 - # Changing display scaling via KDE settings GUI only sets # noqa: SC100 + # that's not how it is used by KDE though. + # Changing display scaling via KDE settings GUI only sets # QT_SCREEN_SCALE_FACTORS. We are thus currently ignoring QT_SCALE_FACTOR. # [1] https://doc.qt.io/qt-5/highdpi.html # QT_SCREEN_SCALE_FACTORS delimiter is semicolon (';') - # Format: Mapping of XrandR display names to scale factor # noqa: SC100 + # Format: Mapping of XrandR display names to scale factor # e.g. 'VGA-1=1.5;VGA-2=2.0;' - # or just list of scale factors e.g. '1.5;2.0;' # noqa: SC100 + # or just list of scale factors e.g. '1.5;2.0;' screen_scale_factors = os.getenv("QT_SCREEN_SCALE_FACTORS", "").split(";") if screen_scale_factors: from DisplayCAL.wxaddons import wx @@ -2204,7 +2204,7 @@ def get_hidpi_scaling_factor(): if top: tmp = False else: - # Create temp frame if no topwindow # noqa: SC100 + # Create temp frame if no topwindow top = wx.Frame(None) # Move to main window location (and thus screen) x, y = ( @@ -2214,7 +2214,7 @@ def get_hidpi_scaling_factor(): if None not in (x, y): top.SetSaneGeometry(x, y) tmp = True - # Get wx display # noqa: SC100 + # Get wx display wx_display = top.GetDisplay() if tmp: # No longer need our temp frame @@ -2254,7 +2254,7 @@ def get_hidpi_scaling_factor(): stdout=sp.PIPE, stderr=sp.PIPE, ) - # Format: 'unint32 1' # noqa: SC100 + # Format: 'unint32 1' stdout, stderr = p.communicate() split = stdout.split() if split: @@ -2353,7 +2353,7 @@ def writecfg(which="user", worker=None, module=None, options=(), cfg=cfg): ) return False else: - # system-wide config - only stores essentials ie. Argyll directory # noqa: SC100 + # system-wide config - only stores essentials ie. Argyll directory cfgfilename1 = os.path.join(confighome, f"{cfgbasename}.local.ini") cfgfilename2 = os.path.join(config_sys, f"{cfgbasename}.ini") if sys.platform == "win32": @@ -2379,7 +2379,7 @@ def writecfg(which="user", worker=None, module=None, options=(), cfg=cfg): cfgfile.close() if sys.platform != "win32": # on Linux and OS X, we write the file to the user's config dir - # then 'su mv' it to the system-wide config dir # noqa: SC100 + # then 'su mv' it to the system-wide config dir result = worker.exec_cmd( "mv", ["-f", cfgfilename1, cfgfilename2], diff --git a/DisplayCAL/dev/mocks.py b/DisplayCAL/dev/mocks.py index 48d2e75b..fad56eb8 100644 --- a/DisplayCAL/dev/mocks.py +++ b/DisplayCAL/dev/mocks.py @@ -9,9 +9,10 @@ import contextlib from types import ModuleType -from typing import Any, Dict, Generator, List, Tuple, Type, overload +from typing import Any, Callable, Dict, Generator, List, Tuple, Type, overload from _pytest.monkeypatch import MonkeyPatch +from mypy_extensions import KwArg, VarArg Call = Tuple[Tuple[Any, ...], Dict[str, Any]] CallList = List[Call] @@ -19,23 +20,25 @@ @overload @contextlib.contextmanager -def _mp_call( # noqa: E704 +def _mp_call( monkeypatch: MonkeyPatch, mock_class: Type[Any] | ModuleType, method: str, return_value: Any, as_property: bool, -) -> Generator[CallList, None, None]: ... +) -> Generator[CallList, None, None]: + ... @overload @contextlib.contextmanager -def _mp_call( # noqa: E704 +def _mp_call( monkeypatch: MonkeyPatch, mock_class: str, method: Any, # return value in this case return_value: bool, # as_property in this case -) -> Generator[CallList, None, None]: ... +) -> Generator[CallList, None, None]: + ... @contextlib.contextmanager @@ -46,8 +49,7 @@ def _mp_call( return_value: Any, as_property: bool = False, ) -> Generator[CallList, None, None]: - """ - Mock a method in a class and record the calls to it. + """Mock a method in a class and record the calls to it. If the given return_value is an Exception, it will be raised. If not, the value will be returned from the mocked function/method. @@ -58,8 +60,8 @@ def func_call(*a: Any, **k: Any) -> Any: """Mock the function call.""" calls.append((a, k)) if isinstance(return_value, Exception): - # bug in pylint https://www.logilab.org/ticket/3207 # noqa: SC100 - raise return_value # pylint: disable-msg=raising-bad-type # noqa: SC100 + # bug in pylint https://www.logilab.org/ticket/3207 + raise return_value # pylint: disable-msg=raising-bad-type if callable(return_value): # Handle the case that a function was passed return return_value(*a, **k) @@ -83,7 +85,7 @@ def func_call(*a: Any, **k: Any) -> Any: @contextlib.contextmanager -def check_call( # pylint: disable=too-many-arguments # noqa: SC100 +def check_call( # pylint: disable=too-many-arguments mock_class: Type[Any] | ModuleType, method: str, return_value: Any = None, @@ -110,9 +112,9 @@ def check_call( # pylint: disable=too-many-arguments "call_args and call_kwargs must be None or have a value " "(list/dict if empty)" ) monkeypatch = MonkeyPatch() - with _mp_call(monkeypatch, mock_class, method, return_value, as_property) as calls: + calls = _mp_call(monkeypatch, mock_class, method, return_value, as_property) try: - yield calls + yield calls finally: m_name = f"{mock_class.__name__}.{method}" monkeypatch.undo() @@ -122,7 +124,7 @@ def check_call( # pylint: disable=too-many-arguments # Duplicate the code because overloading is a mess due to this bug: # https://github.com/python/mypy/issues/11373 @contextlib.contextmanager -def check_call_str( # pylint: disable=too-many-arguments # noqa: SC100 +def check_call_str( # pylint: disable=too-many-arguments mock_class: str, return_value: Any = None, call_args_list: List[Tuple[Any, ...]] | None = None, @@ -141,8 +143,8 @@ def check_call_str( # pylint: disable=too-many-arguments "call_args and call_kwargs must be None or have a value " "(list/dict if empty)" ) monkeypatch = MonkeyPatch() - with _mp_call(monkeypatch, mock_class, return_value, as_property) as calls: - yield calls + calls = _mp_call(monkeypatch, mock_class, return_value, as_property) + yield calls m_name = mock_class monkeypatch.undo() assert_calls(call_count, call_args_list, call_kwargs_list, calls, m_name) diff --git a/DisplayCAL/display_cal.py b/DisplayCAL/display_cal.py index ece93f8c..c192c991 100644 --- a/DisplayCAL/display_cal.py +++ b/DisplayCAL/display_cal.py @@ -34,7 +34,7 @@ import urllib.error import urllib.parse import urllib.request -import webbrowser # Import the webbrowser module for platform-independent results # noqa: SC100 +import webbrowser # Import the webbrowser module for platform-independent results import zipfile from decimal import Decimal from hashlib import md5 @@ -252,7 +252,7 @@ from send2trash import send2trash -# wxPython # noqa: SC100 +# wxPython from wx import xrc from wx.lib import delayedresult, platebtn from wx.lib.art import flagart @@ -288,15 +288,15 @@ except ImportError: ProfileInfoFrame = None -# wxPython # noqa: SC100 +# wxPython try: - # Only wx.lib.aui.AuiNotebook looks reasonable across _all_ platforms. # noqa: SC100 - # Other tabbed book controls like wx.Notebook or wx.aui.AuiNotebook are # noqa: SC100 - # impossible to get to look right under GTK because there's no way to set # noqa: SC100 + # Only wx.lib.aui.AuiNotebook looks reasonable across _all_ platforms. + # Other tabbed book controls like wx.Notebook or wx.aui.AuiNotebook are + # impossible to get to look right under GTK because there's no way to set # the correct background color for the pages. from wx.lib.agw import aui except ImportError: - # Fall back to wx.aui under ancient wxPython versions # noqa: SC100 + # Fall back to wx.aui under ancient wxPython versions from wx import aui # Set no delay time to open the web page diff --git a/DisplayCAL/edid.py b/DisplayCAL/edid.py index 7ce25465..5b3fad43 100644 --- a/DisplayCAL/edid.py +++ b/DisplayCAL/edid.py @@ -110,12 +110,12 @@ import pythoncom import threading - # Use registry as fallback for Win2k/XP/2003 # noqa: SC100 + # Use registry as fallback for Win2k/XP/2003 import winreg wmi = None if sys.getwindowsversion() >= (6,): - # Use WMI for Vista/Win7 # noqa: SC100 + # Use WMI for Vista/Win7 try: import wmi except Exception: @@ -232,7 +232,7 @@ def get_edid_windows(display_no, device): edid = None if not device: - # The ordering will work as long as Argyll continues using EnumDisplayMonitors # noqa: SC100 + # The ordering will work as long as Argyll continues using EnumDisplayMonitors monitors = util_win.get_real_display_devices_info() moninfo = monitors[display_no] device = util_win.get_active_display_device(moninfo["Device"]) @@ -288,7 +288,7 @@ def get_edid_windows_wmi(id, wmi_connection, not_main_thread): try: edid = msmonitor.WmiGetMonitorRawEEdidV1Block(0) except Exception: - # No EDID entry # noqa: SC100 + # No EDID entry pass else: edid = "".join(chr(i) for i in edid[0]) @@ -366,7 +366,7 @@ def get_edid_windows_registry(id, device): try: edid = winreg.QueryValueEx(devparms, "EDID")[0] except WindowsError: - # No EDID entry # noqa: SC100 + # No EDID entry pass else: return edid @@ -584,9 +584,9 @@ def get_pnpid_paths(): list: List of possible paths. """ paths = [ - "/usr/lib/udev/hwdb.d/20-acpi-vendor.hwdb", # systemd # noqa: SC100 - "/usr/share/hwdata/pnp.ids", # hwdata, e.g. Red Hat # noqa: SC100 - "/usr/share/misc/pnp.ids", # pnputils, e.g. Debian # noqa: SC100 + "/usr/lib/udev/hwdb.d/20-acpi-vendor.hwdb", # systemd + "/usr/share/hwdata/pnp.ids", # hwdata, e.g. Red Hat + "/usr/share/misc/pnp.ids", # pnputils, e.g. Debian "/usr/share/libgnome-desktop/pnp.ids", ] # fallback gnome-desktop if sys.platform in ("darwin", "win32"): @@ -709,7 +709,7 @@ def edid_parse_string(desc): Returns: bytes: The parsed string. """ - # Return value should match colord's cd_edid_parse_string in cd-edid.c # noqa: SC100 + # Return value should match colord's cd_edid_parse_string in cd-edid.c # Remember: In C, NULL terminates a string, so do the same here # Replace newline with NULL desc = desc[:13].replace(b"\n", b"\x00").replace(b"\r", b"\x00") @@ -774,7 +774,7 @@ def fix_edid_encoding(edid): """ # this is probably encoded/decoded in a wrong way and contains 2-bytes characters # - # b"\xc2" and b"\xc3" are codepoints # noqa: SC100 + # b"\xc2" and b"\xc3" are codepoints # they can only appear if the byte data is decoded with latin-1 and encoded # back with utf-8. # This apparently is a wrong conversion. @@ -935,8 +935,8 @@ def parse_color_point_data(block): """ result = {} for i in (5, 10): - # 2nd white point index in range 1...255 # noqa: SC100 - # 3rd white point index in range 2...255 # noqa: SC100 + # 2nd white point index in range 1...255 + # 3rd white point index in range 2...255 # 0 = do not use if block[i] > i / 5: white_x = edid_decode_fraction( diff --git a/DisplayCAL/lib/agw/pygauge.py b/DisplayCAL/lib/agw/pygauge.py index b4238aac..4bd54fb6 100644 --- a/DisplayCAL/lib/agw/pygauge.py +++ b/DisplayCAL/lib/agw/pygauge.py @@ -1,12 +1,12 @@ # ---------------------------------------------------------------------------- # -# PYGAUGE wxPython IMPLEMENTATION # noqa: SC100 +# PYGAUGE wxPython IMPLEMENTATION # # Mark Reed, @ 28 Jul 2010 # Latest Revision: 27 Dec 2012, 21.00 GMT # # TODO List # -# 1. Indeterminate mode (see wx.Gauge) # noqa: SC100 +# 1. Indeterminate mode (see wx.Gauge) # 2. Vertical bar # 3. Bitmap support (bar, background) # 4. UpdateFunction - Pass a function to PyGauge which will be called every X diff --git a/DisplayCAL/util_os.py b/DisplayCAL/util_os.py index abbca7e0..ebc8875c 100644 --- a/DisplayCAL/util_os.py +++ b/DisplayCAL/util_os.py @@ -173,7 +173,7 @@ def listdir(path, *args, **kwargs): """ paths = _listdir(path, *args, **kwargs) if isinstance(path, str): - # Undecodable filenames will still be string objects. # noqa: SC100 + # Undecodable filenames will still be string objects. # Ignore them. paths = [path for path in paths if isinstance(path, str)] return paths @@ -247,24 +247,24 @@ def find_library(pattern, arch=None): except Exception: pass else: - # /usr/bin/python3.7: ELF 64-bit LSB shared object, x86-64, # noqa: SC100 - # version 1 (SYSV), dynamically linked, interpreter # noqa: SC100 - # /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, # noqa: SC100 - # BuildID[sha1]=41a1f0d4da3afee8f22d1947cc13a9f33f59f2b8, # noqa: SC100 + # /usr/bin/python3.7: ELF 64-bit LSB shared object, x86-64, + # version 1 (SYSV), dynamically linked, interpreter + # /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, + # BuildID[sha1]=41a1f0d4da3afee8f22d1947cc13a9f33f59f2b8, # stripped parts = file_stdout.split(",") if len(parts) > 1: arch = parts[1].strip() for line in stdout.decode().splitlines(): - # libxyz.so (libc6,x86_64) => /lib64/libxyz.so.1 # noqa: SC100 + # libxyz.so (libc6,x86_64) => /lib64/libxyz.so.1 parts = line.split("=>", 1) candidate = parts[0].split(None, 1) if len(parts) < 2 or len(candidate) < 2: continue info = candidate[1].strip("( )").split(",") if arch and len(info) > 1 and info[1].strip() != arch: - # Skip libs for wrong arch # noqa: SC100 + # Skip libs for wrong arch continue filename = candidate[0] if fnmatch.fnmatch(filename, pattern): @@ -588,8 +588,8 @@ def launch_file(filepath): if sys.platform == "darwin": retcode = sp.call(["open", filepath], **kwargs) elif sys.platform == "win32": - # for win32, we could use os.startfile, # noqa: SC100 - # but then we'd not be able to return exitcode (does it matter?) # noqa: SC100 + # for win32, we could use os.startfile, + # but then we'd not be able to return exitcode (does it matter?) retcode = sp.call(f'start "" "{filepath}"', **kwargs) elif which("xdg-open"): retcode = sp.call(["xdg-open", filepath], **kwargs) @@ -843,7 +843,7 @@ def readlink(path): # This wouldn't return true if the file didn't exist if not islink(path): - # Mimic POSIX error # noqa: SC100 + # Mimic POSIX error raise OSError(22, "Invalid argument", path) # Open the file correctly depending on the string type. @@ -852,11 +852,11 @@ def readlink(path): else: createfilefn = win32file.CreateFile - # Create a PySECURITY_ATTRIBUTES object # noqa: SC100 + # Create a PySECURITY_ATTRIBUTES object security_attributes = win32security.SECURITY_ATTRIBUTES() - # FILE_FLAG_OPEN_REPARSE_POINT alone is not enough if 'path' is a symbolic # noqa: SC100 - # link to a directory or a NTFS junction. # noqa: SC100 + # FILE_FLAG_OPEN_REPARSE_POINT alone is not enough if 'path' is a symbolic + # link to a directory or a NTFS junction. # We need to set FILE_FLAG_BACKUP_SEMANTICS as well. See # https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createfilea # Now use this security_attributes object in the CreateFileW call @@ -878,7 +878,7 @@ def readlink(path): else: handle = int(str(handle)) - # MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16384 = (16 * 1024) # noqa: SC100 + # MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16384 = (16 * 1024) buf = win32file.DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, None, 16 * 1024) # Above will return an ugly string (byte array), so we'll need to parse it. @@ -977,9 +977,9 @@ def safe_iglob(pathname): for name in safe_glob1(os.curdir, basename): yield name return - # `os.path.split()` returns the argument itself as a dirname if it is a # noqa: SC100 - # drive or UNC path. # noqa: SC100 - # Prevent an infinite recursion if a drive or UNC path contains magic # noqa: SC100 + # `os.path.split()` returns the argument itself as a dirname if it is a + # drive or UNC path. + # Prevent an infinite recursion if a drive or UNC path contains magic # characters (i.e. r'\\?\C:'). if dirname != pathname and glob.has_magic(dirname): dirs = safe_iglob(dirname) @@ -1047,7 +1047,7 @@ def safe_shell_filter(names, pat): _cache[pat] = re_pat = re.compile(res) match = re_pat.match if os.path is posixpath: - # normcase on posix is NOP. Optimize it away from the loop. # noqa: SC100 + # normcase on posix is NOP. Optimize it away from the loop. for name in names: if match(name): result.append(name) diff --git a/DisplayCAL/util_win.py b/DisplayCAL/util_win.py index ea530713..ca2273ba 100644 --- a/DisplayCAL/util_win.py +++ b/DisplayCAL/util_win.py @@ -49,19 +49,19 @@ psapi = None -# Access registry directly instead of Wcs* functions that leak handles # noqa: SC100 +# Access registry directly instead of Wcs* functions that leak handles USE_REGISTRY = True # DISPLAY_DEVICE structure, StateFlags member # http://msdn.microsoft.com/en-us/library/dd183569%28v=vs.85%29.aspx -# wingdi.h # noqa: SC100 +# wingdi.h # Flags for parent devices DISPLAY_DEVICE_ATTACHED_TO_DESKTOP = 0x1 DISPLAY_DEVICE_MIRRORING_DRIVER = 0x8 -# Represents a pseudo device used to mirror application drawing for remoting or # noqa: SC100 +# Represents a pseudo device used to mirror application drawing for remoting or # other purposes. # An invisible pseudo monitor is associated with this device. # For example, NetMeeting uses it. @@ -83,17 +83,17 @@ # Flags for child devices DISPLAY_DEVICE_ACTIVE = 0x1 # DISPLAY_DEVICE_ACTIVE specifies whether a monitor is presented as being "on" -# by the respective GDI view. # noqa: SC100 +# by the respective GDI view. # Windows Vista: # EnumDisplayDevices will only enumerate monitors that can be presented as being "on." DISPLAY_DEVICE_ATTACHED = 0x2 -# MONITORINFO structure, dwFlags member # noqa: SC100 +# MONITORINFO structure, dwFlags member # https://msdn.microsoft.com/de-de/library/windows/desktop/dd145065(v=vs.85).aspx MONITORINFOF_PRIMARY = 0x1 -# Icm.h # noqa: SC100 +# Icm.h CLASS_MONITOR = struct.unpack("!L", b"mntr")[0] CLASS_PRINTER = struct.unpack("!L", b"prtr")[0] CLASS_SCANNER = struct.unpack("!L", b"scnr")[0] @@ -152,7 +152,7 @@ def calibration_management_isenabled(): bool: True if calibration is enabled, False otherwise. """ if sys.getwindowsversion() < (6, 1): - # Windows XP and Vista don't have calibration management # noqa: SC100 + # Windows XP and Vista don't have calibration management return False if False: # Using registry - NEVER @@ -244,7 +244,7 @@ def enable_per_user_profiles(enable=True, display_no=0, devicekey=None): profiles state. """ if sys.getwindowsversion() < (6,): - # Windows XP doesn't have per-user profiles # noqa: SC100 + # Windows XP doesn't have per-user profiles raise NotImplementedError( "Per-user profiles are only available in Windows Vista, 7 or later" ) @@ -260,7 +260,7 @@ def enable_per_user_profiles(enable=True, display_no=0, devicekey=None): ) else: # Using ctypes - this leaks registry key handles internally in - # WcsSetUsePerUserProfiles since Windows 10 1903 # noqa: SC100 + # WcsSetUsePerUserProfiles since Windows 10 1903 mscms = _get_mscms_windll() if not mscms: return False @@ -373,7 +373,7 @@ def get_display_device( Returns: DisplayDevice: The display device. """ - # The ordering will work as long as Argyll continues using EnumDisplayMonitors # noqa: SC100 + # The ordering will work as long as Argyll continues using EnumDisplayMonitors monitors = get_real_display_devices_info() moninfo = monitors[display_no] if use_active_display_device: @@ -406,7 +406,7 @@ def get_process_filename(pid, handle=0): if sys.getwindowsversion() >= (6,): dwSize = win32con.MAX_PATH while True: - dwFlags = 0 # The name should use the Win32 path format # noqa: SC100 + dwFlags = 0 # The name should use the Win32 path format lpdwSize = DWORD(dwSize) lpExeName = ctypes.create_unicode_buffer("", lpdwSize.value + 1) success = QueryFullProcessImageNameW( @@ -512,7 +512,7 @@ def get_real_display_devices_info(): Returns: list: List of monitor info. """ - # See Argyll source spectro/dispwin.c MonitorEnumProc, get_displays # noqa: SC100 + # See Argyll source spectro/dispwin.c MonitorEnumProc, get_displays monitors = [] for monitor in win32api.EnumDisplayMonitors(None, None): try: @@ -555,7 +555,7 @@ def per_user_profiles_isenabled(display_no=0, devicekey=None): WindowsError: If an error occurs while querying the registry. """ if sys.getwindowsversion() < (6,): - # Windows XP doesn't have per-user profiles # noqa: SC100 + # Windows XP doesn't have per-user profiles return False if not devicekey: device = get_display_device(display_no) @@ -572,7 +572,7 @@ def per_user_profiles_isenabled(display_no=0, devicekey=None): raise else: # Using ctypes - this leaks registry key handles internally in - # WcsGetUsePerUserProfiles since Windows 10 1903 # noqa: SC100 + # WcsGetUsePerUserProfiles since Windows 10 1903 mscms = _get_mscms_windll() pbool = ctypes.pointer(ctypes.c_bool()) if not mscms or not mscms.WcsGetUsePerUserProfiles( @@ -753,9 +753,9 @@ def __init__(self, bootstrap_icm32=False): self._icm32_handle = None UnloadableWinDLL.__init__(self, "mscms.dll") if bootstrap_icm32: - # Need to load & unload icm32 once before unloading of mscms # noqa: SC100 + # Need to load & unload icm32 once before unloading of mscms # can work in every situation - # (some calls to mscms methods pull in icm32, # noqa: SC100 + # (some calls to mscms methods pull in icm32, # if we haven't loaded/unloaded it before, we won't be able to unload then) self._icm32_handle = ctypes.WinDLL("icm32")._handle _free_library(self._icm32_handle) @@ -768,7 +768,7 @@ def load(self): mscms = self._windll if ( mscms - ): # Ensure mscms is not None # noqa: SC100 + ): # Ensure mscms is not None mscms.WcsGetDefaultColorProfileSize.restype = ctypes.c_bool mscms.WcsGetDefaultColorProfile.restype = ctypes.c_bool mscms.WcsAssociateColorProfileWithDevice.restype = ctypes.c_bool @@ -782,7 +782,7 @@ def unload(self): """ if self._windll: if self._icm32_handle: - # Need to free icm32 first, otherwise mscms won't unload # noqa: SC100 + # Need to free icm32 first, otherwise mscms won't unload try: _free_library(self._icm32_handle) except WindowsError as exception: diff --git a/tests/conftest.py b/tests/conftest.py index 2860f41d..2383e9cb 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -65,7 +65,7 @@ def argyll(): "linux": f"https://www.argyllcms.com/Argyll_V{argyll_version}_linux_x86_64_bin.tgz", } - # first look in to ~/local/bin/ArgyllCMS # noqa: SC100 + # first look in to ~/local/bin/ArgyllCMS home = pathlib.Path().home() argyll_search_paths = [ home / ".local" / "bin" / "Argyll" / "bin", @@ -83,7 +83,7 @@ def argyll(): yield argyll_path return - # apparently argyll has not been found # noqa: SC100 + # apparently argyll has not been found # download from source url = argyll_download_url[sys.platform] @@ -91,7 +91,7 @@ def argyll(): # store current working directory current_working_directory = os.getcwd() - # change dir to argyll temp path # noqa: SC100 + # change dir to argyll temp path os.chdir(argyll_temp_path) tar_file_name = "Argyll.tgz" diff --git a/tests/test_edid.py b/tests/test_edid.py index 817b2d99..fdda6cc2 100644 --- a/tests/test_edid.py +++ b/tests/test_edid.py @@ -97,29 +97,6 @@ def test_get_edid_1(clear_displays, monkeypatch, patch_subprocess, data_files): assert isinstance(result["year_of_manufacture"], int) -# def test_get_edid_3(clear_displays): -# """Testing DisplayCAL.colord.device_id_from_edid() function.""" -# config.initcfg() -# display = RDSMM.get_display(0) -# edid = display.get("edid") -# assert isinstance(edid, str) -# edid = edid.encode("utf-8") -# -# # assert len(edid) == 256 # noqa: SC100 -# assert edid == ( # noqa: SC100 -# b"\x00\xff\xff\xff\xff\xff\xff\x00\x10\xac\xe0@L405\x05\x1b\x01\x04\xb57\x1fx:U" # noqa: SC100 -# b"\xc5\xafO3\xb8%\x0bPT\xa5K\x00qO\xa9@\x81\x80\xd1\xc0\x01\x01\x01\x01\x01\x01" # noqa: SC100 -# b"\x01\x01V^\x00\xa0\xa0\xa0)P0 5\x00)7!\x00\x00\x1a\x00\x00\x00\xff\x00" # noqa: SC100 -# b"TYPR371U504L\n\x00\x00\x00\xfc\x00DELL UP2516D\n\x00\x00\x00\xfd\x002K\x1eX" # noqa: SC100,B950 -# b"\x19\x01\n \x01,\x02\x03\x1c\xf1O\x90\x05\x04\x03\x02\x07\x16\x01\x06" # noqa: SC100,B950 -# b"\x11\x12\x15\x13\x14\x1f#\t\x1f\x07\x83\x01\x00\x00\x02:\x80\x18q8-@X,E" # noqa: SC100 -# b"\x00)7!\x00\x00\x1e~9\x00\xa0\x808\x1f@0 :\x00)7!\x00\x00\x1a\x01\x1d\x00rQ" # noqa: SC100,B950 -# b"\xd0\x1e n(U\x00)7!\x00\x00\x1e\xbf\x16\x00\xa0\x808\x13@0 :\x00)7!\x00\x00" # noqa: SC100,B950 -# b"\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" # noqa: SC100 -# b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86" # noqa: SC100 -# ) - - @pytest.mark.parametrize( "xrandr_data_file_name,dispwin_data_file_name,getcfg_displays_output,display_no,expected_result", [