Browse Source

suggest udev rules when permissions are insufficient to set backlight's brightness

Fabian Peter Hammerle 1 year ago
parent
commit
b2cee8c8fa
3 changed files with 52 additions and 1 deletions
  1. 15 0
      CHANGELOG.md
  2. 14 1
      acpi_backlight/__init__.py
  3. 23 0
      tests/test_backlight.py

+ 15 - 0
CHANGELOG.md

@@ -0,0 +1,15 @@
+# Changelog
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [Unreleased]
+### Added
+- suggest udev rules when permissions are insufficient to set backlight's brightness
+
+TODO document commits before 2022-06-16
+
+[Unreleased]: https://github.com/fphammerle/acpi-backlight/compare/0.2.0...HEAD
+[0.2.0]: https://github.com/fphammerle/acpi-backlight/compare/0.1.0...0.2.0
+[0.1.0]: https://github.com/fphammerle/acpi-backlight/releases/tag/0.1.0

+ 14 - 1
acpi_backlight/__init__.py

@@ -11,6 +11,7 @@ class Backlight:
     # pylint: disable=too-few-public-methods; does not count properties
 
     def __init__(self, name: str = "intel_backlight"):
+        self._device_name = name
         self._acpi_dir_path = _ACPI_BACKLIGHT_ROOT_DIR_PATH.joinpath(name)
 
     @property
@@ -27,7 +28,19 @@ class Backlight:
 
     @_brightness_absolute.setter
     def _brightness_absolute(self, brightness_absolute: int):
-        self._brightness_path.write_text(str(brightness_absolute), encoding="ascii")
+        try:
+            self._brightness_path.write_text(str(brightness_absolute), encoding="ascii")
+        except PermissionError as exc:
+            raise PermissionError(
+                "Insufficient permissions to set brightness of backlight."
+                "\nConsider adding the following udev rules:"
+                f'\nACTION=="add", SUBSYSTEM=="backlight"'
+                f', KERNEL=="{self._device_name}"'
+                f', RUN+="/bin/chgrp video /sys$devpath/brightness"'
+                f'\nACTION=="add", SUBSYSTEM=="backlight"'
+                f', KERNEL=="{self._device_name}"'
+                f', RUN+="/bin/chmod g+w /sys$devpath/brightness"'
+            ) from exc
 
     @property
     def _max_brightness_absolute(self) -> int:

+ 23 - 0
tests/test_backlight.py

@@ -1,5 +1,6 @@
 import pathlib
 import unittest.mock
+import re
 
 import pytest
 
@@ -20,6 +21,28 @@ def test_init(name):
     assert backlight._acpi_dir_path.as_posix() == "/sys/class/backlight/" + name
 
 
+def test__brightness_absolute_set_permission_denied() -> None:
+    backlight = Backlight()
+    with unittest.mock.patch(
+        "pathlib.Path.open",
+        side_effect=PermissionError(
+            "[Errno 13] Permission denied:"
+            " '/sys/class/backlight/intel_backlight/brightness'"
+        ),
+    ), pytest.raises(
+        PermissionError,
+        match=re.escape(
+            "Insufficient permissions to set brightness of backlight."
+            "\nConsider adding the following udev rules:"
+            '\nACTION=="add", SUBSYSTEM=="backlight", KERNEL=="intel_backlight"'
+            ', RUN+="/bin/chgrp video /sys$devpath/brightness"'
+            '\nACTION=="add", SUBSYSTEM=="backlight", KERNEL=="intel_backlight"'
+            ', RUN+="/bin/chmod g+w /sys$devpath/brightness"'
+        ),
+    ):
+        backlight._brightness_absolute = 42
+
+
 @pytest.mark.parametrize(
     ("max_brightness", "brightness_absolute_str", "expected_brightness_relative"),
     (