Skip to main content

Text-first parsing and modding support library for Europa Universalis V data files, with optional MCP server and Kivy desktop GUI

Project description

EU5Miner (core)

The core library of the EU5Miner umbrella. See the umbrella README.md for install and layout.

EU5Miner is a text-first Python library for reading, indexing, and planning edits to Europa Universalis V data and mod files.

This is an unofficial community project. It is not affiliated with, endorsed by, or sponsored by Paradox Interactive or the Europa Universalis V development team.

The repository and published package do not include game assets. Real-file validation and many install-backed workflows expect a locally available EU5 installation.

Release 0.8.0 is the current umbrella release; the previous 0.7.x and 0.6.x lines stay supported.

The current release focuses on the major moddable text-based file families:

  • Clausewitz-style script text used in common, events, setup, and map_data
  • GUI script
  • Localization YAML
  • JSON metadata
  • Semicolon-delimited CSV

The project is intentionally test-heavy. Core functionality is validated against representative real EU5 install files so later parser work is anchored in observed game behavior instead of assumptions.

Module paths and extras

This package is the single eu5miner distribution. It exposes three Python modules:

  • eu5miner — core library and CLI (always available).
  • eu5miner.mcp — MCP server (requires the [mcp] extra).
  • eu5miner.gui — Kivy desktop UI (requires the [gui] extra).

Without the matching extra, importing eu5miner.mcp or eu5miner.gui raises an ImportError directing you to install the extra.

Status

The 0.8.x line is published from this umbrella as a single eu5miner wheel with optional extras (pip install eu5miner[mcp], eu5miner[gui], eu5miner[all]). The MCP server and GUI are submodules inside the unified package rather than separate distributions.

Compared with 0.5.0, the 0.6.x line expanded the stable read-only inspection seam with initial entity browsing for economy, diplomacy, government, religion, and map while keeping the public API deliberately curated.

  • The root package, grouped domain packages, eu5miner.inspection, and the eu5miner.mods facade are intended for real use.
  • The CLI is intended as a thin convenience surface over the same library APIs.
  • Additional helper layers and future editing surfaces are still expected to evolve before 1.0.
  • API coverage is intentionally incomplete relative to the full game data surface; missing families and API adjustments should still be expected during the preview line.

In practice, this release is suitable for install inspection, virtual filesystem queries, representative parsing, typed domain reads, and the current mod update planning and application workflow. It is not yet a promise that every exported helper will remain unchanged across future minor releases.

Install

pip install eu5miner

Or with the optional surfaces:

pip install eu5miner[mcp]   # adds eu5miner.mcp
pip install eu5miner[gui]   # adds eu5miner.gui
pip install eu5miner[all]

Python 3.12 and uv are required for development.

Development

Within the umbrella workspace:

cd EU5Miner
uv sync --extra=dev
cd packages/core
uv run pytest
uv run ruff check .
uv run mypy src
uv build

The repo is stored under OneDrive. The Windows setup script at scripts/setup-centralized-uv.ps1 points UV_PROJECT_ENVIRONMENT at %USERPROFILE%\.venvs\EU5Miner, sets UV_LINK_MODE=copy for OneDrive-safe uv operations, and runs uv sync --extra dev there.

Run the broader optional sweep explicitly when you want wider install-backed coverage:

uv run python -m pytest -m broad

CLI

The project ships a thin CLI:

eu5miner inspect-install
eu5miner list-systems
eu5miner list-files --phase in_game --subpath gui --limit 10
eu5miner analyze-script --representative scripted_trigger
eu5miner report-system --install-root C:\EU5 --system economy
eu5miner report-system --install-root C:\EU5 --system diplomacy
eu5miner plan-mod-update --install-root C:\EU5 --mod-root C:\mods\my_mod --phase in_game --subtree common/buildings --content-root C:\work\content
eu5miner apply-mod-update --install-root C:\EU5 --mod-root C:\mods\my_mod --phase in_game --subtree common/buildings --content-root C:\work\content

These seven commands and their documented arguments are the intended thin CLI contract. Higher-level automation should prefer the library facades in eu5miner.inspection and eu5miner.mods rather than depending on internal CLI helpers.

list-systems and report-system provide install-backed summaries for the major connected systems currently implemented in the library: economy, diplomacy, government, religion, interface, and map.

