"""Shared stubs for the unit tests. Several bot modules under test import ``discord`` (and ``discord.ext.commands`` / ``discord.ext.tasks``) at import time. The pytest-only unit CI job doesn't install discord, so the test modules stub it themselves - but each stubbed only the pieces IT needed, and because they share ``sys.modules`` the first one to run won (skip-if-present), leaving a later module that needs e.g. ``discord.ext.tasks`` with an incomplete stub. That made collection order-dependent and flaky (e.g. test_bar_commands, whose stub omits ``tasks``, shadowing test_lore_commands, which needs it). Stubbing ``discord`` here - once, completely, before any test module is imported - removes the ordering dependency. The per-file stubs then simply skip. Only ``discord`` is stubbed centrally; ai_functions / communication_subroutine stay per-file because different modules legitimately want the real vs a stubbed one. """ import sys import types def _ensure_discord_stub() -> None: if "discord" in sys.modules: return try: # real discord present (local dev) -> use it import discord # noqa: F401 return except ImportError: pass mod = types.ModuleType("discord") class Object: def __init__(self, id=None): # noqa: A002 - mirrors discord.Object self.id = id class Member: pass mod.Object = Object mod.Member = Member ext = types.ModuleType("discord.ext") commands = types.ModuleType("discord.ext.commands") tasks = types.ModuleType("discord.ext.tasks") class Cog: pass commands.Cog = Cog commands.hybrid_command = lambda **_kwargs: (lambda fn: fn) def loop(**_kwargs): def decorator(fn): fn.before_loop = lambda f: f return fn return decorator tasks.loop = loop commands.tasks = tasks ext.commands = commands ext.tasks = tasks mod.ext = ext sys.modules["discord"] = mod sys.modules["discord.ext"] = ext sys.modules["discord.ext.commands"] = commands sys.modules["discord.ext.tasks"] = tasks _ensure_discord_stub()