# -*- coding: utf-8 -*-
"""
:Purpose: This module provides a simple interface to the Windows
registry. It contains a :class:`~Registry` class that can
be used to interact with the registry; and is supported by
the :class:`~Key` and :class:`~Value` classes.
This module also provides the following objects that can be
used to directly access the registry methods for each root
HKEY.
- hkcr = HKEY_CLASSES_ROOT
- hkcu = HKEY_CURRENT_USER
- hklm = HKEY_LOCAL_MACHINE
- hkus = HKEY_USERS
- hkcc = HKEY_CURRENT_CONFIG
:Platform: Windows | Python 3.7+
:Developer: M Critchard
:Email: support@s3dev.uk
:Example: For a use example, refer to the :class:`~Registry` docstring.
"""
# For Linux linting:
# pylint: disable=import-error # import winreg
# pylint: disable=possibly-used-before-assignment # import winreg
# pylint: disable=undefined-variable # WindowsError
# --
try:
import utils
from reporterror import reporterror
from user_interface import ui
except ImportError:
from utils4 import utils
from utils4.reporterror import reporterror
from utils4.user_interface import ui
_OS = utils.get_os()
# Test OS before importing winreg.
if 'win' in _OS:
import winreg as wr
else:
ui.print_alert(f'\nYour operating system ({_OS}) is not compatible with this module.')
[docs]
class Value:
"""This class encapsulates the Windows registry values.
It provides the following attributes to mimic the attributes of a value
in the registry:
- :attr:`~name`
- :attr:`~type`
- :attr:`~data`
"""
# pylint: disable=too-few-public-methods
[docs]
def __init__(self, name: str, regtype, data):
"""Set the name, type and data attributes."""
self.name = name
self.type = regtype
self.data = data
[docs]
class Key:
"""This class encapsulates the Windows registry keys.
It provides methods that can be used to interact with the values
of the key.
"""
[docs]
def __init__(self, key):
"""Initialise a private self._key attribute.
This attribute is used throughout the class to provide a set
of key specific functions.
"""
self._key = key
[docs]
def get_value(self, name):
"""Get the key value specified by name.
Args:
name (str): Name of the registry key.
Returns:
If the value exists, a value object is returned, otherwise
``None`` is returned.
"""
try:
data, regtype = wr.QueryValueEx(self._key, name)
value = Value(name, regtype, data)
return value
except WindowsError:
return None
[docs]
def set_data(self, name: str, data: str):
"""Set the data of the key value specified by name.
Args:
name (str): Name of the registry key.
data (str): Data to store into the key.
Note:
Currently, only strings or unicode values are supported.
"""
try:
if isinstance(data, str):
wr.SetValueEx(self._key, name, 0, wr.REG_SZ, data)
else:
raise NotImplementedError
except NotImplementedError as err1:
reporterror(err1)
except WindowsError as err2:
reporterror(err2)
[docs]
class Registry:
r"""This class encapsulates the Windows registry.
It provides methods that can be used to interact with the keys and
values in the registry.
:Example:
Example of how to get the value of a registry key::
>>> from utils4 import registry
>>> hkcu = registry.hkcu
>>> my_value = hkcu.get_value('control panel\desktop', 'wallpaper')
>>> my_wallpaper = my_value.data
"""
[docs]
def __init__(self, hkey):
"""Initialise a private self._hkey attribute.
This attribute is used throughout the class to provide a set
of hkey specific functions.
"""
self._hkey = hkey
[docs]
def get_value(self, path: str, name: str):
"""Get the key value specified by the path and name
Args:
path (str): Path to the registry key.
name (str): Name of the registry key.
Returns:
If the value exists, a value object is returned, otherwise
``None`` is returned.
"""
key = self._open_key(path, wr.KEY_READ)
value = key.get_value(name)
return value
[docs]
def set_data(self, path: str, name: str, data: str):
"""Set the data of the key value specified by the path and name.
Args:
path (str): Path to the registry key.
name (str): Name of the registry key.
data (str): Data to store into the key.
:Design:
If the value doesn't exist, this method creates it and sets
its type and data accordingly. A check is performed to
determine if the operation has been completed successfully.
If it hasn't the user is notified.
Returns:
The value of the registry key.
"""
key = self._open_key(path, wr.KEY_SET_VALUE)
key.set_data(name, data)
key = self._open_key(path, wr.KEY_READ)
value = key.get_value(name)
if (value is None) or (value.data != data):
ui.print_error_unexpected()
return value
[docs]
def create_key(self, path: str):
"""Create the key specified by the path.
Args:
path (str): Path to the registry key.
:Design:
If a creation error occurs, the user is notified.
Returns:
If created successfully, a ``winreg.CreateKey`` object is
returned, otherwise ``None`` is returned.
"""
try:
return wr.CreateKey(self._hkey, path)
except WindowsError as err:
reporterror(err)
return None
[docs]
def delete_key(self, path: str):
"""Delete the key specified by the path.
Args:
path (str): Path to the registry key.
Note:
**All of the values under the key are also deleted** but
subkeys cannot be deleted with this method. The user is
notified if an error occurs.
Returns:
If deleted successfully, a ``winreg.DeleteKey`` object is
returned, otherwise ``None`` is returned.
"""
try:
return wr.DeleteKey(self._hkey, path)
except WindowsError as err:
reporterror(err)
return None
[docs]
def _open_key(self, path: str, sam):
"""Open and return the key specified by the path.
Args:
path (str): Path to the registry key.
sam: The SAM privilege level used to open the key.
:Design:
The key is opened with privilege level defined by ``sam``.
The user is notified if an error occurs.
Returns:
If opened successfully, a ``winreg.OpenKey`` object is
returned, otherwise ``None`` is returned.
"""
try:
key = wr.OpenKey(self._hkey, path, 0, sam)
key = Key(key)
return key
except WindowsError as err:
reporterror(err)
return None
# Test IS before shortcutting.
if 'win' in _OS:
# Shortcut class instances for outside access.
hkcr = Registry(wr.HKEY_CLASSES_ROOT)
hkcu = Registry(wr.HKEY_CURRENT_USER)
hklm = Registry(wr.HKEY_LOCAL_MACHINE)
hkus = Registry(wr.HKEY_USERS)
hkcc = Registry(wr.HKEY_CURRENT_CONFIG)