thatsIch/sublime-rainmeter

View on GitHub
path/program_path_provider.py

Summary

Maintainability
A
0 mins
Test Coverage
"""
This module is about path resolving for the program path.

This is required to execute Rainmeter.exe for example to refresh the current skin.
"""

import os
from functools import lru_cache
import winreg

import sublime

from .. import logger


def get_rm_path_from_default_path():
    r"""
    Default location is "C:\Program Files\Rainmeter" in windows.

    We can get "C:\Program Files" through the environmental variables
    %PROGRAMFILES%
    """
    programfiles = os.getenv("PROGRAMFILES")
    rainmeterpath = os.path.join(programfiles, "Rainmeter")

    return rainmeterpath


def _get_rainmeter_registry_key():
    r"""
    Throw FileNotFoundException if Software\WOW6432Node\Rainmeter does not exist.

    not much we can do to handle that
    """
    return winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\WOW6432Node\\Rainmeter")


def get_rm_path_from_registry():
    """Registry."""
    rainmeter_key = _get_rainmeter_registry_key()
    rainmeter_path = winreg.QueryValue(rainmeter_key, None)

    return rainmeter_path


def _executable_exists(rm_path):
    """Check if Rainmeter executable exists."""
    # normalize path
    rainmeter_exe = os.path.join(rm_path, "Rainmeter.exe")
    if not os.path.exists(rainmeter_exe):
        message = """Rainmeter path was found, but no Rainmeter.exe found.
                     Check if you have installed Rainmeter correctly."""
        logger.error(message)
        sublime.error_message(message)
        return False

    return True


@lru_cache(maxsize=None)
def get_cached_program_path():
    """Try to retrieve the program path of RM through magic.

    Possible options are:

    * It is given through settings
    * It is in the default installation path
    * It is registered in the registry
    * Ask the user for the path
    """
    # Load setting
    settings = sublime.load_settings("Rainmeter.sublime-settings")
    rm_path = settings.get("rainmeter_path", None)

    # If setting is not set, try default location
    if not rm_path:
        logger.info("rainmeter_path not found in settings. Trying default location.")
        rm_path = get_rm_path_from_default_path()

    # if it is not even specified by default,
    # try using the registry to retrieve the installation path
    if not os.path.isdir(rm_path):
        rm_path = get_rm_path_from_registry()

    # Check if path exists and contains Rainmeter.exe
    if not os.path.isdir(rm_path):
        message = """Path to Rainmeter.exe could neither be found:

                     * in the settings,
                     * in the standard directory,
                     * nor via registry.

                     Check your \"rainmeter_path\" setting."""
        logger.info(message)
        return

    if not _executable_exists(rm_path):
        return

    logger.info("Rainmeter found in " + rm_path)
    return rm_path + "\\"