The mod workflow commands print a structured report to stdout, note: advisories for planned metadata actions such as replace_path additions, and warning: diagnostics for intended outputs that will still be shadowed by later sources.

Library

The root package intentionally stays narrow. It exposes install discovery, VFS primitives, and the public mod workflow facade:

from pathlib import Path

from eu5miner import ContentPhase, GameInstall, VirtualFilesystem, plan_mod_update

install = GameInstall.discover(r"C:\Program Files (x86)\Steam\steamapps\common\Europa Universalis V")
vfs = VirtualFilesystem.from_install(install)

merged = vfs.get_merged_file(ContentPhase.IN_GAME, Path("gui") / "agenda_view.gui")
assert merged is not None

update = plan_mod_update(
    vfs,
    "my_mod",
    ContentPhase.IN_GAME,
    Path("common") / "buildings",
    intended_relative_paths=(Path("common") / "buildings" / "a.txt",),
    content_by_relative_path={Path("common") / "buildings" / "a.txt": "building = {}\n"},
)

The root package does not also re-export install inspection helpers or domain parsing helpers. Keep those imports explicit so downstream code can depend on the intended stable seams.

For downstream GUI and MCP consumers that need a stable read-only seam for install discovery, high-level system summaries, and initial entity browsing, use eu5miner.inspection instead of reaching into CLI helpers:

from eu5miner import GameInstall
from eu5miner.inspection import (
    get_system_entity,
    format_install_summary,
    format_system_report,
    get_system_report,
    inspect_install,
    list_entity_systems,
    list_system_entities,
    list_supported_systems,
)

summary = inspect_install(r"C:\Program Files (x86)\Steam\steamapps\common\Europa Universalis V")
print(format_install_summary(summary))

systems = list_supported_systems()
economy_report = get_system_report(
    GameInstall.discover(summary.root),
    "economy",
)
print(format_system_report(economy_report))

entity_systems = list_entity_systems()
economy_entities = list_system_entities(
    GameInstall.discover(summary.root),
    "economy",
)
iron = get_system_entity(
    GameInstall.discover(summary.root),
    "economy",
    "iron",
)

This inspection facade is the stable public entrypoint for install summaries, available system listing, install-backed system report retrieval, and a deliberately narrow entity-browsing seam. The current browseable subset is intentionally limited to one primary entity family per system: economy goods, diplomacy casus belli, government government types, religion religions, and map linked locations. That keeps the preview API useful for GUI and MCP read-only flows without overcommitting to a generic graph API across every catalog family yet.

Repeated inspection entity queries are cached process-locally per install, system, and mod-root context. If a mutating workflow can change inspection results, invalidate the affected system entries with eu5miner.inspection.invalidate_system_entity_cache(...) or otherwise refresh the inspection cache state before querying again.

For domain adapters and higher-level helpers, prefer grouped package entrypoints when you are working within one concept area:

from eu5miner.domains.diplomacy import (
    build_diplomacy_graph_catalog,
    build_war_flow_catalog,
    parse_casus_belli_document,
    parse_country_interaction_document,
    parse_peace_treaty_document,
    parse_subject_type_document,
    parse_wargoal_document,
)
from eu5miner.domains.economy import (
    build_market_catalog,
    parse_goods_document,
    parse_price_document,
)
from eu5miner.domains.government import build_government_catalog, parse_government_type_document
from eu5miner.domains.localization import build_localization_bundle
from eu5miner.domains.map import build_linked_location_document, parse_default_map_document
from eu5miner.domains.religion import build_religion_catalog, parse_religion_document
from eu5miner.domains.units import parse_unit_category_document

casus_belli_document = parse_casus_belli_document(
    "sample_cb = { war_goal_type = superiority }\n"
)
wargoal_document = parse_wargoal_document(
    "superiority = { type = superiority attacker = { conquer_cost = 1 } }\n"
)
peace_treaty_document = parse_peace_treaty_document(
    "peace_example = { effect = { make_subject_of = { type = subject_type:sample_subject } } }\n"
)
subject_type_document = parse_subject_type_document(
    "sample_subject = { level = 1 allow_subjects = no }\n"
)
country_interaction_document = parse_country_interaction_document(
    "sample_country_interaction = { type = diplomacy }\n"
)

