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.1-py3-none-win_amd64.whl (38.7 kB view details)

Uploaded Python 3Windows x86-64

bethkit-1.0.1-py3-none-manylinux_2_34_x86_64.whl (38.4 kB view details)

Uploaded Python 3manylinux: glibc 2.34+ x86-64

File details

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

File metadata

  • Download URL: bethkit-1.0.1-py3-none-win_amd64.whl
  • Upload date:
  • Size: 38.7 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.1-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 e6d3dbabc871cb926ac820ad3c052dce7b51691b246d6c325ce891101553a84b
MD5 d650b06463fa3b97f2d5e7abfcac66b3
BLAKE2b-256 ea546cd1f2985caa8ca89d326f6bee67ae6dda3c6e82be613c47efb6d6dbc3dc

See more details on using hashes here.

File details

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

File metadata

  • Download URL: bethkit-1.0.1-py3-none-manylinux_2_34_x86_64.whl
  • Upload date:
  • Size: 38.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.1-py3-none-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 8e75a8f13613e038f4605576f2192e17a1881f6ec1a815b2ae9ddd12631a3740
MD5 0c5b1e555a3d45ebe747a224d117a7db
BLAKE2b-256 ac2bf1b70f4127c7ea620562d6c3f8f1da1eb9ebbf36366f95297df03c5d005c

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