Auto merge dev → main (#1225)

* fix BOT.data_parser import in render_recap.py

render_recap.py runs as a subprocess (Path(__file__).parent.parent on
sys.path) and used `from BOT.data_parser import ...`. After the SHARED
move, data_parser is no longer in the BOT package. Add BOTS/SHARED to
sys.path and switch to the absolute `from data_parser import ...`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* centralize SHARED sys.path bootstrap in BOT/__init__.py

Drop per-file `sys.path.insert(SHARED)` bandaids from BOT/scoreboard.py,
gob.py, utils.py, and game_api.py. The bootstrap now happens exactly
once when the BOT package is imported (via BOT/__init__.py), which is
implicit for any `from BOT.X import …` / `import BOT.X` and any
`python -m BOT.x` invocation.

`SHARED_DIR` is exposed as a public name on the BOT package; siblings
import it via `from . import SHARED_DIR` for building asset paths
(MAPS, ICONS, FONTS, vromfs) instead of recomputing the location.

render_recap.py is the one subprocess entry point that runs as
__main__, so it keeps a minimal bootstrap: add SREBOT to sys.path
then `import BOT` to fire the package init once.

Also move pyrightconfig.json to the BOTS monorepo root so pyright
resolves data_parser and third-party imports regardless of which
subproject the editor opens from.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
NotSoToothless
2026-05-13 23:42:47 -07:00
committed by GitHub
parent ff420e131f
commit 39ef90b3fd
7 changed files with 35 additions and 56 deletions
+12 -6
View File
@@ -1,12 +1,18 @@
"""SREBOT bot package.
Bootstraps the sibling BOTS/SHARED directory onto sys.path so that
`from data_parser import ...` (and other SHARED-only modules) resolve
regardless of which submodule gets imported first.
Single source of truth for the BOTS/SHARED bootstrap. Importing this
package (which happens automatically for any `from BOT.X import ...`
or `import BOT.X`) puts the sibling `BOTS/SHARED/` directory on
sys.path, so submodules can simply `from data_parser import ...` etc.
`SHARED_DIR` is also re-exported so consumers can compute asset paths
(MAPS, ICONS, FONTS, vromfs) without re-deriving the location.
"""
import sys
from pathlib import Path
_SHARED_DIR = Path(__file__).resolve().parents[2] / "SHARED"
if str(_SHARED_DIR) not in sys.path:
sys.path.insert(0, str(_SHARED_DIR))
SHARED_DIR: Path = Path(__file__).resolve().parents[2] / "SHARED"
if str(SHARED_DIR) not in sys.path:
sys.path.insert(0, str(SHARED_DIR))
__all__ = ["SHARED_DIR"]
+1 -6
View File
@@ -12,7 +12,6 @@ import json
import logging
import os
import sqlite3
import sys
import time
from pathlib import Path
from typing import Any, Dict, Tuple
@@ -23,11 +22,7 @@ import aiohttp
import aiosqlite
from dotenv import load_dotenv
# Ensure project root is in path for DAGOR_FILES imports
_project_root = Path(__file__).resolve().parent.parent
if str(_project_root) not in sys.path:
sys.path.insert(0, str(_project_root))
# DAGOR_FILES lives in BOTS/SHARED; BOT/__init__.py already put it on sys.path.
from DAGOR_FILES.WtFileUtils.blk.BlkParser import BlkDecoder
# Local Module Imports
+5 -9
View File
@@ -33,14 +33,10 @@ import numpy as np
import pygob
import zstandard as zstd
from . import SHARED_DIR
from .utils import REPLAYS_DIR
from PIL import Image, ImageDraw, ImageFilter, ImageFont
# Make SHARED (sibling of SREBOT under BOTS/) importable
_SHARED_DIR = Path(__file__).resolve().parents[2] / "SHARED"
if str(_SHARED_DIR) not in sys.path:
sys.path.insert(0, str(_SHARED_DIR))
try:
from data_parser import (
LangTableReader as _LangTableReader,
@@ -114,9 +110,9 @@ N_WORKERS = min(8, os.cpu_count() or 4) # Thread pool size for parallel frame
WIN_COLOR = (0, 200, 0) # green
LOSE_COLOR = (220, 30, 30) # red
MINIMAPS_DIR = _SHARED_DIR / "MAPS" / "MINIMAPS"
LEVELS_DIR = _SHARED_DIR / "MAPS" / "LEVELS"
ICONS_DIR = _SHARED_DIR / "ICONS"
MINIMAPS_DIR = SHARED_DIR / "MAPS" / "MINIMAPS"
LEVELS_DIR = SHARED_DIR / "MAPS" / "LEVELS"
ICONS_DIR = SHARED_DIR / "ICONS"
_tl = threading.local()
@@ -221,7 +217,7 @@ def _get_unit_tags(internal_name: str) -> list[str] | None:
return UnitTags.get()._get_tags(internal_name)
MINIS_DIR = _SHARED_DIR / "ICONS" / "MINIS"
MINIS_DIR = SHARED_DIR / "ICONS" / "MINIS"
_AIRCRAFT_TAGS = {"air", "aircraft", "helicopter"}
+6 -4
View File
@@ -69,11 +69,13 @@ def _sanitize_render_text(s: str) -> str:
)
_repo_root = Path(__file__).resolve().parent.parent
if str(_repo_root) not in sys.path:
sys.path.insert(0, str(_repo_root))
# This script runs as a subprocess entry point (python BOT/render_recap.py …),
# so BOT/__init__.py is not invoked automatically. Put SREBOT on sys.path,
# then `import BOT` to trigger the package's SHARED bootstrap once.
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
import BOT # noqa: F401, E402 — side effect: adds BOTS/SHARED to sys.path
from BOT.data_parser import apply_vehicle_name_filters # noqa: E402
from data_parser import apply_vehicle_name_filters # noqa: E402
LOCALES_DIR = Path(__file__).resolve().parent.parent / "web" / "locales"
DEFAULT_LANG = "en"
+5 -9
View File
@@ -14,7 +14,6 @@ import logging
import os
import pstats
import re
import sys
from datetime import datetime, timezone
from functools import lru_cache
from pathlib import Path
@@ -24,12 +23,9 @@ import numpy as np
from PIL import Image, ImageDraw, ImageFilter, ImageFont
from PIL.Image import Resampling
# Make SHARED (sibling of SREBOT under BOTS/) importable
_SHARED_DIR = Path(__file__).resolve().parents[2] / "SHARED"
if str(_SHARED_DIR) not in sys.path:
sys.path.insert(0, str(_SHARED_DIR))
# Local Module Imports
from . import SHARED_DIR
# Toggle for data_parser dependency
# Set to False to avoid importing data_parser and show all vehicles as "?" in team composition
USE_DATA_PARSER = True
@@ -45,9 +41,9 @@ else:
return name
BASE_DIR = Path(__file__).resolve().parent
MAPS_DIR = _SHARED_DIR / "MAPS"
ICON_BASE_DIR = _SHARED_DIR / "ICONS"
TEXT_FONT_PATH = _SHARED_DIR / "FONTS" / "arial_unicode_ms.otf"
MAPS_DIR = SHARED_DIR / "MAPS"
ICON_BASE_DIR = SHARED_DIR / "ICONS"
TEXT_FONT_PATH = SHARED_DIR / "FONTS" / "arial_unicode_ms.otf"
def _normalize_squad_key(value: str | None) -> str:
+6 -8
View File
@@ -30,12 +30,10 @@ from discord.utils import escape_markdown, escape_mentions
from dotenv import load_dotenv
from wcwidth import wcswidth
# Make SHARED (sibling of SREBOT under BOTS/) importable
_SHARED_DIR = Path(__file__).resolve().parents[2] / "SHARED"
if str(_SHARED_DIR) not in sys.path:
sys.path.insert(0, str(_SHARED_DIR))
# Local Module Imports
# BOT/__init__.py has already put BOTS/SHARED on sys.path; re-export it
# under a public name so peer modules can use it for asset paths.
from . import SHARED_DIR # noqa: F401 — re-exported for siblings
from data_parser import (
LangTableReader,
UnitTags,
@@ -64,7 +62,7 @@ def esc(text: str) -> str:
# Base storage paths
STORAGE_DIR = require_storage_dir()
ICONS_DIR = _SHARED_DIR / "ICONS"
ICONS_DIR = SHARED_DIR / "ICONS"
# Cache and Auth directories
CACHE_DIR = STORAGE_DIR / "CACHE"
@@ -1411,7 +1409,7 @@ async def init_game_cache():
all_names = unit_tags.all_names
logging.info(f"[GAMES] TOTAL VEHICLES: {len(all_names)}")
icons_dir = _SHARED_DIR / "ICONS" / "VEHICLES"
icons_dir = SHARED_DIR / "ICONS" / "VEHICLES"
# Case-insensitive lookup: unittags.blk uses CDKs like "ussr_su_122P" while the
# icon file on disk is "ussr_su_122p.png". On case-sensitive filesystems an exact
# match silently drops these vehicles from the cache.
@@ -1445,7 +1443,7 @@ async def init_game_cache_all():
all_names = unit_tags.all_names
logging.info(f"[GAMES] TOTAL VEHICLES (ALL): {len(all_names)}")
icons_dir = _SHARED_DIR / "ICONS" / "VEHICLES"
icons_dir = SHARED_DIR / "ICONS" / "VEHICLES"
icons_on_disk = {p.name.lower(): p.name for p in icons_dir.iterdir() if p.suffix == ".png"} if icons_dir.is_dir() else {}
translate = LangTableReader("English")
-14
View File
@@ -1,14 +0,0 @@
{
"pythonVersion": "3.14",
"extraPaths": [
".venv/lib/python3.14/site-packages",
"../SHARED"
],
"exclude": [
".venv",
"../SHARED/DAGOR_FILES",
"web/node_modules",
"node_modules",
"**/__pycache__"
]
}