wakepy

repository·main·Indexed 42 days ago

https://github.com/wakepy/wakepy

A cross-platform Python package and CLI tool to keep a system awake. It provides mechanisms to inhibit system sleep (keep.running) or both system sleep and screen lock (keep.presenting) using native OS APIs across macOS, Linux, and Windows.

Tokens
20.4K
Snippets
81
Records
105
Agent score
51%

What's inside wakepy

  1. What is Post-exit Inhibit behavior?

    main

    Some inhibitors include a Post-exit Inhibit period. This means that after the wakepy mode is deactivated, an additional inhibitor flag is held for a specific duration.

    Crucially, this post-exit flag is Non-Resetting: it does not touch or reset the idle timer; it simply suppresses the suspend action for a short window. This causes the idle action to trigger later than it would have at the exact moment of mode deactivation. *Example: SetThreadExecutionState on Windows 10.

  2. What are wakepy Methods?

    main

    In wakepy, Methods are the underlying mechanisms used to enter or maintain a specific Mode (such as keep.running or keep.presenting).

    Each Method is designed to support specific platforms and may have software requirements (like D-Bus or specific Desktop Environments). A single Mode can be achieved through multiple different Methods depending on the operating system and environment.

    Mode Legend

    • ⌛: keep.running mode (prevents system sleep/suspend)
    • 🖥️: keep.presenting mode (prevents display sleep/idle)

    Method Availability by Mode

    MethodModes
    caffeinate⌛ 🖥️
    org.freedesktop.PowerManagement⌛
    org.freedesktop.ScreenSaver🖥️
    org.gnome.SessionManager⌛ 🖥️
    SetThreadExecutionState⌛ 🖥️
  3. How Wakepy selects and prioritizes Methods

    main

    When a wakepy.Mode instance is created, it follows a specific selection process to determine which system Methods (like org.gnome.SessionManager or SetThreadExecutionState) will be used to keep the system awake:

    1. Selection: Methods are filtered based on the methods or omit arguments provided during initialization.
    2. Fake Success Injection: If the WAKEPY_FAKE_SUCCESS environment variable is truthy, a WakepyFakeSuccess method is inserted at the start of the list (useful for testing).
    3. Prioritization: The list is reordered based on the methods_priority argument.
    4. Platform Filtering: Methods incompatible with the current operating system are removed.
    5. Activation: Wakepy attempts to activate the remaining methods in priority order. It stops at the first method that successfully activates.
  4. Extend wakepy with custom DBus adapters

    main

    For advanced users, wakepy allows the use of custom D-Bus adapters. This is useful if you want to use a different Python D-Bus library instead of the default jeepney.

    To implement a custom adapter, you should inherit from wakepy.DBusAdapter. The system uses these adapters to communicate with system services via the D-Bus protocol to manage power states.

  5. Understand how inhibitors and idle timers work

    main

    Wakepy works by using inhibitors to prevent a system's idle timer from reaching its timeout. An idle timer is reset to zero by user interaction (mouse/keyboard). Once the timer reaches its limit, the system performs a suspend action (like sleeping or turning off the display).

    An inhibitor prevents this action in one of two ways:

    1. Resetting the timer: Periodically restarting the timer or freezing it at zero.
    2. Suppressing the action: Allowing the timer to run, but using a flag to suppress the suspend action even when the timeout is reached.

    Note that system sleep and display timeouts use separate timers and may have different limits.

  6. Control Wakepy behavior in CI and tests with environment variables

    main

    CI environments often lack the Desktop Environments or system services (like D-Bus) that Wakepy requires. To ensure consistent test behavior, Wakepy provides two environment variables to control mode activation:

    1. WAKEPY_FAKE_SUCCESS: Forces all modes to succeed by inserting a WakepyFakeSuccess method as the highest priority. This prevents any real I/O, executable calls, or 3rd party service calls. Use this for standard unit tests and CI.
    2. WAKEPY_FORCE_FAILURE: Forces all mode activations to fail. Use this to test your application's error handling when Wakepy cannot prevent sleep or screen locking.

    Precedence: If both are set to truthy values, WAKEPY_FORCE_FAILURE takes precedence and activation will fail.

    # Example: Forcing success in a shell environment
    export WAKEPY_FAKE_SUCCESS=yes
    
    # Example: Forcing failure in a shell environment
    export WAKEPY_FORCE_FAILURE=1
  7. Difference between Resetting and Non-Resetting IdleTimerResetTypes

    main

    Wakepy methods are categorized by how they affect the system's idle timer upon deactivation:

    Resetting

    When a method of this type exits, the idle timer starts from zero. The system will wait for a full timeout period starting from the moment the wakepy mode ends. *Example: org.gnome.SessionManager on GNOME.

    Non-Resetting

    When a method of this type exits, the idle timer continues to increase. Because the timer was already running during the wakepy session, the system may trigger a suspend action almost immediately after the mode is deactivated. *Example: SetThreadExecutionState on Windows.

  8. Understand Wakepy Modes

    main

    Wakepy uses 'Modes' to inhibit system sleep/suspend. When a mode is activated, it prevents the system from automatically entering sleep based on idle timers. You can choose between two primary modes depending on whether you need the screen to remain visible or if you only need the CPU to keep running.

    ModePrevents SleepPrevents ScreenlockPrevents Screensaver
    keep.runningYesNo*No
    keep.presentingYesYesYes

    *On Windows, screenlock prevention depends on whether ScreenSaverIsSecure is set or enforced via Group Policy (GPO).

    Important Note: Wakepy only prevents automatic idle-timer-based actions. It does not prevent manual actions like selecting 'Sleep' from a menu, closing a laptop lid, pressing a power button, or manually triggering a screensaver/lockscreen.

  9. Understand the Wakepy Mode lifecycle

    main

    A wakepy.Mode transitions through several states:

    1. Inactive: The state after the Mode instance is created but before it is activated.
    2. Activation: The process of trying Methods in priority order. This involves checking requirements (Method.caniuse()), calling Method.enter_mode(), and optionally starting a heartbeat().
    3. Active / Activation Failed: Once activation is attempted, the mode is either Active (if a method succeeded) or in Activation Failed state (if no methods could be used). Your USER_CODE runs in this state.
    4. Deactivation: Triggered automatically when exiting a with block or when a decorated function returns. This calls Method.exit_mode() and stops any active heartbeat() threads.
  10. How wakepy modes work

    main

    Wakepy provides two primary modes for controlling system wakefulness:

    1. keep.running (⌛): Designed for long-running background tasks (e.g., ML training, video encoding). It inhibits automatic timer-based sleep or suspend actions but allows the screen to lock, the screensaver to start, and the monitor to turn off.

    2. keep.presenting (🖥️): Designed for tasks that require visual continuity (e.g., dashboards, video playback). It inhibits both system sleep and screen lock/screensaver/monitor turn-off.

  11. Multithreading and multiprocessing safety in Wakepy

    main

    Wakepy is designed to be multiprocessing and multithreading safe. Every Wakepy method is safe by default because Wakepy does not alter settings in a way that prevents multiple Mode instances (inhibitors) from being active simultaneously.

    Key Safety Rules

    • Safe: Using Wakepy factory functions (like decorators or context managers) within multiple threads. Each call creates its own internal Mode instance.
    • Unsafe: Sharing a single Mode instance (the object returned by keep.running() or keep.presenting()) across different threads.
    • Thread-safe alternative: If you need to access the current mode within a thread, use wakepy.current_mode instead of passing a shared instance.
  12. What are Modes and Methods in wakepy?

    main

    wakepy uses two core abstractions to manage system sleep states:

    1. Modes: These represent the desired state of the system (e.g., keep.running or keep.presenting).
    2. Methods: These are the underlying OS-specific implementations used to achieve a Mode.

    A single Mode is implemented by multiple Methods depending on your operating system, Desktop Environment, and version. For example, the keep.presenting mode might use org.gnome.SessionManager on Linux/GNOME, SetThreadExecutionState on Windows, or caffeinate on macOS. wakepy provides a unified API so you don't have to manage these platform-specific details manually.