A fake Windows registry for testing registry-related code on non-Windows platforms
Project description
fake_winreg
Table of Contents
- Why fake_winreg?
- Overview
- Installation
- Configuration
- Quick Start
- API Reference
- CLI Usage
- Development
- License
Why fake_winreg?
Python's winreg module is
only available on Windows. If your code reads or writes the Windows registry,
you can't test it on Linux or macOS - and you can't run it in CI on
Ubuntu runners.
fake_winreg solves this by providing a complete fake
registry that works everywhere Python runs. Just replace import winreg
with import fake_winreg as winreg and your tests work on any platform.
Test your code before it hits the real registry!
You can also export real registry data from Windows via regedit.exe as a
.reg file, import it into a SQLite database with fake-winreg convert if=exported.reg of=registry.db, and run your tests against real-world data.
Overview
fake_winreg provides a drop-in replacement for Python's built-in
winreg module, enabling testing of Windows registry-dependent code on
Linux and macOS without a Windows environment.
Key capabilities:
- All 20
winregAPI functions (OpenKey,SetValueEx,EnumKey, etc.) with matching signatures and error behavior - Three storage backends: in-memory (default), SQLite (for large registries), JSON (for fixtures)
- Import and export of Windows
.regfiles (Version 5.00 and REGEDIT4 formats) - CLI commands for querying and modifying persistent SQLite registries (
fake-winreg reg) - Streaming format conversion between
.db,.json, and.regvia CLI or Python API - Pre-built test registries mimicking Windows 10, Windows 11 23H2, and Wine environments
- Positional-only parameter enforcement matching real
winregbehavior - Clean Architecture with
import-linterenforcement, pyright strict mode, high test coverage
Installation
Recommended: uv (fast, isolated)
# install uv if needed
curl -LsSf https://astral.sh/uv/install.sh | sh
# one-shot run without installing
uvx fake_winreg@latest info
# persistent install as CLI tool
uv tool install fake_winreg
# install as project dependency
uv pip install fake_winreg
Via pip
pip install fake_winreg
From source
pip install "git+https://github.com/bitranox/fake_winreg"
See INSTALL.md for all options (pipx, Poetry, PDM, system packages).
Configuration
See CONFIG.md for detailed documentation on the layered configuration system, including precedence rules, profile support, and customization best practices.
Quick Start
# Install
uv tool install fake_winreg
# Verify
fake-winreg --version
# Deploy config files
fake-winreg config-deploy --target user
# Export demo registries (Windows 10, 11, Wine) as .json, .reg, .db
fake-winreg export-demo-registries
# Query a persistent registry
fake-winreg reg --db windows11.db list-keys HKEY_LOCAL_MACHINE\SOFTWARE
fake-winreg reg --db windows11.db get HKEY_LOCAL_MACHINE\SOFTWARE\...\CurrentVersion CurrentBuild
# Convert between formats
fake-winreg convert if=windows11.db of=export.reg
# Show package info
fake-winreg info
Python API
import fake_winreg as winreg
# Load a pre-built Windows 10-like test registry
fake_registry = winreg.fake_reg_tools.get_minimal_windows_testregistry()
winreg.load_fake_registry(fake_registry)
# Use exactly like the real winreg module
reg = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
key = winreg.OpenKey(reg, r"SOFTWARE\Microsoft\Windows NT\CurrentVersion")
value, value_type = winreg.QueryValueEx(key, "CurrentBuild")
API Reference
All functions mirror the signatures and behavior of Python's built-in winreg module.
Registry Functions
Connection
ConnectRegistry(computer_name: str | None, key: Handle, /) -> PyHKEY
Establish a connection to a predefined registry handle. Pass None for computer_name to connect to the local (fake) registry.
Key Operations
CreateKey(key: Handle, sub_key: str | None, /) -> PyHKEY
Create or open a registry key, returning a handle.
CreateKeyEx(key: Handle, sub_key: str, reserved: int = 0, access: int = KEY_WRITE, /) -> PyHKEY
Create or open a registry key with explicit access control.
OpenKey(key: Handle, sub_key: str | None, reserved: int = 0, access: int = KEY_READ) -> PyHKEY
Open an existing registry key. Does not create the key if it does not exist.
OpenKeyEx(key: Handle, sub_key: str | None, reserved: int = 0, access: int = KEY_READ) -> PyHKEY
Open an existing registry key with explicit access. Equivalent to OpenKey.
DeleteKey(key: Handle, sub_key: str, /) -> None
Delete a registry key. The key must have no subkeys.
DeleteKeyEx(key: Handle, sub_key: str, access: int = KEY_WOW64_64KEY, reserved: int = 0, /) -> None
Delete a registry key (64-bit variant).
CloseKey(hkey: int | HKEYType, /) -> None
Close a previously opened registry key.
FlushKey(key: Handle, /) -> None
Write all attributes of a key to the registry. No-op in the fake implementation since data is already in memory.
Value Operations
SetValue(key: Handle, sub_key: str | None, type: int, value: str, /) -> None
Set the default (unnamed) value of a key. Only REG_SZ is accepted for type.
SetValueEx(key: Handle, value_name: str | None, reserved: int, type: int, value: RegData, /) -> None
Store data in a named value of an open registry key. Supports all registry value types.
QueryValue(key: Handle, sub_key: str | None, /) -> str
Retrieve the default (unnamed) value of a key as a string.
QueryValueEx(key: Handle, value_name: str | None, /) -> tuple[RegData, int]
Retrieve value data and its type code for a named value. Returns (data, type).
DeleteValue(key: Handle, value: str | None, /) -> None
Remove a named value from a registry key.
Enumeration
EnumKey(key: Handle, index: int, /) -> str
Enumerate subkeys of an open key by zero-based index. Raises OSError when index exceeds the number of subkeys.
EnumValue(key: Handle, index: int, /) -> tuple[str, RegData, int]
Enumerate values of an open key by zero-based index. Returns (name, data, type). Raises OSError when index exceeds the number of values.
QueryInfoKey(key: Handle, /) -> tuple[int, int, int]
Return information about a key: (num_subkeys, num_values, last_modified_timestamp).
Utility
ExpandEnvironmentStrings(string: str, /) -> str
Expand %VAR%-style environment variable references in a string. Works on all platforms.
DisableReflectionKey(key: Handle, /) -> None
EnableReflectionKey(key: Handle, /) -> None
QueryReflectionKey(key: Handle, /) -> bool
Registry reflection stubs. No-op in the fake implementation; QueryReflectionKey always returns True.
Backend Management
fake_winreg supports multiple storage backends. The default is an in-memory backend.
import fake_winreg as winreg
# Default: in-memory (created automatically if no backend is set)
winreg.use_backend(winreg.InMemoryBackend())
# SQLite: for large registries or persistent storage
winreg.use_backend(winreg.SqliteBackend("/path/to/registry.db"))
# JSON: load from a JSON file, work in memory
winreg.use_backend(winreg.JsonBackend("/path/to/registry.json"))
# Backward-compatible: load a FakeRegistry object directly
fake_registry = winreg.fake_reg_tools.get_minimal_windows_testregistry()
winreg.load_fake_registry(fake_registry)
Import/Export
Exchange registry data between formats. All exports produce deterministic, alphabetically sorted output — keys and values are ordered by name regardless of which backend is active.
import fake_winreg as winreg
# JSON format (always UTF-8, per RFC 8259)
winreg.export_json("/path/to/snapshot.json")
winreg.import_json("/path/to/fixture.json")
# Windows .reg format (Version 5.00, UTF-16 LE with BOM by default)
winreg.export_reg("/path/to/export.reg")
winreg.import_reg("/path/to/import.reg")
# REGEDIT4 format (legacy, ANSI encoding)
winreg.export_reg("/path/to/export.reg", version=4)
# Override encoding for human-readable .reg files
winreg.export_reg("/path/to/export.reg", encoding="utf-8")
# Convert between formats (streaming, memory-efficient for large registries)
winreg.convert_registry("source.db", "target.reg")
winreg.convert_registry("source.reg", "target.json")
Character Encoding
| Format | Default Encoding | Notes |
|---|---|---|
.json |
UTF-8 | Per RFC 8259. Binary values are base64-encoded. |
.reg export (v5) |
UTF-16 LE with BOM | Default. Matches Windows regedit.exe. Override with encoding="utf-8". |
.reg export (v4) |
ASCII | export_reg(path, version=4). Legacy REGEDIT4 format, no Unicode. |
.reg import |
Auto-detected | UTF-16 LE if BOM (FF FE) present, otherwise UTF-8. Both v4 and v5 supported. |
.db (SQLite) |
N/A | Binary format. String values stored as SQLite TEXT (UTF-8 internally). |
The Windows registry stores all strings as UTF-16 LE internally. Values encoded as
hex(2): (REG_EXPAND_SZ) and hex(7): (REG_MULTI_SZ) in .reg files use UTF-16 LE
byte sequences regardless of the file encoding.
Constants
All constants from the winreg module are available.
Hive keys:
| Constant | Description |
|---|---|
HKEY_CLASSES_ROOT |
Registry entries for file associations and COM |
HKEY_CURRENT_USER |
Settings for the current user |
HKEY_LOCAL_MACHINE |
System-wide settings |
HKEY_USERS |
Settings for all user profiles |
HKEY_CURRENT_CONFIG |
Current hardware profile |
HKEY_PERFORMANCE_DATA |
Performance counters |
HKEY_DYN_DATA |
Dynamic data (Windows 95/98) |
Value types:
| Constant | Description |
|---|---|
REG_NONE |
No defined value type |
REG_SZ |
Null-terminated string |
REG_EXPAND_SZ |
String with unexpanded environment variable refs |
REG_BINARY |
Binary data |
REG_DWORD |
32-bit integer (little-endian) |
REG_DWORD_BIG_ENDIAN |
32-bit integer (big-endian) |
REG_LINK |
Symbolic link (Unicode) |
REG_MULTI_SZ |
Array of null-terminated strings |
REG_QWORD |
64-bit integer (little-endian) |
REG_RESOURCE_LIST |
Device driver resource list |
REG_FULL_RESOURCE_DESCRIPTOR |
Hardware resource descriptor |
REG_RESOURCE_REQUIREMENTS_LIST |
Hardware resource requirements |
Access rights:
| Constant | Description |
|---|---|
KEY_READ |
Read access |
KEY_WRITE |
Write access |
KEY_ALL_ACCESS |
Full access |
KEY_EXECUTE |
Execute access (same as KEY_READ) |
KEY_QUERY_VALUE |
Query subkey values |
KEY_SET_VALUE |
Set subkey values |
KEY_CREATE_SUB_KEY |
Create subkeys |
KEY_ENUMERATE_SUB_KEYS |
Enumerate subkeys |
KEY_NOTIFY |
Change notification |
KEY_CREATE_LINK |
Create symbolic link |
KEY_WOW64_64KEY |
Access 64-bit registry view |
KEY_WOW64_32KEY |
Access 32-bit registry view |
Data Types
# All possible types of data that registry values can hold
RegData = None | bytes | int | str | list[str]
# Handle types accepted by all API functions
Handle = int | HKEYType | PyHKEY
# Registry data structures
FakeRegistry # Top-level registry container (holds hive roots)
FakeRegistryKey # A single registry key with subkeys and values
FakeRegistryValue # A named value with data and type code
PyHKEY supports the context manager protocol:
with winreg.OpenKey(reg, r"SOFTWARE\Microsoft") as key:
value, vtype = winreg.QueryValueEx(key, "SomeName")
Test Registries
Pre-built registry fixtures for common test scenarios. See docs/registry_values.md for a detailed reference of all registry values, version detection logic, and branch codenames.
import fake_winreg as winreg
# Windows 10 (build 18363)
reg = winreg.fake_reg_tools.get_minimal_windows_testregistry()
# Windows 11 23H2 Pro (build 22631)
reg = winreg.fake_reg_tools.get_minimal_windows11_testregistry()
# Wine environment (build 7601)
reg = winreg.fake_reg_tools.get_minimal_wine_testregistry()
CLI Usage
# Query a persistent SQLite registry
fake-winreg reg --db registry.db list-keys HKEY_LOCAL_MACHINE\SOFTWARE
fake-winreg reg --db registry.db list-values HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft
fake-winreg reg --db registry.db get HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\...\CurrentVersion CurrentBuild
fake-winreg reg --db registry.db info HKEY_LOCAL_MACHINE\SOFTWARE
# Modify a persistent registry
fake-winreg reg --db registry.db create-key HKEY_LOCAL_MACHINE\SOFTWARE\MyApp
fake-winreg reg --db registry.db set HKEY_LOCAL_MACHINE\SOFTWARE\MyApp Name "hello"
fake-winreg reg --db registry.db set HKEY_LOCAL_MACHINE\SOFTWARE\MyApp Count 42 --type REG_DWORD
fake-winreg reg --db registry.db delete-value HKEY_LOCAL_MACHINE\SOFTWARE\MyApp Name
fake-winreg reg --db registry.db delete-key HKEY_LOCAL_MACHINE\SOFTWARE\MyApp
# Convert between registry formats
fake-winreg convert if=registry.db of=export.reg
fake-winreg convert if=export.reg of=registry.json
# Export demo registries (Windows 10 + 11 + Wine) as .json, .reg, .db
fake-winreg export-demo-registries
# Show package information
fake-winreg info
The --db option can be replaced by configuring registry.db_path via TOML config,
.env file (REGISTRY__DB_PATH=/path/to/db), or environment variable
(FAKE_WINREG___REGISTRY__DB_PATH=/path/to/db).
Development
Run the full test suite (lint, type-check, tests with coverage):
make test
See DEVELOPMENT.md for the complete development setup guide.
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fake_winreg-1.8.1.tar.gz.
File metadata
- Download URL: fake_winreg-1.8.1.tar.gz
- Upload date:
- Size: 143.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c9a513e160025498d0737bec5b11dbe554d4643cec2fb3af2e05f9f5a8012bb8
|
|
| MD5 |
22b78105fd1eecf7effab4703177feda
|
|
| BLAKE2b-256 |
c6077bb9fd8b5ee5a8a0482a6fc6d1a086575869981221ba7c5ffc1fb31d4c8b
|
File details
Details for the file fake_winreg-1.8.1-py3-none-any.whl.
File metadata
- Download URL: fake_winreg-1.8.1-py3-none-any.whl
- Upload date:
- Size: 91.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b8df71f59231e7841ce3e49c25d179caa804ac686f5f4b94908adb550ab8e713
|
|
| MD5 |
7d8a2dfa7c57e1bfbac1ce327d2a8a81
|
|
| BLAKE2b-256 |
996b729195d7e4c1ab47763475db22aab028ef926e80ade7b05fcac635320f8b
|