"""Apply the maintained patch to installed upstream, then test real patched methods. No audio, clipboard, keyboard event, window focus or service mutation occurs. """ import importlib.util import json import os from pathlib import Path import shutil import struct import subprocess import sys import tempfile import threading import unittest from unittest.mock import Mock, patch ROOT = Path(__file__).resolve().parents[1] SOURCE = Path('/usr/lib/hyprwhspr/lib/src') class Wire: def __init__(self, data): self.data = data def __enter__(self): return self def __exit__(self, *args): pass def settimeout(self, value): pass def connect(self, path): pass def sendall(self, data): self.sent = data def recv(self, count): part, self.data = self.data[:min(count, 7)], self.data[min(count, 7):] return part class FocusTests(unittest.TestCase): @classmethod def setUpClass(cls): cls.folder = tempfile.TemporaryDirectory() root = Path(cls.folder.name) (root/'lib/src').mkdir(parents=True) shutil.copy2(SOURCE/'text_injector.py', root/'lib/src/text_injector.py') subprocess.run(['patch', '--batch', '--fuzz=0', '-p1', '-i', str(ROOT/'hyprwhspr/integration/sway-focus-paste.patch')], cwd=root, check=True, capture_output=True) sys.path.insert(0, str(SOURCE)) spec = importlib.util.spec_from_file_location('patched_injector', root/'lib/src/text_injector.py') cls.module = importlib.util.module_from_spec(spec) sys.modules[spec.name] = cls.module spec.loader.exec_module(cls.module) @classmethod def tearDownClass(cls): cls.folder.cleanup() sys.path.remove(str(SOURCE)) def setUp(self): self.env = patch.dict(os.environ, SWAYSOCK='/fake/sway.sock') self.env.start(); self.addCleanup(self.env.stop) self.injector = self.module.TextInjector.__new__(self.module.TextInjector) self.injector.config_manager = None self.injector.wtype_available = True self.injector.ydotool_available = True self.injector.xdotool_available = True self.injector._is_hyprland_session = Mock(return_value=False) self.injector._is_x11_session = Mock(return_value=False) self.injector._is_gnome_wayland_session = Mock(return_value=False) self.logs = patch.object(self.module, 'log') self.logs.start(); self.addCleanup(self.logs.stop) def read_tree(self, tree): data = json.dumps(tree).encode() wire = Wire(b'i3-ipc'+struct.pack('