Skip to main content

Python bindings for bethkit — a Bethesda plugin and archive toolkit

Project description

bethkit.py

License Python PyPI

Python bindings for bethkit - a fast Rust library for reading and writing Bethesda game plugin and archive files. bethkit.py wraps the bethkit_ffi C ABI via ctypes; no compiler or build tools required.

Features

  • Plugin reading - open .esp/.esm/.esl files by path or from in-memory bytes; iterate groups and records; look up records by FormID or EditorID; inspect sub-records
  • Plugin writing - build new plugins from scratch with PluginWriter, WritableGroup, and WritableRecord
  • BSA / BA2 archives - open and extract entries from BSA (TES4/SSE) and BA2 (GNRL/DX10) archives; write new archives with BsaWriter, Ba2GnrlWriter, and Ba2Dx10Writer
  • String tables - read, edit, and write .STRINGS/.DLSTRINGS/.ILSTRINGS localisation files; apply translation sets with LocalizationSet
  • Schema - decode sub-records into typed FieldValue variants (integers, floats, FormIDs, enums with resolved names, flags, structs, arrays) via RecordView and SchemaRegistry
  • Load-order utilities - LoadOrder, GlobalFormId, and PluginCache for winning-override lookups and EditorID search across multiple plugins

Requirements

Requirement Version
Python ≥ 3.10
pydantic ≥ 2.0

The native bethkit_ffi library is bundled in the wheel — no separate installation required.

Installation

uv add bethkit

or

pip install bethkit

Quick Start

Reading a plugin

from pathlib import Path
from bethkit import Plugin, Game

with Plugin.open(Path("Ordinator - Perks of Skyrim.esp"), Game.SKYRIM_SE) as plugin:
    print("Masters:", plugin.masters)
    print("Kind:", plugin.kind)

    for group in plugin:
        for child in group:
            if hasattr(child, "form_id"):
                print(f"  0x{child.form_id:08X}  {child.editor_id}")

Building a plugin from scratch

from pathlib import Path
from bethkit import Game, PluginWriter, WritableGroup, WritableRecord

with PluginWriter(Game.SKYRIM_SE) as writer:
    with WritableGroup.new(b"NPC_") as group:
        rec = WritableRecord.new(b"NPC_", form_id=0x000D62)
        rec.add_subrecord(b"EDID", b"MyNPC\x00")
        group.add_record(rec)
        writer.add_group(group)
    writer.write_to_file(Path("MyMod.esp"))

Extracting from an archive

from pathlib import Path
from bethkit import Archive

with Archive.open(Path("Skyrim - Meshes.bsa")) as arc:
    data = arc.extract("meshes/actors/character/character assets/skeleton.nif")
    if data:
        Path("skeleton.nif").write_bytes(data)

Load-order and FormID resolution

from pathlib import Path
from bethkit import Game, Plugin, PluginCache, PluginKind, LoadOrder

lo = LoadOrder()
lo.push("Skyrim.esm", PluginKind.FULL)
lo.push("MyMod.esp", PluginKind.FULL)

cache = PluginCache()
cache.add("Skyrim.esm", Plugin.open(Path("Skyrim.esm"), Game.SKYRIM_SE))

hit = cache.find_by_editor_id("ArmorIronCuirass")
if hit:
    print(hit.global_form_id)   # Skyrim.esm:0x012E49
    print(hit.record.editor_id)

Development

git clone https://github.com/Modding-Forge/bethkit.py
cd bethkit.py
uv sync --extra dev
uv run pytest

Linting and type-checking:

uv tool run ruff check src/ tests/
uv tool run pyright src/ tests/

Related projects

  • bethkit - the underlying Rust library; bethkit.py wraps its C ABI
  • SSE-Auto-Translator - uses bethkit.py to patch localised strings

License

Apache-2.0 - see LICENSE.

Project details


Download files

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

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

bethkit-1.0.2-py3-none-win_amd64.whl (390.6 kB view details)

Uploaded Python 3Windows x86-64

bethkit-1.0.2-py3-none-manylinux_2_34_x86_64.whl (518.4 kB view details)

Uploaded Python 3manylinux: glibc 2.34+ x86-64

File details

Details for the file bethkit-1.0.2-py3-none-win_amd64.whl.

File metadata

  • Download URL: bethkit-1.0.2-py3-none-win_amd64.whl
  • Upload date:
  • Size: 390.6 kB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for bethkit-1.0.2-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 a89506fbd2a46f3204978092504790974928801dae98ac113ee971b949a4f5aa
MD5 066e3dcb63a1cd6d33293466403407c2
BLAKE2b-256 73a5a0e51fa4677085eb8495364002bc0231abeab1e3970b8cece42d2193bfe2

See more details on using hashes here.

File details

Details for the file bethkit-1.0.2-py3-none-manylinux_2_34_x86_64.whl.

File metadata

  • Download URL: bethkit-1.0.2-py3-none-manylinux_2_34_x86_64.whl
  • Upload date:
  • Size: 518.4 kB
  • Tags: Python 3, manylinux: glibc 2.34+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for bethkit-1.0.2-py3-none-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 d92e35a0b0810a91be14d84ed5bc2bf3be4fa2cf9366c0538edeb37c67e42048
MD5 1a8c39251647727eb1b14b207a6c0180
BLAKE2b-256 f2023b50801ba04c0f146d707c078090b2b908f876bbbf94e67db6135e7c4504

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