feat(identity): rename user-visible identity to voculinux with one-time legacy import

The fork takes its own name everywhere a user can see it: binaries
(voculinux, voculinux-gui), desktop entry, autostart, tray, D-Bus
namespace (com.voculinux.Voculinux, no alias for the old name),
config/data/cache dirs, single-instance lock, IBus engine identity,
tray icons, resource prefixes, VOCULINUX_* environment names, and the
update-checker user agent. The internal Python module stays vocalinux
and the distribution metadata keeps the upstream URLs as provenance.

On first run a previous Vocalinux install's config.json, custom
dictionary, and portal restore token are copied once into the new
locations (new config always wins, no merge, no write-back); models
re-resolve through the pinned-checksum download path. An offline
naming-sweep test proves no old-name strings remain on user-visible
surfaces outside the allowlist.

Refs #18
This commit is contained in:
soubarnak
2026-11-06 01:29:39 +05:30
parent c565e6d946
commit ea7be5f111
251 changed files with 2449 additions and 1991 deletions
+32 -32
View File
@@ -194,7 +194,7 @@ class TestIBusEngineModuleFunctions(unittest.TestCase):
@patch("subprocess.run")
def test_is_engine_active_success(self, mock_run):
"""Test when engine is active."""
mock_run.return_value = MagicMock(returncode=0, stdout="vocalinux")
mock_run.return_value = MagicMock(returncode=0, stdout="voculinux")
from vocalinux.text_injection.ibus_engine import is_engine_active
result = is_engine_active()
@@ -231,10 +231,10 @@ class TestIBusEngineModuleFunctions(unittest.TestCase):
@patch("vocalinux.text_injection.ibus_engine.get_current_engine")
def test_switch_engine_success(self, mock_get_current, mock_run):
"""Test switching engine successfully."""
mock_get_current.return_value = "vocalinux"
mock_get_current.return_value = "voculinux"
from vocalinux.text_injection.ibus_engine import switch_engine
result = switch_engine("vocalinux")
result = switch_engine("voculinux")
self.assertTrue(result)
@patch("subprocess.run")
@@ -244,7 +244,7 @@ class TestIBusEngineModuleFunctions(unittest.TestCase):
mock_get_current.return_value = "other-engine"
from vocalinux.text_injection.ibus_engine import switch_engine
result = switch_engine("vocalinux")
result = switch_engine("voculinux")
self.assertFalse(result)
@patch("vocalinux.text_injection.ibus_engine.PID_FILE")
@@ -380,7 +380,7 @@ class TestVocalinuxEngine(unittest.TestCase):
VocalinuxEngine._server_socket = None
VocalinuxEngine._server_running = False
def test_vocalinux_engine_init(self):
def test_voculinux_engine_init(self):
"""Test VocalinuxEngine initialization."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngine
@@ -394,7 +394,7 @@ class TestVocalinuxEngine(unittest.TestCase):
self.assertIsNone(VocalinuxEngine._server_socket)
self.assertFalse(VocalinuxEngine._server_running)
def test_vocalinux_engine_do_enable(self):
def test_voculinux_engine_do_enable(self):
"""Test engine enable signal handler."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngine
@@ -404,7 +404,7 @@ class TestVocalinuxEngine(unittest.TestCase):
# Verify active instance is set
self.assertEqual(VocalinuxEngine._active_instance, engine)
def test_vocalinux_engine_do_disable(self):
def test_voculinux_engine_do_disable(self):
"""Test engine disable signal handler."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngine
@@ -414,7 +414,7 @@ class TestVocalinuxEngine(unittest.TestCase):
# Instance should still be active (not cleared on disable)
self.assertEqual(VocalinuxEngine._active_instance, engine)
def test_vocalinux_engine_do_focus_in(self):
def test_voculinux_engine_do_focus_in(self):
"""Test engine focus in signal handler."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngine
@@ -423,7 +423,7 @@ class TestVocalinuxEngine(unittest.TestCase):
self.assertEqual(VocalinuxEngine._active_instance, engine)
self.assertTrue(VocalinuxEngine._focus_event.is_set())
def test_vocalinux_engine_do_focus_out(self):
def test_voculinux_engine_do_focus_out(self):
"""Test engine focus out signal handler."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngine
@@ -508,7 +508,7 @@ class TestVocalinuxEngine(unittest.TestCase):
self.assertIsNone(VocalinuxEngine._active_instance)
self.assertFalse(VocalinuxEngine._focus_event.is_set())
def test_vocalinux_engine_do_process_key_event(self):
def test_voculinux_engine_do_process_key_event(self):
"""Test engine key event processing."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngine
@@ -517,7 +517,7 @@ class TestVocalinuxEngine(unittest.TestCase):
# Should return False to pass through all keys
self.assertFalse(result)
def test_vocalinux_engine_inject_text_empty(self):
def test_voculinux_engine_inject_text_empty(self):
"""Test text injection with empty text."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngine
@@ -526,7 +526,7 @@ class TestVocalinuxEngine(unittest.TestCase):
# Empty text should return True (no-op)
self.assertTrue(result)
def test_vocalinux_engine_inject_text_success(self):
def test_voculinux_engine_inject_text_success(self):
"""Test successful text injection."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngine
@@ -540,7 +540,7 @@ class TestVocalinuxEngine(unittest.TestCase):
self.assertTrue(result)
engine.commit_text.assert_called_once()
def test_vocalinux_engine_inject_text_failure(self):
def test_voculinux_engine_inject_text_failure(self):
"""Test text injection error handling."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngine
@@ -733,7 +733,7 @@ class TestVocalinuxEngineApplication(unittest.TestCase):
pass
@patch("vocalinux.text_injection.ibus_engine.VocalinuxEngine._start_socket_server")
def test_vocalinux_engine_application_init(self, mock_start_server):
def test_voculinux_engine_application_init(self, mock_start_server):
"""Test VocalinuxEngineApplication initialization."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngineApplication
@@ -748,7 +748,7 @@ class TestVocalinuxEngineApplication(unittest.TestCase):
self.assertEqual(type(app.mainloop).__name__, "MagicMock")
@patch("vocalinux.text_injection.ibus_engine.VocalinuxEngine._start_socket_server")
def test_vocalinux_engine_application_on_disconnected(self, mock_start_server):
def test_voculinux_engine_application_on_disconnected(self, mock_start_server):
"""Test IBus disconnection handler."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngineApplication
@@ -760,7 +760,7 @@ class TestVocalinuxEngineApplication(unittest.TestCase):
app.mainloop.quit.assert_called_once()
@patch("vocalinux.text_injection.ibus_engine.VocalinuxEngine._start_socket_server")
def test_vocalinux_engine_application_run(self, mock_start_server):
def test_voculinux_engine_application_run(self, mock_start_server):
"""Test engine application main loop."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngineApplication
@@ -774,7 +774,7 @@ class TestVocalinuxEngineApplication(unittest.TestCase):
@patch("vocalinux.text_injection.ibus_engine.IBus.Component")
@patch("vocalinux.text_injection.ibus_engine.IBus.Factory.new")
@patch("vocalinux.text_injection.ibus_engine.IBus.Bus")
def test_vocalinux_engine_application_standalone_registers_component(
def test_voculinux_engine_application_standalone_registers_component(
self,
mock_bus_cls,
mock_factory_new,
@@ -810,7 +810,7 @@ class TestVocalinuxEngineApplication(unittest.TestCase):
@patch("vocalinux.text_injection.ibus_engine.VocalinuxEngine._start_socket_server")
@patch("vocalinux.text_injection.ibus_engine.IBus.Factory.new")
@patch("vocalinux.text_injection.ibus_engine.IBus.Bus")
def test_vocalinux_engine_application_ibus_exec_requests_name(
def test_voculinux_engine_application_ibus_exec_requests_name(
self,
mock_bus_cls,
mock_factory_new,
@@ -835,7 +835,7 @@ class TestVocalinuxEngineApplication(unittest.TestCase):
@patch("vocalinux.text_injection.ibus_engine.VocalinuxEngine._start_socket_server")
@patch("vocalinux.text_injection.ibus_engine.IBus.Factory.new")
@patch("vocalinux.text_injection.ibus_engine.IBus.Bus")
def test_vocalinux_engine_application_request_name_failure_raises(
def test_voculinux_engine_application_request_name_failure_raises(
self,
mock_bus_cls,
mock_factory_new,
@@ -858,7 +858,7 @@ class TestVocalinuxEngineApplication(unittest.TestCase):
@patch("vocalinux.text_injection.ibus_engine.VocalinuxEngine._start_socket_server")
@patch("vocalinux.text_injection.ibus_engine.IBus.Factory.new")
@patch("vocalinux.text_injection.ibus_engine.IBus.Bus")
def test_vocalinux_engine_application_register_component_failure_raises(
def test_voculinux_engine_application_register_component_failure_raises(
self,
mock_bus_cls,
mock_factory_new,
@@ -880,7 +880,7 @@ class TestVocalinuxEngineApplication(unittest.TestCase):
@patch("vocalinux.text_injection.ibus_engine.VocalinuxEngine._start_socket_server")
@patch("vocalinux.text_injection.ibus_engine.IBus.Bus")
def test_vocalinux_engine_application_disconnected_bus_raises(
def test_voculinux_engine_application_disconnected_bus_raises(
self,
mock_bus_cls,
mock_start_server,
@@ -898,7 +898,7 @@ class TestVocalinuxEngineApplication(unittest.TestCase):
@patch("vocalinux.text_injection.ibus_engine.VocalinuxEngine._start_socket_server")
@patch("vocalinux.text_injection.ibus_engine.IBus.Factory.new")
@patch("vocalinux.text_injection.ibus_engine.IBus.Bus")
def test_vocalinux_engine_application_none_connection_raises(
def test_voculinux_engine_application_none_connection_raises(
self,
mock_bus_cls,
mock_factory_new,
@@ -962,7 +962,7 @@ class TestIBusEngineMainEntrypoint(unittest.TestCase):
msg=f"stdout={result.stdout!r} stderr={result.stderr!r}",
)
self.assertIn("<engines>", result.stdout)
self.assertIn("vocalinux", result.stdout)
self.assertIn("voculinux", result.stdout)
self.assertNotIn("attempted relative import", result.stderr)
def test_main_passes_ibus_flag_to_application(self):
@@ -1008,7 +1008,7 @@ class TestStartEngineProcess(unittest.TestCase):
patch.object(ibus_engine, "is_engine_process_running", side_effect=running_states),
patch.object(ibus_engine, "ensure_ibus_dir"),
patch.object(ibus_engine, "PID_FILE") as mock_pid,
patch.object(ibus_engine, "VOCALINUX_IBUS_DIR", Path(tempfile.mkdtemp())),
patch.object(ibus_engine, "VOCULINUX_IBUS_DIR", Path(tempfile.mkdtemp())),
patch.object(ibus_engine.subprocess, "Popen", return_value=mock_proc) as mock_popen,
patch.object(ibus_engine.time, "sleep"),
patch.object(ibus_engine.sys, "prefix", "/venv"),
@@ -1040,7 +1040,7 @@ class TestStartEngineProcess(unittest.TestCase):
patch.object(ibus_engine, "is_engine_process_running", side_effect=iter([False, True])),
patch.object(ibus_engine, "ensure_ibus_dir"),
patch.object(ibus_engine, "PID_FILE"),
patch.object(ibus_engine, "VOCALINUX_IBUS_DIR", Path(tempfile.mkdtemp())),
patch.object(ibus_engine, "VOCULINUX_IBUS_DIR", Path(tempfile.mkdtemp())),
patch.object(ibus_engine.subprocess, "Popen", return_value=mock_proc) as mock_popen,
patch.object(ibus_engine.time, "sleep"),
):
@@ -1077,7 +1077,7 @@ class TestStartEngineProcess(unittest.TestCase):
patch.object(ibus_engine, "is_engine_process_running", return_value=False),
patch.object(ibus_engine, "ensure_ibus_dir"),
patch.object(ibus_engine, "PID_FILE") as mock_pid,
patch.object(ibus_engine, "VOCALINUX_IBUS_DIR", tmp),
patch.object(ibus_engine, "VOCULINUX_IBUS_DIR", tmp),
patch.object(ibus_engine.subprocess, "Popen", side_effect=popen_side_effect),
patch.object(ibus_engine.time, "sleep"),
patch.object(ibus_engine.logger, "error") as mock_error,
@@ -1110,7 +1110,7 @@ class TestStartEngineProcess(unittest.TestCase):
patch.object(ibus_engine, "is_engine_process_running", return_value=False),
patch.object(ibus_engine, "ensure_ibus_dir"),
patch.object(ibus_engine, "PID_FILE") as mock_pid,
patch.object(ibus_engine, "VOCALINUX_IBUS_DIR", tmp),
patch.object(ibus_engine, "VOCULINUX_IBUS_DIR", tmp),
patch.object(ibus_engine.subprocess, "Popen", return_value=mock_proc),
patch.object(ibus_engine.time, "sleep"),
patch.object(ibus_engine.logger, "error") as mock_error,
@@ -1137,7 +1137,7 @@ class TestStartEngineProcess(unittest.TestCase):
patch.object(ibus_engine, "is_engine_process_running", return_value=False),
patch.object(ibus_engine, "ensure_ibus_dir"),
patch.object(ibus_engine, "PID_FILE") as mock_pid,
patch.object(ibus_engine, "VOCALINUX_IBUS_DIR", tmp),
patch.object(ibus_engine, "VOCULINUX_IBUS_DIR", tmp),
patch.object(ibus_engine.subprocess, "Popen", return_value=mock_proc),
patch.object(ibus_engine.time, "sleep"),
patch.object(ibus_engine.logger, "error") as mock_error,
@@ -1173,7 +1173,7 @@ class TestStartEngineProcess(unittest.TestCase):
patch.object(ibus_engine, "is_engine_process_running", return_value=False),
patch.object(ibus_engine, "ensure_ibus_dir"),
patch.object(ibus_engine, "PID_FILE") as mock_pid,
patch.object(ibus_engine, "VOCALINUX_IBUS_DIR", tmp),
patch.object(ibus_engine, "VOCULINUX_IBUS_DIR", tmp),
patch.object(ibus_engine.subprocess, "Popen", return_value=mock_proc),
patch.object(ibus_engine.time, "sleep"),
):
@@ -1198,7 +1198,7 @@ class TestStartEngineProcess(unittest.TestCase):
patch.object(ibus_engine, "is_engine_process_running", return_value=False),
patch.object(ibus_engine, "ensure_ibus_dir"),
patch.object(ibus_engine, "PID_FILE") as mock_pid,
patch.object(ibus_engine, "VOCALINUX_IBUS_DIR", tmp),
patch.object(ibus_engine, "VOCULINUX_IBUS_DIR", tmp),
patch.object(ibus_engine.subprocess, "Popen", return_value=mock_proc),
patch.object(ibus_engine.time, "sleep"),
):
@@ -1230,7 +1230,7 @@ class TestStartEngineProcess(unittest.TestCase):
patch.object(ibus_engine, "is_engine_process_running", return_value=False),
patch.object(ibus_engine, "ensure_ibus_dir"),
patch.object(ibus_engine, "PID_FILE") as mock_pid,
patch.object(ibus_engine, "VOCALINUX_IBUS_DIR", tmp),
patch.object(ibus_engine, "VOCULINUX_IBUS_DIR", tmp),
patch.object(ibus_engine.subprocess, "Popen", return_value=mock_proc),
patch.object(ibus_engine.time, "sleep"),
patch.object(ibus_engine.logger, "error") as mock_error,
@@ -1249,7 +1249,7 @@ class TestStartEngineProcess(unittest.TestCase):
with (
patch.object(ibus_engine, "is_engine_process_running", return_value=False),
patch.object(ibus_engine, "ensure_ibus_dir"),
patch.object(ibus_engine, "VOCALINUX_IBUS_DIR", Path(tempfile.mkdtemp())),
patch.object(ibus_engine, "VOCULINUX_IBUS_DIR", Path(tempfile.mkdtemp())),
patch.object(ibus_engine.subprocess, "Popen", side_effect=OSError("cannot exec")),
patch.object(ibus_engine.logger, "error") as mock_error,
):