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:
+12
-6
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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")
|
||||
|
||||
@@ -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__"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user