war_catalog = build_war_flow_catalog(
    casus_belli_documents=(casus_belli_document,),
    wargoal_documents=(wargoal_document,),
    peace_treaty_documents=(peace_treaty_document,),
    subject_type_documents=(subject_type_document,),
)
diplomacy_catalog = build_diplomacy_graph_catalog(
    casus_belli_documents=(casus_belli_document,),
    wargoal_documents=(wargoal_document,),
    peace_treaty_documents=(peace_treaty_document,),
    subject_type_documents=(subject_type_document,),
    country_interaction_documents=(country_interaction_document,),
)

goods_document = parse_goods_document("iron = { method = mining category = raw_material }\n")
price_document = parse_price_document("build_road = { gold = 10 }\n")
market_catalog = build_market_catalog(
    goods_documents=(goods_document,),
    price_documents=(price_document,),
)

government_type_document = parse_government_type_document(
    "monarchy = { heir_selection = cognatic government_power = legitimacy }\n"
)
government_catalog = build_government_catalog(
    government_type_documents=(government_type_document,),
)

religion_document = parse_religion_document("example_faith = { group = abrahamic }\n")
religion_catalog = build_religion_catalog(religion_documents=(religion_document,))

default_map_document = parse_default_map_document('setup = "definitions.txt"\n')
localization_bundle = build_localization_bundle(
    (("sample.yml", 'l_english:\nSAMPLE_KEY: "Sample"\n'),)
)
unit_category_document = parse_unit_category_document(
    "sample_category = { is_army = yes startup_amount = 1 }\n"
)

For mod update workflows in the preview release, eu5miner.mods remains the stable higher-level seam, while the CLI stays a thin wrapper over the same plan/apply/report operations.

The built-in apply_mod_update(...) flow already invalidates matching inspection entity caches when the planned update still carries install-backed context. Lower-level direct write helpers such as materialize_targeted_mod_emission(...) remain inspection-agnostic on purpose, so callers using those helpers directly must own any required inspection cache refresh or invalidation themselves.

The broad eu5miner.domains convenience export remains available for callers that genuinely want one import hub across many domains, but grouped packages are the preferred stable seam when the concept area is clear. Avoid reaching into internal implementation modules such as eu5miner.domains.diplomacy.casus_belli or eu5miner.domains.map.map_text from downstream code.

Testing

The default baseline keeps uv run pytest warning-free even when plugin-specific pytest options are unavailable.

When the development environment includes pytest-timeout via uv sync --extra dev, the suite also applies a global per-test timeout and preserves the per-test @pytest.mark.timeout(...) overrides used by parser-sensitive tests.

Configuration

The test suite and install-discovery helpers use this precedence for the game install path:

  1. EU5_INSTALL_DIR
  2. The default Steam install path on Windows

Documentation

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

eu5miner-0.8.0.tar.gz (292.8 kB view details)

Uploaded Source

Built Distribution

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

eu5miner-0.8.0-py3-none-any.whl (209.1 kB view details)

Uploaded Python 3

File details

Details for the file eu5miner-0.8.0.tar.gz.

File metadata

  • Download URL: eu5miner-0.8.0.tar.gz
  • Upload date:
  • Size: 292.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","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 eu5miner-0.8.0.tar.gz
Algorithm Hash digest
SHA256 5a40795ac27244a20174173f079462d944bbe9300230d4f3fe7884fb76eea0a3
MD5 3eeca7671fbbb56154fa05c78166bdda
BLAKE2b-256 abe09c7cb3a52a5b93ff0e7525b4b913ae88918192fee3ecf0f9c456db3ef224

See more details on using hashes here.

File details

Details for the file eu5miner-0.8.0-py3-none-any.whl.

File metadata

  • Download URL: eu5miner-0.8.0-py3-none-any.whl
  • Upload date:
  • Size: 209.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","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 eu5miner-0.8.0-py3-none-any.whl
Algorithm Hash digest
SHA256 27c341dc84d4da9d7d8c65b9e65b80fc0262cceb9649838649c369b2e4a3ba5b
MD5 712f97bdf8d7b40368c3809ffe806515
BLAKE2b-256 182a870163695c7923767bf612bf4b0d7821ec87be7fd21de0d7e90de75263f9

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