Skip to main content

A fake Windows registry for testing registry-related code on non-Windows platforms

Project description

fake_winreg

CI CodeQL License: MIT Open in Codespaces PyPI PyPI - Downloads Code Style: Ruff codecov Maintainability Known Vulnerabilities security: bandit

Table of Contents

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, or to test software without hitting a real registry on Windows.

Key capabilities:

  • All 22 winreg API functions (OpenKey, SetValueEx, EnumKey, SaveKey, LoadKey, 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 .reg files (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 .reg via CLI or Python API
  • Pre-built test registries mimicking Windows 10, Windows 11 23H2, and Wine environments
  • Positional-only parameter enforcement matching real winreg behavior
  • Clean Architecture with import-linter enforcement, 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.

Save / Load

SaveKey(key: Handle, file_name: str, /) -> None

Save a registry key and all its subkeys/values to a JSON file. On real Windows this writes a binary hive file; the fake implementation serialises the subtree as JSON so that LoadKey can restore it.

LoadKey(key: Handle, sub_key: str, file_name: str, /) -> None

Load registry data from a JSON file (produced by SaveKey) into a subkey. On real Windows this loads a binary hive file; the fake implementation reads the JSON and grafts the subtree under sub_key of key.

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

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fake_winreg-1.9.0.tar.gz (149.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fake_winreg-1.9.0-py3-none-any.whl (92.0 kB view details)

Uploaded Python 3

File details

Details for the file fake_winreg-1.9.0.tar.gz.

File metadata

  • Download URL: fake_winreg-1.9.0.tar.gz
  • Upload date:
  • Size: 149.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for fake_winreg-1.9.0.tar.gz
Algorithm Hash digest
SHA256 17b86b31b6b8ea88d0ae5cd507fde32bced2b7166910f90a02f6ff942c555270
MD5 bfd3415c2592dc968fe3788a06d63d1b
BLAKE2b-256 92152d5ad392ee1a1db9065fadcc1b0d83a05a09181bf71f115b225ee98c1798

See more details on using hashes here.

File details

Details for the file fake_winreg-1.9.0-py3-none-any.whl.

File metadata

  • Download URL: fake_winreg-1.9.0-py3-none-any.whl
  • Upload date:
  • Size: 92.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for fake_winreg-1.9.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0f571049eca98acd32cccf315eeb7acaa1ea27d3acd2c0be75aa6cd3ab47e8a0
MD5 289e806c9b7ec8758773bf25fe99f372
BLAKE2b-256 4f8b5e51df13cd0767ecdceaf5ca2d33fdc084d0610ca5529b904d839e8d30b4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page