Table of Contents

Namespace WoWLib.Filesystem

Classes

ClientInstall

What a client installation says about itself: the exact version, the flavor that follows from its product code, and the TACT product code itself.

Detecting beats hand-writing a ClientVersion for anything Classic. Those
products ship new builds continuously and the build — not the 1.15 / 4.4
version number — decides which engine's file formats the install
carries, so the build has to be right. detect() reads it from the files
Blizzard's installer leaves behind.

Examples:
    ```python
    from wowlib.fs import ClientInstall, FileSystem, FileSystemSettings

    install = ClientInstall.detect("/Games/World of Warcraft/_classic_era_")
    print(install.version)         # 1.15.9.69109 (ClassicEra)
    print(install.casc_product)    # 'wow_classic_era'

    settings = FileSystemSettings(install.path, install.version,
                                  casc_product=install.casc_product)
    with FileSystem.open(settings) as fs:
        ...
    ```
FileSystem

The runtime gateway to one client's files. Picks the storage backend from the client version and hides the static composition behind one bindable type; C++ code that wants zero dispatch overhead can use MpqFileSystem/CascFileSystem directly.

Lifetime: open() returns an open filesystem and destruction releases it —
in C++ that is the whole story (RAII; no public close, so no reachable
wrong state beyond a moved-from object). The scripting languages, where
finalization timing belongs to the runtime, additionally get explicit
control: close() and is_open (welded from the protected surface), and in
Python the with-statement.

Examples:
    Preferred: scope the storage with a `with` block — `open()` returns
    the filesystem, `__enter__` hands it to the block, and `__exit__`
    calls `close()` on the way out, exception or not:

    ```python
    from wowlib import versions
    from wowlib.fs import FileSystem, FileSystemSettings

    settings = FileSystemSettings("/Games/WoW 3.3.5a", versions.wotlk)
    with FileSystem.open(settings) as fs:
        data = fs.read_file("Interface/FrameXML/UIParent.lua")
    ```

    Equivalent explicit form, when the lifetime cannot be a single block
    (a viewer holding the storage across UI events):

    ```python
    fs = FileSystem.open(settings)
    try:
        data = fs.read_file("Interface/FrameXML/UIParent.lua")
    finally:
        fs.close()      # storage released now, not at GC time
    ```
FileSystemSettings

Everything needed to open a client filesystem: where the client is, which version it is, and the optional listfile / project directory / locale configuration. An immutable value, fully described at construction — a settings object can never be half-edited into an inconsistent state. In C++ it stays an aggregate (designated initializers; const members); the scripting languages construct through the synthesized field constructor, where everything after the version is optional.