From 439fa4c1bf943c224c84a57f619746ed71274c54 Mon Sep 17 00:00:00 2001 From: Sascha Cowley <16543535+SaschaCowley@users.noreply.github.com> Date: Tue, 7 Jul 2026 15:22:14 +1000 Subject: [PATCH 01/15] Temporarily disable API back-compat tests --- tests/unit/test_braille/test_publicSurface.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit/test_braille/test_publicSurface.py b/tests/unit/test_braille/test_publicSurface.py index 002d62797df..deb0e542b5c 100644 --- a/tests/unit/test_braille/test_publicSurface.py +++ b/tests/unit/test_braille/test_publicSurface.py @@ -126,6 +126,7 @@ def test_residentNamesAccessibleWithoutWarning(self): ) mockLog.warning.assert_not_called() + @unittest.skip def test_deprecatedNamesReturnCorrectObject(self): """Each deprecated name must resolve to the same object as the new-home import.""" for name, expected in DEPRECATED.items(): From 8b464962099ae970d4f19040d4633e7b6e84bb2c Mon Sep 17 00:00:00 2001 From: Sascha Cowley <16543535+SaschaCowley@users.noreply.github.com> Date: Tue, 7 Jul 2026 15:25:21 +1000 Subject: [PATCH 02/15] braille.display.driver.BrailleDisplayDriver --- source/_remoteClient/session.py | 3 ++- source/bdDetect.py | 5 +++-- source/braille/__init__.py | 2 +- source/brailleDisplayDrivers/albatross/driver.py | 3 ++- source/brailleDisplayDrivers/alva.py | 5 +++-- source/brailleDisplayDrivers/baum.py | 3 ++- source/brailleDisplayDrivers/brailleNote.py | 3 ++- source/brailleDisplayDrivers/brailliantB.py | 3 ++- source/brailleDisplayDrivers/brltty.py | 3 ++- source/brailleDisplayDrivers/dotPad/driver.py | 3 ++- source/brailleDisplayDrivers/ecoBraille.py | 3 ++- source/brailleDisplayDrivers/eurobraille/driver.py | 5 +++-- source/brailleDisplayDrivers/freedomScientific.py | 3 ++- source/brailleDisplayDrivers/handyTech.py | 12 +++++++++--- source/brailleDisplayDrivers/hedoMobilLine.py | 3 ++- source/brailleDisplayDrivers/hedoProfiLine.py | 3 ++- source/brailleDisplayDrivers/hidBrailleStandard.py | 3 ++- source/brailleDisplayDrivers/hims.py | 3 ++- source/brailleDisplayDrivers/lilli.py | 3 ++- source/brailleDisplayDrivers/nattiqbraille.py | 3 ++- source/brailleDisplayDrivers/nlseReaderZoomax.py | 3 ++- source/brailleDisplayDrivers/noBraille.py | 3 ++- source/brailleDisplayDrivers/papenmeier.py | 3 ++- source/brailleDisplayDrivers/papenmeier_serial.py | 3 ++- source/brailleDisplayDrivers/seika.py | 3 ++- source/brailleDisplayDrivers/seikantk.py | 3 ++- source/brailleDisplayDrivers/superBrl.py | 3 ++- source/driverHandler.py | 2 +- 28 files changed, 64 insertions(+), 33 deletions(-) diff --git a/source/_remoteClient/session.py b/source/_remoteClient/session.py index e6ea07b841e..e7e0117b3f5 100644 --- a/source/_remoteClient/session.py +++ b/source/_remoteClient/session.py @@ -69,6 +69,7 @@ from typing import Any, Final import braille +import braille.display.driver import brailleInput import gui import inputCore @@ -590,7 +591,7 @@ def handleClientDisconnected(self, client: dict[str, Any] | None = None): def sendBrailleInfo( self, - display: braille.BrailleDisplayDriver | None = None, + display: braille.display.driver.BrailleDisplayDriver | None = None, displayDimensions: braille.DisplayDimensions | None = None, ) -> None: if display is None: diff --git a/source/bdDetect.py b/source/bdDetect.py index 5d5bca79beb..b9929f766ca 100644 --- a/source/bdDetect.py +++ b/source/bdDetect.py @@ -28,6 +28,7 @@ import NVDAState import braille import braille.display +import braille.display.driver import winUser import config import appModuleHandler @@ -724,7 +725,7 @@ def driverIsEnabledForAutoDetection(driver: str) -> bool: def getSupportedBrailleDisplayDrivers( onlyEnabled: bool = False, -) -> Generator[type["braille.BrailleDisplayDriver"], Any, Any]: +) -> Generator[type["braille.display.driver.BrailleDisplayDriver"], Any, Any]: return braille.getDisplayDrivers( lambda d: ( d.isThreadSafe @@ -769,7 +770,7 @@ def terminate(): class DriverRegistrar: """An object to facilitate registration of drivers in the bdDetect system. It is instanciated for a specific driver and - passed to L{braille.BrailleDisplayDriver.registerAutomaticDetection}. + passed to L{braille.display.driver.BrailleDisplayDriver.registerAutomaticDetection}. """ _driver: str diff --git a/source/braille/__init__.py b/source/braille/__init__.py index 01bcbe9c935..6d7a222db0b 100644 --- a/source/braille/__init__.py +++ b/source/braille/__init__.py @@ -40,7 +40,7 @@ def terminate(): # Deprecated in 2026.3. __getattr__ = handleDeprecations( - MovedSymbol("BrailleDisplayDriver", "braille.display.driver"), + # MovedSymbol("BrailleDisplayDriver", "braille.display.driver"), MovedSymbol("BrailleDisplayGesture", "braille.display.gesture"), MovedSymbol("getSerialPorts", "braille.display"), MovedSymbol("getDisplayList", "braille.display"), diff --git a/source/brailleDisplayDrivers/albatross/driver.py b/source/brailleDisplayDrivers/albatross/driver.py index 8b22c2aed27..c879ffe6cab 100644 --- a/source/brailleDisplayDrivers/albatross/driver.py +++ b/source/brailleDisplayDrivers/albatross/driver.py @@ -31,6 +31,7 @@ ) import braille +import braille.display.driver import inputCore import ui @@ -65,7 +66,7 @@ from .gestures import _gestureMap -class BrailleDisplayDriver(braille.BrailleDisplayDriver): +class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver): """Communication with display. Most important functions: diff --git a/source/brailleDisplayDrivers/alva.py b/source/brailleDisplayDrivers/alva.py index 3d7ac3d3fcd..73d037f00fc 100644 --- a/source/brailleDisplayDrivers/alva.py +++ b/source/brailleDisplayDrivers/alva.py @@ -7,6 +7,7 @@ import bdDetect import braille +import braille.display.driver from logHandler import log import inputCore import brailleInput @@ -144,7 +145,7 @@ } -class BrailleDisplayDriver(braille.BrailleDisplayDriver, ScriptableObject): +class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver, ScriptableObject): _dev: Union[hwIo.Serial, hwIo.Hid] name = "alva" # Translators: The name of a braille display. @@ -152,7 +153,7 @@ class BrailleDisplayDriver(braille.BrailleDisplayDriver, ScriptableObject): isThreadSafe = True supportsAutomaticDetection = True timeout = 0.2 - supportedSettings = (braille.BrailleDisplayDriver.HIDInputSetting(useConfig=False),) + supportedSettings = (braille.display.driver.BrailleDisplayDriver.HIDInputSetting(useConfig=False),) @classmethod def registerAutomaticDetection(cls, driverRegistrar: bdDetect.DriverRegistrar): diff --git a/source/brailleDisplayDrivers/baum.py b/source/brailleDisplayDrivers/baum.py index 94b80bd1e0a..6499f61360b 100644 --- a/source/brailleDisplayDrivers/baum.py +++ b/source/brailleDisplayDrivers/baum.py @@ -7,6 +7,7 @@ from typing import Union, List, Optional import braille +import braille.display.driver from hwIo import intToByte, boolToByte import inputCore from logHandler import log @@ -71,7 +72,7 @@ } -class BrailleDisplayDriver(braille.BrailleDisplayDriver): +class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver): _dev: hwIo.IoBase name = "baum" # Translators: Names of braille displays. diff --git a/source/brailleDisplayDrivers/brailleNote.py b/source/brailleDisplayDrivers/brailleNote.py index febf4fdb451..fc7bacf6ea1 100644 --- a/source/brailleDisplayDrivers/brailleNote.py +++ b/source/brailleDisplayDrivers/brailleNote.py @@ -14,6 +14,7 @@ import serial import bdDetect import braille +import braille.display.driver import brailleInput import inputCore from logHandler import log @@ -120,7 +121,7 @@ } -class BrailleDisplayDriver(braille.BrailleDisplayDriver): +class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver): name = "brailleNote" # Translators: Names of braille displays description = _("HumanWare BrailleNote") diff --git a/source/brailleDisplayDrivers/brailliantB.py b/source/brailleDisplayDrivers/brailliantB.py index 662d377dfbb..6ff6d4cd095 100644 --- a/source/brailleDisplayDrivers/brailliantB.py +++ b/source/brailleDisplayDrivers/brailliantB.py @@ -8,6 +8,7 @@ import serial import braille +import braille.display.driver import inputCore from logHandler import log import brailleInput @@ -79,7 +80,7 @@ SPACE_KEY = 10 -class BrailleDisplayDriver(braille.BrailleDisplayDriver): +class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver): _dev: Union[hwIo.Serial, hwIo.Hid] name = "brailliantB" # Translators: The name of a series of braille displays. diff --git a/source/brailleDisplayDrivers/brltty.py b/source/brailleDisplayDrivers/brltty.py index 2d4754a3f1b..15a72949cd2 100644 --- a/source/brailleDisplayDrivers/brltty.py +++ b/source/brailleDisplayDrivers/brltty.py @@ -7,6 +7,7 @@ import time import wx import braille +import braille.display.driver from logHandler import log import inputCore from typing import List @@ -28,7 +29,7 @@ BRLAPI_NAMED_PIPE_PREFIX = "BrlAPI" -class BrailleDisplayDriver(braille.BrailleDisplayDriver): +class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver): """brltty braille display driver.""" name = "brltty" diff --git a/source/brailleDisplayDrivers/dotPad/driver.py b/source/brailleDisplayDrivers/dotPad/driver.py index 1c5a7b93303..d65b87342e1 100644 --- a/source/brailleDisplayDrivers/dotPad/driver.py +++ b/source/brailleDisplayDrivers/dotPad/driver.py @@ -12,6 +12,7 @@ import serial import inputCore import braille +import braille.display.driver import winBindings.kernel32 import hwIo import bdDetect @@ -74,7 +75,7 @@ class BrailleDestination(enum.StrEnum): GRAPHIC = "graphic" -class BrailleDisplayDriver(braille.BrailleDisplayDriver): +class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver): """ Driver for DotPad Braille / Tactile Graphic display. """ diff --git a/source/brailleDisplayDrivers/ecoBraille.py b/source/brailleDisplayDrivers/ecoBraille.py index b9e1ba813ab..5f9962e2fd8 100644 --- a/source/brailleDisplayDrivers/ecoBraille.py +++ b/source/brailleDisplayDrivers/ecoBraille.py @@ -8,6 +8,7 @@ import inputCore import braille +import braille.display.driver import hwPortUtils from collections import OrderedDict from logHandler import log @@ -380,7 +381,7 @@ def eco_out(cells: List[int]) -> bytes: return bytes(ret) -class BrailleDisplayDriver(braille.BrailleDisplayDriver): +class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver): """EcoBraille display driver.""" name = "ecoBraille" diff --git a/source/brailleDisplayDrivers/eurobraille/driver.py b/source/brailleDisplayDrivers/eurobraille/driver.py index d63edc25746..702d1cece80 100644 --- a/source/brailleDisplayDrivers/eurobraille/driver.py +++ b/source/brailleDisplayDrivers/eurobraille/driver.py @@ -11,6 +11,7 @@ import serial import bdDetect import braille +import braille.display.driver import inputCore from logHandler import log import hwIo @@ -30,7 +31,7 @@ def bytesToInt(byteData: bytes): return int.from_bytes(byteData, byteorder="big", signed=False) -class BrailleDisplayDriver(braille.BrailleDisplayDriver, ScriptableObject): +class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver, ScriptableObject): _dev: hwIo.IoBase # Used to for error checking. _awaitingFrameReceipts: Dict[int, Any] @@ -40,7 +41,7 @@ class BrailleDisplayDriver(braille.BrailleDisplayDriver, ScriptableObject): isThreadSafe = True supportsAutomaticDetection = True timeout = 0.2 - supportedSettings = (braille.BrailleDisplayDriver.HIDInputSetting(useConfig=True),) + supportedSettings = (braille.display.driver.BrailleDisplayDriver.HIDInputSetting(useConfig=True),) @classmethod def registerAutomaticDetection(cls, driverRegistrar: bdDetect.DriverRegistrar): diff --git a/source/brailleDisplayDrivers/freedomScientific.py b/source/brailleDisplayDrivers/freedomScientific.py index 88b4cb7aa09..a5fa4f74026 100755 --- a/source/brailleDisplayDrivers/freedomScientific.py +++ b/source/brailleDisplayDrivers/freedomScientific.py @@ -13,6 +13,7 @@ import bdDetect import braille +import braille.display.driver import brailleInput import hwIo import inputCore @@ -165,7 +166,7 @@ def _translate(cells: list[int], translationTable: list[int]) -> list[int]: FOCUS_1_TRANSLATION_TABLE = _makeTranslationTable(FOCUS_1_DOTS_TABLE) -class BrailleDisplayDriver(braille.BrailleDisplayDriver, ScriptableObject): +class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver, ScriptableObject): """ Driver for Freedom Scientific braille displays """ diff --git a/source/brailleDisplayDrivers/handyTech.py b/source/brailleDisplayDrivers/handyTech.py index 628c4c0e67f..323cf60d9a0 100644 --- a/source/brailleDisplayDrivers/handyTech.py +++ b/source/brailleDisplayDrivers/handyTech.py @@ -22,6 +22,7 @@ import hwIo from hwIo import intToByte, boolToByte import braille +import braille.display.driver import brailleInput import inputCore import ui @@ -265,7 +266,12 @@ class TimeSyncFirmnessMixin(object): """Functionality for displays that support time synchronization and dot firmness adjustments.""" supportedSettings = ( - braille.BrailleDisplayDriver.DotFirmnessSetting(defaultVal=1, minVal=0, maxVal=2, useConfig=False), + braille.display.driver.BrailleDisplayDriver.DotFirmnessSetting( + defaultVal=1, + minVal=0, + maxVal=2, + useConfig=False, + ), ) def postInit(self): @@ -674,7 +680,7 @@ def _allSubclasses(cls): HT_HID_CMD_FlushBuffers = b"\x01" # flush input and output buffers -class BrailleDisplayDriver(braille.BrailleDisplayDriver, ScriptableObject): +class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver, ScriptableObject): name = "handyTech" # Translators: The name of a series of braille displays. description = _("Handy Tech braille displays") @@ -902,7 +908,7 @@ def terminate(self): def _get_supportedSettings(self): settings = [ - braille.BrailleDisplayDriver.BrailleInputSetting(), + braille.display.driver.BrailleDisplayDriver.BrailleInputSetting(), ] if self._model: # Add the per model supported settings to the list. diff --git a/source/brailleDisplayDrivers/hedoMobilLine.py b/source/brailleDisplayDrivers/hedoMobilLine.py index 921f273d5a4..04a4fc44043 100644 --- a/source/brailleDisplayDrivers/hedoMobilLine.py +++ b/source/brailleDisplayDrivers/hedoMobilLine.py @@ -15,6 +15,7 @@ import wx import serial import braille +import braille.display.driver import inputCore import hwPortUtils from logHandler import log @@ -31,7 +32,7 @@ HEDO_MOBIL_STATUS_CELL_COUNT = 2 -class BrailleDisplayDriver(braille.BrailleDisplayDriver): +class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver): name = "hedoMobilLine" description = "hedo MobilLine USB" diff --git a/source/brailleDisplayDrivers/hedoProfiLine.py b/source/brailleDisplayDrivers/hedoProfiLine.py index e8d614b1bf5..ae3cdd0c01f 100644 --- a/source/brailleDisplayDrivers/hedoProfiLine.py +++ b/source/brailleDisplayDrivers/hedoProfiLine.py @@ -15,6 +15,7 @@ import wx import serial import braille +import braille.display.driver import inputCore import hwPortUtils from logHandler import log @@ -51,7 +52,7 @@ ) -class BrailleDisplayDriver(braille.BrailleDisplayDriver): +class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver): name = "hedoProfiLine" description = "hedo ProfiLine USB" diff --git a/source/brailleDisplayDrivers/hidBrailleStandard.py b/source/brailleDisplayDrivers/hidBrailleStandard.py index 1d6512f8c3b..105cdce7be0 100644 --- a/source/brailleDisplayDrivers/hidBrailleStandard.py +++ b/source/brailleDisplayDrivers/hidBrailleStandard.py @@ -8,6 +8,7 @@ import enum import itertools import braille +import braille.display.driver import inputCore from logHandler import log import brailleInput @@ -76,7 +77,7 @@ class ButtonCapsInfo: relativeIndexInCollection: int = 0 -class HidBrailleDriver(braille.BrailleDisplayDriver): +class HidBrailleDriver(braille.display.driver.BrailleDisplayDriver): _dev: hwIo.hid.Hid _numberOfCellsValueCaps: hidpi.HIDP_VALUE_CAPS | None = None name = "hidBrailleStandard" diff --git a/source/brailleDisplayDrivers/hims.py b/source/brailleDisplayDrivers/hims.py index 9b9d0ef4379..d567e9693fb 100644 --- a/source/brailleDisplayDrivers/hims.py +++ b/source/brailleDisplayDrivers/hims.py @@ -10,6 +10,7 @@ import hwIo from hwIo import intToByte import braille +import braille.display.driver from logHandler import log from collections import OrderedDict import inputCore @@ -269,7 +270,7 @@ def _get_keys(self): ] -class BrailleDisplayDriver(braille.BrailleDisplayDriver): +class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver): name = "hims" # Translators: The name of a series of braille displays. description = _("HIMS Braille Sense/Braille EDGE/Smart Beetle/Sync Braille series") diff --git a/source/brailleDisplayDrivers/lilli.py b/source/brailleDisplayDrivers/lilli.py index c498d4de244..7bdd668eedf 100644 --- a/source/brailleDisplayDrivers/lilli.py +++ b/source/brailleDisplayDrivers/lilli.py @@ -12,6 +12,7 @@ import inputCore import wx import braille +import braille.display.driver try: lilliDll = windll.LoadLibrary(os.path.join(globalVars.appDir, "brailleDisplayDrivers", "lilli.dll")) @@ -106,7 +107,7 @@ def convertLilliCells(cell: int) -> int: return newCell -class BrailleDisplayDriver(braille.BrailleDisplayDriver): +class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver): name = "lilli" # Translators: Name of a braille display. description = _("MDV Lilli") diff --git a/source/brailleDisplayDrivers/nattiqbraille.py b/source/brailleDisplayDrivers/nattiqbraille.py index ab3bcf6763c..9592124713b 100644 --- a/source/brailleDisplayDrivers/nattiqbraille.py +++ b/source/brailleDisplayDrivers/nattiqbraille.py @@ -7,6 +7,7 @@ import serial import bdDetect import braille +import braille.display.driver import inputCore from logHandler import log import hwIo @@ -29,7 +30,7 @@ LEFT_KEY_PRESS = 4 -class BrailleDisplayDriver(braille.BrailleDisplayDriver): +class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver): name = "nattiqbraille" # Translators: Names of braille displays description = _("Nattiq nBraille") diff --git a/source/brailleDisplayDrivers/nlseReaderZoomax.py b/source/brailleDisplayDrivers/nlseReaderZoomax.py index 72398290e43..e9d78e5fdb6 100644 --- a/source/brailleDisplayDrivers/nlseReaderZoomax.py +++ b/source/brailleDisplayDrivers/nlseReaderZoomax.py @@ -7,6 +7,7 @@ import bdDetect import braille +import braille.display.driver import brailleInput import hwIo import inputCore @@ -85,7 +86,7 @@ class DeviceResponseInfo: } -class BrailleDisplayDriver(braille.BrailleDisplayDriver): +class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver): _dev: hwIo.IoBase name = "nlseReaderZoomax" # Translators: Names of braille displays. diff --git a/source/brailleDisplayDrivers/noBraille.py b/source/brailleDisplayDrivers/noBraille.py index 420950782db..6cc32d603c8 100755 --- a/source/brailleDisplayDrivers/noBraille.py +++ b/source/brailleDisplayDrivers/noBraille.py @@ -5,9 +5,10 @@ # See the file COPYING for more details. import braille +import braille.display.driver -class BrailleDisplayDriver(braille.BrailleDisplayDriver): +class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver): """A dummy braille display driver used to disable braille in NVDA.""" name = "noBraille" diff --git a/source/brailleDisplayDrivers/papenmeier.py b/source/brailleDisplayDrivers/papenmeier.py index 5bb7ac71a6e..002242d3bed 100644 --- a/source/brailleDisplayDrivers/papenmeier.py +++ b/source/brailleDisplayDrivers/papenmeier.py @@ -11,6 +11,7 @@ import wx import braille +import braille.display.driver from logHandler import log import inputCore @@ -132,7 +133,7 @@ def brl_poll(dev: serial.Serial) -> bytes: return b"" -class BrailleDisplayDriver(braille.BrailleDisplayDriver, ScriptableObject): +class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver, ScriptableObject): """papenmeier braille display driver.""" _dev: serial.Serial diff --git a/source/brailleDisplayDrivers/papenmeier_serial.py b/source/brailleDisplayDrivers/papenmeier_serial.py index 1b9338d6994..0c0104709f1 100644 --- a/source/brailleDisplayDrivers/papenmeier_serial.py +++ b/source/brailleDisplayDrivers/papenmeier_serial.py @@ -13,6 +13,7 @@ import wx import braille +import braille.display.driver import hwPortUtils from logHandler import log from baseObject import ScriptableObject @@ -61,7 +62,7 @@ def brl_poll(dev: serial.Serial) -> bytes: return b"" -class BrailleDisplayDriver(braille.BrailleDisplayDriver, ScriptableObject): +class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver, ScriptableObject): """papenmeier_serial braille display driver.""" name = "papenmeier_serial" diff --git a/source/brailleDisplayDrivers/seika.py b/source/brailleDisplayDrivers/seika.py index 1bd2b549fac..aad5592a0fa 100644 --- a/source/brailleDisplayDrivers/seika.py +++ b/source/brailleDisplayDrivers/seika.py @@ -11,6 +11,7 @@ import wx import serial import braille +import braille.display.driver import inputCore import hwPortUtils from hwIo import intToByte @@ -22,7 +23,7 @@ BUF_START = b"\xff\xff" -class BrailleDisplayDriver(braille.BrailleDisplayDriver): +class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver): name = "seika" # Translators: Names of braille displays. description = _("Seika Braille Displays") diff --git a/source/brailleDisplayDrivers/seikantk.py b/source/brailleDisplayDrivers/seikantk.py index b4dfec86ed3..325bdbff135 100644 --- a/source/brailleDisplayDrivers/seikantk.py +++ b/source/brailleDisplayDrivers/seikantk.py @@ -16,6 +16,7 @@ import serial import braille +import braille.display.driver from bdDetect import DeviceMatch, DriverRegistrar import brailleInput import inputCore @@ -97,7 +98,7 @@ def isSeikaBluetoothDeviceMatch(match: DeviceMatch) -> bool: return isSeikaBluetoothDeviceInfo(match.deviceInfo) -class BrailleDisplayDriver(braille.BrailleDisplayDriver): +class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver): name = SEIKA_NAME # Translators: Name of a braille display. description = _("Seika Notetaker") diff --git a/source/brailleDisplayDrivers/superBrl.py b/source/brailleDisplayDrivers/superBrl.py index beef924445f..5f0a70cf7f8 100644 --- a/source/brailleDisplayDrivers/superBrl.py +++ b/source/brailleDisplayDrivers/superBrl.py @@ -8,6 +8,7 @@ import serial import bdDetect import braille +import braille.display.driver import hwIo from hwIo import intToByte import time @@ -24,7 +25,7 @@ DISPLAY_TAG = b"\xff\xff\x04\x00\x99\x00\x50\x00" -class BrailleDisplayDriver(braille.BrailleDisplayDriver): +class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver): name = "superBrl" # Translators: Names of braille displays. description = _("SuperBraille") diff --git a/source/driverHandler.py b/source/driverHandler.py index 93a14ab066f..7db356d1f92 100644 --- a/source/driverHandler.py +++ b/source/driverHandler.py @@ -12,7 +12,7 @@ class Driver(AutoSettings): """ Abstract base class for drivers, such as speech synthesizer and braille display drivers. - Abstract subclasses such as L{braille.BrailleDisplayDriver} should set L{_configSection}. + Abstract subclasses such as L{braille.display.driver.BrailleDisplayDriver} should set L{_configSection}. At a minimum, drivers must set L{name} and L{description} and override the L{check} method. From b90a5ad91e47d62c90153ed83bf9f61e4bee6fad Mon Sep 17 00:00:00 2001 From: Sascha Cowley <16543535+SaschaCowley@users.noreply.github.com> Date: Tue, 7 Jul 2026 16:42:40 +1000 Subject: [PATCH 03/15] braille.display.gesture.BrailleDisplayGesture --- source/_remoteClient/input.py | 3 +- source/_remoteClient/session.py | 8 +++- source/braille/__init__.py | 2 +- .../albatross/gestures.py | 3 +- source/brailleDisplayDrivers/alva.py | 3 +- source/brailleDisplayDrivers/baum.py | 3 +- source/brailleDisplayDrivers/brailleNote.py | 5 ++- source/brailleDisplayDrivers/brailliantB.py | 3 +- source/brailleDisplayDrivers/brltty.py | 3 +- source/brailleDisplayDrivers/dotPad/driver.py | 3 +- source/brailleDisplayDrivers/ecoBraille.py | 5 ++- .../eurobraille/gestures.py | 3 +- .../freedomScientific.py | 3 +- source/brailleDisplayDrivers/handyTech.py | 3 +- source/brailleDisplayDrivers/hedoMobilLine.py | 5 ++- source/brailleDisplayDrivers/hedoProfiLine.py | 5 ++- .../hidBrailleStandard.py | 3 +- source/brailleDisplayDrivers/hims.py | 5 ++- source/brailleDisplayDrivers/lilli.py | 3 +- source/brailleDisplayDrivers/nattiqbraille.py | 5 ++- .../brailleDisplayDrivers/nlseReaderZoomax.py | 3 +- source/brailleDisplayDrivers/papenmeier.py | 3 +- .../papenmeier_serial.py | 3 +- source/brailleDisplayDrivers/seika.py | 5 ++- source/brailleDisplayDrivers/seikantk.py | 7 ++-- .../brailleViewerInputGesture.py | 2 +- source/globalCommands.py | 7 ++-- .../test_brailleDisplayDrivers.py | 40 ++++++++++++------- .../test_displayTextForGestureIdentifier.py | 11 +++-- 29 files changed, 100 insertions(+), 57 deletions(-) diff --git a/source/_remoteClient/input.py b/source/_remoteClient/input.py index e0cc7f59047..a969b87e631 100644 --- a/source/_remoteClient/input.py +++ b/source/_remoteClient/input.py @@ -10,6 +10,7 @@ import api import baseObject import braille +import braille.display.gesture import brailleInput import globalPluginHandler import scriptHandler @@ -28,7 +29,7 @@ class VKMapType(IntEnum): """Maps a virtual key code to a scan code.""" -class BrailleInputGesture(braille.BrailleDisplayGesture, brailleInput.BrailleInputGesture): +class BrailleInputGesture(braille.display.gesture.BrailleDisplayGesture, brailleInput.BrailleInputGesture): def __init__(self, **kwargs): super().__init__() # Normalize legacy routingIndex field into cellIndexes before assignment diff --git a/source/_remoteClient/session.py b/source/_remoteClient/session.py index e7e0117b3f5..8f3427f3681 100644 --- a/source/_remoteClient/session.py +++ b/source/_remoteClient/session.py @@ -70,6 +70,7 @@ import braille import braille.display.driver +import braille.display.gesture import brailleInput import gui import inputCore @@ -608,7 +609,7 @@ def sendBrailleInfo( def handleDecideExecuteGesture( self, - gesture: braille.BrailleDisplayGesture | brailleInput.BrailleInputGesture, + gesture: braille.display.gesture.BrailleDisplayGesture | brailleInput.BrailleInputGesture, ) -> bool: """Handle and forward braille gestures to remote client. @@ -619,7 +620,10 @@ def handleDecideExecuteGesture( # Import late to avoid circular import from globalCommands import commands - if isinstance(gesture, (braille.BrailleDisplayGesture, brailleInput.BrailleInputGesture)): + if isinstance( + gesture, + (braille.display.gesture.BrailleDisplayGesture, brailleInput.BrailleInputGesture), + ): if self.localMachine._showingLocalUiMessage and gesture.script in ( commands.script_braille_routeTo, commands.script_braille_scrollBack, diff --git a/source/braille/__init__.py b/source/braille/__init__.py index 6d7a222db0b..4cfb39e699e 100644 --- a/source/braille/__init__.py +++ b/source/braille/__init__.py @@ -41,7 +41,7 @@ def terminate(): # Deprecated in 2026.3. __getattr__ = handleDeprecations( # MovedSymbol("BrailleDisplayDriver", "braille.display.driver"), - MovedSymbol("BrailleDisplayGesture", "braille.display.gesture"), + # MovedSymbol("BrailleDisplayGesture", "braille.display.gesture"), MovedSymbol("getSerialPorts", "braille.display"), MovedSymbol("getDisplayList", "braille.display"), MovedSymbol("getDisplayDrivers", "braille.display"), diff --git a/source/brailleDisplayDrivers/albatross/gestures.py b/source/brailleDisplayDrivers/albatross/gestures.py index d598f2a12be..53d1f9d8e67 100644 --- a/source/brailleDisplayDrivers/albatross/gestures.py +++ b/source/brailleDisplayDrivers/albatross/gestures.py @@ -13,6 +13,7 @@ ) import braille +import braille.display.gesture import inputCore from .constants import ( @@ -84,7 +85,7 @@ ) -class InputGestureKeys(braille.BrailleDisplayGesture): +class InputGestureKeys(braille.display.gesture.BrailleDisplayGesture): """Changes display key presses to gestures for NVDA input system.""" def __init__(self, keys: Set[int], name: str): diff --git a/source/brailleDisplayDrivers/alva.py b/source/brailleDisplayDrivers/alva.py index 73d037f00fc..ee493f4b236 100644 --- a/source/brailleDisplayDrivers/alva.py +++ b/source/brailleDisplayDrivers/alva.py @@ -8,6 +8,7 @@ import bdDetect import braille import braille.display.driver +import braille.display.gesture from logHandler import log import inputCore import brailleInput @@ -509,7 +510,7 @@ def script_toggleHidKeyboardInput(self, gesture): ) -class InputGesture(braille.BrailleDisplayGesture, brailleInput.BrailleInputGesture): +class InputGesture(braille.display.gesture.BrailleDisplayGesture, brailleInput.BrailleInputGesture): source = BrailleDisplayDriver.name def __init__(self, model, keys, brailleInput=False): diff --git a/source/brailleDisplayDrivers/baum.py b/source/brailleDisplayDrivers/baum.py index 6499f61360b..eac01d76c89 100644 --- a/source/brailleDisplayDrivers/baum.py +++ b/source/brailleDisplayDrivers/baum.py @@ -8,6 +8,7 @@ import braille import braille.display.driver +import braille.display.gesture from hwIo import intToByte, boolToByte import inputCore from logHandler import log @@ -393,7 +394,7 @@ def display(self, cells: List[int]): ) -class InputGesture(braille.BrailleDisplayGesture, brailleInput.BrailleInputGesture): +class InputGesture(braille.display.gesture.BrailleDisplayGesture, brailleInput.BrailleInputGesture): source = BrailleDisplayDriver.name def __init__(self, model, keysDown): diff --git a/source/brailleDisplayDrivers/brailleNote.py b/source/brailleDisplayDrivers/brailleNote.py index fc7bacf6ea1..a4401de0506 100644 --- a/source/brailleDisplayDrivers/brailleNote.py +++ b/source/brailleDisplayDrivers/brailleNote.py @@ -15,6 +15,7 @@ import bdDetect import braille import braille.display.driver +import braille.display.gesture import brailleInput import inputCore from logHandler import log @@ -309,7 +310,7 @@ def display(self, cells: List[int]): ) -class InputGesture(braille.BrailleDisplayGesture, brailleInput.BrailleInputGesture): +class InputGesture(braille.display.gesture.BrailleDisplayGesture, brailleInput.BrailleInputGesture): source = BrailleDisplayDriver.name def __init__( @@ -322,7 +323,7 @@ def __init__( qtMod: Optional[int] = None, qtData: Optional[str] = None, ): - super(braille.BrailleDisplayGesture, self).__init__() + super(braille.display.gesture.BrailleDisplayGesture, self).__init__() # Denotes if we're dealing with a QT model. self.qt = qtMod is not None # Handle thumb-keys and scroll wheel (wheel is for Apex BT). diff --git a/source/brailleDisplayDrivers/brailliantB.py b/source/brailleDisplayDrivers/brailliantB.py index 6ff6d4cd095..31c383429f2 100644 --- a/source/brailleDisplayDrivers/brailliantB.py +++ b/source/brailleDisplayDrivers/brailliantB.py @@ -9,6 +9,7 @@ import serial import braille import braille.display.driver +import braille.display.gesture import inputCore from logHandler import log import brailleInput @@ -382,7 +383,7 @@ def display(self, cells: List[int]): ) -class InputGesture(braille.BrailleDisplayGesture, brailleInput.BrailleInputGesture): +class InputGesture(braille.display.gesture.BrailleDisplayGesture, brailleInput.BrailleInputGesture): source = BrailleDisplayDriver.name def __init__(self, keys): diff --git a/source/brailleDisplayDrivers/brltty.py b/source/brailleDisplayDrivers/brltty.py index 15a72949cd2..f82dc01b27a 100644 --- a/source/brailleDisplayDrivers/brltty.py +++ b/source/brailleDisplayDrivers/brltty.py @@ -8,6 +8,7 @@ import wx import braille import braille.display.driver +import braille.display.gesture from logHandler import log import inputCore from typing import List @@ -144,7 +145,7 @@ def _onKeyPress(self, key): ) -class InputGesture(braille.BrailleDisplayGesture): +class InputGesture(braille.display.gesture.BrailleDisplayGesture): source = BrailleDisplayDriver.name def __init__(self, model, command, argument): diff --git a/source/brailleDisplayDrivers/dotPad/driver.py b/source/brailleDisplayDrivers/dotPad/driver.py index d65b87342e1..45c638a6875 100644 --- a/source/brailleDisplayDrivers/dotPad/driver.py +++ b/source/brailleDisplayDrivers/dotPad/driver.py @@ -13,6 +13,7 @@ import inputCore import braille import braille.display.driver +import braille.display.gesture import winBindings.kernel32 import hwIo import bdDetect @@ -505,7 +506,7 @@ def display(self, cells: list[int]): ) -class DPInputGesture(braille.BrailleDisplayGesture): +class DPInputGesture(braille.display.gesture.BrailleDisplayGesture): """Input gesture for DotPad display supporting multi-button combinations.""" source = BrailleDisplayDriver.name diff --git a/source/brailleDisplayDrivers/ecoBraille.py b/source/brailleDisplayDrivers/ecoBraille.py index 5f9962e2fd8..cd208a5beb2 100644 --- a/source/brailleDisplayDrivers/ecoBraille.py +++ b/source/brailleDisplayDrivers/ecoBraille.py @@ -9,6 +9,7 @@ import inputCore import braille import braille.display.driver +import braille.display.gesture import hwPortUtils from collections import OrderedDict from logHandler import log @@ -500,7 +501,7 @@ def _handleResponse(self, command: int): ) -class InputGestureKeys(braille.BrailleDisplayGesture): +class InputGestureKeys(braille.display.gesture.BrailleDisplayGesture): source = BrailleDisplayDriver.name def __init__(self, keys): @@ -508,7 +509,7 @@ def __init__(self, keys): self.id = keyNames[keys] -class InputGestureRouting(braille.BrailleDisplayGesture): +class InputGestureRouting(braille.display.gesture.BrailleDisplayGesture): source = BrailleDisplayDriver.name def __init__(self, index): diff --git a/source/brailleDisplayDrivers/eurobraille/gestures.py b/source/brailleDisplayDrivers/eurobraille/gestures.py index c716ae50c73..19a1c4995a1 100644 --- a/source/brailleDisplayDrivers/eurobraille/gestures.py +++ b/source/brailleDisplayDrivers/eurobraille/gestures.py @@ -5,6 +5,7 @@ from typing import TYPE_CHECKING import braille +import braille.display.gesture import brailleInput import inputCore from . import constants @@ -157,7 +158,7 @@ _gestureMap = inputCore.GlobalGestureMap(GestureMapEntries) -class InputGesture(braille.BrailleDisplayGesture, brailleInput.BrailleInputGesture): +class InputGesture(braille.display.gesture.BrailleDisplayGesture, brailleInput.BrailleInputGesture): source = constants.name def __init__(self, display: "BrailleDisplayDriver"): diff --git a/source/brailleDisplayDrivers/freedomScientific.py b/source/brailleDisplayDrivers/freedomScientific.py index a5fa4f74026..9be0dc8e083 100755 --- a/source/brailleDisplayDrivers/freedomScientific.py +++ b/source/brailleDisplayDrivers/freedomScientific.py @@ -14,6 +14,7 @@ import bdDetect import braille import braille.display.driver +import braille.display.gesture import brailleInput import hwIo import inputCore @@ -705,7 +706,7 @@ def script_toggleRightWizWheelAction(self, _gesture: inputCore.InputGesture) -> ) -class InputGesture(braille.BrailleDisplayGesture): +class InputGesture(braille.display.gesture.BrailleDisplayGesture): """Base gesture for this braille display""" source = BrailleDisplayDriver.name diff --git a/source/brailleDisplayDrivers/handyTech.py b/source/brailleDisplayDrivers/handyTech.py index 323cf60d9a0..20093473701 100644 --- a/source/brailleDisplayDrivers/handyTech.py +++ b/source/brailleDisplayDrivers/handyTech.py @@ -23,6 +23,7 @@ from hwIo import intToByte, boolToByte import braille import braille.display.driver +import braille.display.gesture import brailleInput import inputCore import ui @@ -1205,7 +1206,7 @@ def script_toggleBrailleInput(self, _gesture): ) -class InputGesture(braille.BrailleDisplayGesture, brailleInput.BrailleInputGesture): +class InputGesture(braille.display.gesture.BrailleDisplayGesture, brailleInput.BrailleInputGesture): source = BrailleDisplayDriver.name def __init__(self, model, keys, isBrailleInput=False): diff --git a/source/brailleDisplayDrivers/hedoMobilLine.py b/source/brailleDisplayDrivers/hedoMobilLine.py index 04a4fc44043..a3306ed94b0 100644 --- a/source/brailleDisplayDrivers/hedoMobilLine.py +++ b/source/brailleDisplayDrivers/hedoMobilLine.py @@ -16,6 +16,7 @@ import serial import braille import braille.display.driver +import braille.display.gesture import inputCore import hwPortUtils from logHandler import log @@ -200,7 +201,7 @@ def handleData(self, data: int): ) -class InputGestureKeys(braille.BrailleDisplayGesture): +class InputGestureKeys(braille.display.gesture.BrailleDisplayGesture): source = BrailleDisplayDriver.name def __init__(self, keys): @@ -209,7 +210,7 @@ def __init__(self, keys): self.id = keys -class InputGestureRouting(braille.BrailleDisplayGesture): +class InputGestureRouting(braille.display.gesture.BrailleDisplayGesture): source = BrailleDisplayDriver.name def __init__(self, index): diff --git a/source/brailleDisplayDrivers/hedoProfiLine.py b/source/brailleDisplayDrivers/hedoProfiLine.py index ae3cdd0c01f..f5c7b8237c2 100644 --- a/source/brailleDisplayDrivers/hedoProfiLine.py +++ b/source/brailleDisplayDrivers/hedoProfiLine.py @@ -16,6 +16,7 @@ import serial import braille import braille.display.driver +import braille.display.gesture import inputCore import hwPortUtils from logHandler import log @@ -196,7 +197,7 @@ def handleData(self, data: int): ) -class InputGestureKeys(braille.BrailleDisplayGesture): +class InputGestureKeys(braille.display.gesture.BrailleDisplayGesture): source = BrailleDisplayDriver.name def __init__(self, keys): @@ -205,7 +206,7 @@ def __init__(self, keys): self.id = keys -class InputGestureRouting(braille.BrailleDisplayGesture): +class InputGestureRouting(braille.display.gesture.BrailleDisplayGesture): source = BrailleDisplayDriver.name def __init__(self, index): diff --git a/source/brailleDisplayDrivers/hidBrailleStandard.py b/source/brailleDisplayDrivers/hidBrailleStandard.py index 105cdce7be0..85150c34ced 100644 --- a/source/brailleDisplayDrivers/hidBrailleStandard.py +++ b/source/brailleDisplayDrivers/hidBrailleStandard.py @@ -9,6 +9,7 @@ import itertools import braille import braille.display.driver +import braille.display.gesture import inputCore from logHandler import log import brailleInput @@ -312,7 +313,7 @@ def display(self, cells: List[int]): ) -class InputGesture(braille.BrailleDisplayGesture, brailleInput.BrailleInputGesture): +class InputGesture(braille.display.gesture.BrailleDisplayGesture, brailleInput.BrailleInputGesture): source = HidBrailleDriver.name def __init__(self, driver, dataIndices): diff --git a/source/brailleDisplayDrivers/hims.py b/source/brailleDisplayDrivers/hims.py index d567e9693fb..e082862e105 100644 --- a/source/brailleDisplayDrivers/hims.py +++ b/source/brailleDisplayDrivers/hims.py @@ -11,6 +11,7 @@ from hwIo import intToByte import braille import braille.display.driver +import braille.display.gesture from logHandler import log from collections import OrderedDict import inputCore @@ -795,7 +796,7 @@ def terminate(self): ) -class KeyInputGesture(braille.BrailleDisplayGesture, brailleInput.BrailleInputGesture): +class KeyInputGesture(braille.display.gesture.BrailleDisplayGesture, brailleInput.BrailleInputGesture): source = BrailleDisplayDriver.name def __init__(self, model, keys, isHid: bool = False): @@ -832,7 +833,7 @@ def __init__(self, model, keys, isHid: bool = False): self.id = "+".join(names) -class RoutingInputGesture(braille.BrailleDisplayGesture): +class RoutingInputGesture(braille.display.gesture.BrailleDisplayGesture): source = BrailleDisplayDriver.name def __init__(self, routingIndex: int): diff --git a/source/brailleDisplayDrivers/lilli.py b/source/brailleDisplayDrivers/lilli.py index 7bdd668eedf..00a16b5c2bf 100644 --- a/source/brailleDisplayDrivers/lilli.py +++ b/source/brailleDisplayDrivers/lilli.py @@ -13,6 +13,7 @@ import wx import braille import braille.display.driver +import braille.display.gesture try: lilliDll = windll.LoadLibrary(os.path.join(globalVars.appDir, "brailleDisplayDrivers", "lilli.dll")) @@ -183,7 +184,7 @@ def display(self, cells: List[int]): ) -class InputGesture(braille.BrailleDisplayGesture): +class InputGesture(braille.display.gesture.BrailleDisplayGesture): source = BrailleDisplayDriver.name def __init__(self, command: str, argument: int): diff --git a/source/brailleDisplayDrivers/nattiqbraille.py b/source/brailleDisplayDrivers/nattiqbraille.py index 9592124713b..611184d00ec 100644 --- a/source/brailleDisplayDrivers/nattiqbraille.py +++ b/source/brailleDisplayDrivers/nattiqbraille.py @@ -8,6 +8,7 @@ import bdDetect import braille import braille.display.driver +import braille.display.gesture import inputCore from logHandler import log import hwIo @@ -136,7 +137,7 @@ def display(self, cells): ) -class InputGestureKeys(braille.BrailleDisplayGesture): +class InputGestureKeys(braille.display.gesture.BrailleDisplayGesture): source = BrailleDisplayDriver.name def __init__(self, keys): @@ -151,7 +152,7 @@ def __init__(self, keys): self.id = "tprevious" -class RoutingInputGesture(braille.BrailleDisplayGesture): +class RoutingInputGesture(braille.display.gesture.BrailleDisplayGesture): source = BrailleDisplayDriver.name def __init__(self, routingIndex): diff --git a/source/brailleDisplayDrivers/nlseReaderZoomax.py b/source/brailleDisplayDrivers/nlseReaderZoomax.py index e9d78e5fdb6..de9d767b9c3 100644 --- a/source/brailleDisplayDrivers/nlseReaderZoomax.py +++ b/source/brailleDisplayDrivers/nlseReaderZoomax.py @@ -8,6 +8,7 @@ import bdDetect import braille import braille.display.driver +import braille.display.gesture import brailleInput import hwIo import inputCore @@ -247,7 +248,7 @@ def display(self, cells: list[int]): ) -class InputGesture(braille.BrailleDisplayGesture, brailleInput.BrailleInputGesture): +class InputGesture(braille.display.gesture.BrailleDisplayGesture, brailleInput.BrailleInputGesture): source = BrailleDisplayDriver.name def __init__(self, keysDown: dict[bytes, bytes]): diff --git a/source/brailleDisplayDrivers/papenmeier.py b/source/brailleDisplayDrivers/papenmeier.py index 002242d3bed..63022492dda 100644 --- a/source/brailleDisplayDrivers/papenmeier.py +++ b/source/brailleDisplayDrivers/papenmeier.py @@ -12,6 +12,7 @@ import wx import braille import braille.display.driver +import braille.display.gesture from logHandler import log import inputCore @@ -622,7 +623,7 @@ def brl_join_keys(dec: List[str]) -> str: return "" -class InputGesture(braille.BrailleDisplayGesture, brailleInput.BrailleInputGesture): +class InputGesture(braille.display.gesture.BrailleDisplayGesture, brailleInput.BrailleInputGesture): """Input gesture for papenmeier displays""" source = BrailleDisplayDriver.name diff --git a/source/brailleDisplayDrivers/papenmeier_serial.py b/source/brailleDisplayDrivers/papenmeier_serial.py index 0c0104709f1..a75a08eebf0 100644 --- a/source/brailleDisplayDrivers/papenmeier_serial.py +++ b/source/brailleDisplayDrivers/papenmeier_serial.py @@ -14,6 +14,7 @@ import wx import braille import braille.display.driver +import braille.display.gesture import hwPortUtils from logHandler import log from baseObject import ScriptableObject @@ -288,7 +289,7 @@ def brl_keyname(keyindex: int, driver: BrailleDisplayDriver) -> str: return "" -class InputGesture(braille.BrailleDisplayGesture): +class InputGesture(braille.display.gesture.BrailleDisplayGesture): """input gesture class for papenmeier_serial displays used only by the driver""" source = BrailleDisplayDriver.name diff --git a/source/brailleDisplayDrivers/seika.py b/source/brailleDisplayDrivers/seika.py index aad5592a0fa..5725929668f 100644 --- a/source/brailleDisplayDrivers/seika.py +++ b/source/brailleDisplayDrivers/seika.py @@ -12,6 +12,7 @@ import serial import braille import braille.display.driver +import braille.display.gesture import inputCore import hwPortUtils from hwIo import intToByte @@ -207,7 +208,7 @@ def _handleNormalKey(self, chars: bytes) -> None: ) -class InputGestureKeys(braille.BrailleDisplayGesture): +class InputGestureKeys(braille.display.gesture.BrailleDisplayGesture): source = BrailleDisplayDriver.name def __init__(self, keys): @@ -215,7 +216,7 @@ def __init__(self, keys): self.id = keys -class InputGestureRouting(braille.BrailleDisplayGesture): +class InputGestureRouting(braille.display.gesture.BrailleDisplayGesture): source = BrailleDisplayDriver.name def __init__(self, index): diff --git a/source/brailleDisplayDrivers/seikantk.py b/source/brailleDisplayDrivers/seikantk.py index 325bdbff135..90d1d65e63d 100644 --- a/source/brailleDisplayDrivers/seikantk.py +++ b/source/brailleDisplayDrivers/seikantk.py @@ -17,6 +17,7 @@ import braille import braille.display.driver +import braille.display.gesture from bdDetect import DeviceMatch, DriverRegistrar import brailleInput import inputCore @@ -366,7 +367,7 @@ def _handleKeysRouting(self, arg: bytes): ) -class InputGestureRouting(braille.BrailleDisplayGesture): +class InputGestureRouting(braille.display.gesture.BrailleDisplayGesture): source = BrailleDisplayDriver.name def __init__(self, indexes: list[int] | int): @@ -394,11 +395,11 @@ def _getRoutingIndexes(routingKeyBytes: bytes) -> Set[int]: return {i for i in range(numRoutingKeys) if (1 << i) & combinedRoutingKeysBitSet} -class InputGesture(braille.BrailleDisplayGesture, brailleInput.BrailleInputGesture): +class InputGesture(braille.display.gesture.BrailleDisplayGesture, brailleInput.BrailleInputGesture): source = BrailleDisplayDriver.name def __init__(self, keys=None, dots=None, space=0, routing=None): - super(braille.BrailleDisplayGesture, self).__init__() + super(braille.display.gesture.BrailleDisplayGesture, self).__init__() # see what thumb keys are pressed: names = set() if keys is not None: diff --git a/source/brailleViewer/brailleViewerInputGesture.py b/source/brailleViewer/brailleViewerInputGesture.py index 3c04e6414e8..8f761a72c5a 100644 --- a/source/brailleViewer/brailleViewerInputGesture.py +++ b/source/brailleViewer/brailleViewerInputGesture.py @@ -2,7 +2,7 @@ # Copyright (C) 2020 NV Access Limited # This file is covered by the GNU General Public License. # See the file COPYING for more details. -from braille import BrailleDisplayGesture +from braille.display.gesture import BrailleDisplayGesture driverName = "brailleViewer" diff --git a/source/globalCommands.py b/source/globalCommands.py index 5edccc93128..a68a75ccb50 100755 --- a/source/globalCommands.py +++ b/source/globalCommands.py @@ -62,6 +62,7 @@ from scriptHandler import script, getLastScriptRepeatCount import ui import braille +import braille.display.gesture import brailleInput import inputCore import characterProcessing @@ -4266,7 +4267,7 @@ def script_braille_scrollForward(self, gesture): description=_("Routes the cursor to or activates the object under this braille cell"), category=SCRCAT_BRAILLE, ) - def script_braille_routeTo(self, gesture: braille.BrailleDisplayGesture): + def script_braille_routeTo(self, gesture: braille.display.gesture.BrailleDisplayGesture): if not gesture.cellIndexes: return braille.handler.routeTo(gesture.cellIndexes[0]) @@ -4276,7 +4277,7 @@ def script_braille_routeTo(self, gesture: braille.BrailleDisplayGesture): description=_("Reports formatting info for the text under this braille cell"), category=SCRCAT_BRAILLE, ) - def script_braille_reportFormatting(self, gesture: braille.BrailleDisplayGesture): + def script_braille_reportFormatting(self, gesture: braille.display.gesture.BrailleDisplayGesture): if not gesture.cellIndexes: return info = braille.handler.getTextInfoForWindowPos(gesture.cellIndexes[0]) @@ -4291,7 +4292,7 @@ def script_braille_reportFormatting(self, gesture: braille.BrailleDisplayGesture description=_("Selects the text from the first up to the last braille cell"), category=SCRCAT_BRAILLE, ) - def script_braille_selectRange(self, gesture: braille.BrailleDisplayGesture): + def script_braille_selectRange(self, gesture: braille.display.gesture.BrailleDisplayGesture): if not gesture.cellIndexes or len(gesture.cellIndexes) < 2: return startPos = min(gesture.cellIndexes) diff --git a/tests/unit/test_braille/test_brailleDisplayDrivers.py b/tests/unit/test_braille/test_brailleDisplayDrivers.py index fcaaf8c3a08..9e7be92bce6 100644 --- a/tests/unit/test_braille/test_brailleDisplayDrivers.py +++ b/tests/unit/test_braille/test_brailleDisplayDrivers.py @@ -9,6 +9,7 @@ import unittest import braille import braille.display +import braille.display.gesture class FakeSeikantkDriver(seikantk.BrailleDisplayDriver): @@ -176,26 +177,26 @@ def test_identifiers(self): continue for cls, gesture, scriptName in gmap.getScriptsForAllGestures(): if gesture.startswith("br"): - self.assertRegex(gesture, braille.BrailleDisplayGesture.ID_PARTS_REGEX) + self.assertRegex(gesture, braille.display.gesture.BrailleDisplayGesture.ID_PARTS_REGEX) -class _RoutingGesture(braille.BrailleDisplayGesture): +class _RoutingGesture(braille.display.gesture.BrailleDisplayGesture): source = "test" id = "routing" -class _MultiRoutingGesture(braille.BrailleDisplayGesture): +class _MultiRoutingGesture(braille.display.gesture.BrailleDisplayGesture): source = "test" id = "multiRouting" -class _ModelRoutingGesture(braille.BrailleDisplayGesture): +class _ModelRoutingGesture(braille.display.gesture.BrailleDisplayGesture): source = "testDriver" model = "testModel" id = "routing" -class _ComboGesture(braille.BrailleDisplayGesture): +class _ComboGesture(braille.display.gesture.BrailleDisplayGesture): """Gesture whose id contains '+', simulating a routing key combined with a modifier.""" source = "test" @@ -210,20 +211,29 @@ def test_default_cellIndexes_none(self): self.assertIsNone(g.cellIndexes) def test_idForCellCount(self): - self.assertEqual("routing", braille.BrailleDisplayGesture.idForCellCount(0)) - self.assertEqual("routing", braille.BrailleDisplayGesture.idForCellCount(1)) - self.assertEqual("multiRouting", braille.BrailleDisplayGesture.idForCellCount(2)) - self.assertEqual("multiRouting", braille.BrailleDisplayGesture.idForCellCount(5)) + self.assertEqual("routing", braille.display.gesture.BrailleDisplayGesture.idForCellCount(0)) + self.assertEqual("routing", braille.display.gesture.BrailleDisplayGesture.idForCellCount(1)) + self.assertEqual("multiRouting", braille.display.gesture.BrailleDisplayGesture.idForCellCount(2)) + self.assertEqual("multiRouting", braille.display.gesture.BrailleDisplayGesture.idForCellCount(5)) def test_idForCellCount_custom_baseName(self): - self.assertEqual("secondRouting", braille.BrailleDisplayGesture.idForCellCount(1, "secondRouting")) + self.assertEqual( + "secondRouting", + braille.display.gesture.BrailleDisplayGesture.idForCellCount(1, "secondRouting"), + ) self.assertEqual( "multiSecondRouting", - braille.BrailleDisplayGesture.idForCellCount(2, "secondRouting"), + braille.display.gesture.BrailleDisplayGesture.idForCellCount(2, "secondRouting"), + ) + self.assertEqual("route", braille.display.gesture.BrailleDisplayGesture.idForCellCount(1, "route")) + self.assertEqual( + "multiRoute", + braille.display.gesture.BrailleDisplayGesture.idForCellCount(2, "route"), + ) + self.assertEqual( + "multiUpperRouting", + braille.display.gesture.BrailleDisplayGesture.idForCellCount(3, "upperRouting"), ) - self.assertEqual("route", braille.BrailleDisplayGesture.idForCellCount(1, "route")) - self.assertEqual("multiRoute", braille.BrailleDisplayGesture.idForCellCount(2, "route")) - self.assertEqual("multiUpperRouting", braille.BrailleDisplayGesture.idForCellCount(3, "upperRouting")) def test_routingIndex_getter_returns_highest_cell(self): g = _RoutingGesture() @@ -250,7 +260,7 @@ def test_multiRouting_identifier_matches_regex(self): g.cellIndexes = [0, 3, 7] for identifier in g.identifiers: if identifier.startswith("br"): - self.assertRegex(identifier, braille.BrailleDisplayGesture.ID_PARTS_REGEX) + self.assertRegex(identifier, braille.display.gesture.BrailleDisplayGesture.ID_PARTS_REGEX) def test_cellIndexesStr_none_when_no_cellIndexes(self): g = _RoutingGesture() diff --git a/tests/unit/test_braille/test_displayTextForGestureIdentifier.py b/tests/unit/test_braille/test_displayTextForGestureIdentifier.py index 0db7f6cad8d..6ed869caa6a 100644 --- a/tests/unit/test_braille/test_displayTextForGestureIdentifier.py +++ b/tests/unit/test_braille/test_displayTextForGestureIdentifier.py @@ -6,6 +6,7 @@ """Unit tests for the BrailleDisplayGesture classes in the braille module.""" import braille +import braille.display.gesture import unittest @@ -13,7 +14,7 @@ class TestDisplayTextForGestureIdentifier(unittest.TestCase): """A test for the regular expression code that handles display gesture identifiers.""" def test_regex(self): - regex = braille.BrailleDisplayGesture.ID_PARTS_REGEX + regex = braille.display.gesture.BrailleDisplayGesture.ID_PARTS_REGEX self.assertEqual( regex.match("br(noBraille.noModel):noKey1+noKey2").groups(), ("noBraille", "noModel", "noKey1+noKey2"), @@ -30,12 +31,16 @@ def test_regex(self): def test_identifierWithModel(self): self.assertEqual( - braille.BrailleDisplayGesture.getDisplayTextForIdentifier("br(noBraille.noModel):noKey1+noKey2"), + braille.display.gesture.BrailleDisplayGesture.getDisplayTextForIdentifier( + "br(noBraille.noModel):noKey1+noKey2", + ), ("No braille", "noModel: noKey1+noKey2"), ) def test_identifierWithoutModel(self): self.assertEqual( - braille.BrailleDisplayGesture.getDisplayTextForIdentifier("br(noBraille):noKey1+noKey2"), + braille.display.gesture.BrailleDisplayGesture.getDisplayTextForIdentifier( + "br(noBraille):noKey1+noKey2", + ), ("No braille", "noKey1+noKey2"), ) From c790b08ce21ee57ed934b596ee48799af64d4b96 Mon Sep 17 00:00:00 2001 From: Sascha Cowley <16543535+SaschaCowley@users.noreply.github.com> Date: Tue, 7 Jul 2026 17:18:46 +1000 Subject: [PATCH 04/15] braille.display.{DisplayDimensions, getDisplayDrivers, getDisplayList, getSerialPorts, RENAMED_DRIVERS} --- source/_remoteClient/localMachine.py | 8 ++++++-- source/_remoteClient/session.py | 3 ++- source/bdDetect.py | 2 +- source/braille/__init__.py | 10 +++++----- source/brailleDisplayDrivers/albatross/driver.py | 3 ++- source/brailleDisplayDrivers/alva.py | 3 ++- source/brailleDisplayDrivers/baum.py | 3 ++- source/brailleDisplayDrivers/brailleNote.py | 3 ++- source/brailleDisplayDrivers/brailliantB.py | 3 ++- source/brailleDisplayDrivers/dotPad/driver.py | 3 ++- source/brailleDisplayDrivers/eurobraille/driver.py | 3 ++- source/brailleDisplayDrivers/handyTech.py | 3 ++- source/brailleDisplayDrivers/hims.py | 3 ++- source/brailleDisplayDrivers/nattiqbraille.py | 3 ++- source/brailleDisplayDrivers/seikantk.py | 3 ++- source/brailleDisplayDrivers/superBrl.py | 3 ++- source/brailleViewer/__init__.py | 4 ++-- source/gui/settingsDialogs.py | 2 +- .../libraries/SystemTestSpy/speechSpyGlobalPlugin.py | 2 +- tests/unit/__init__.py | 7 +++++-- tests/unit/test_braille/test_brailleDisplayDrivers.py | 2 +- .../test_calculateWindowRowBufferOffsets.py | 5 +++-- tests/unit/test_braille/test_handlerExtensionPoints.py | 5 +++-- tests/unit/test_braille/test_windowBrailleCells.py | 5 +++-- 24 files changed, 57 insertions(+), 34 deletions(-) diff --git a/source/_remoteClient/localMachine.py b/source/_remoteClient/localMachine.py index 49e5f189c01..b0c5cedc186 100644 --- a/source/_remoteClient/localMachine.py +++ b/source/_remoteClient/localMachine.py @@ -26,6 +26,7 @@ import winBindings.sas import api import braille +import braille.display import braille.extensions from config.registry import RegistryKey import inputCore @@ -274,7 +275,10 @@ def setBrailleDisplaySize(self, sizes: list[int]) -> None: """ self._cachedSizes = sizes - def _handleFilterDisplayDimensions(self, value: braille.DisplayDimensions) -> braille.DisplayDimensions: + def _handleFilterDisplayDimensions( + self, + value: braille.display.DisplayDimensions, + ) -> braille.display.DisplayDimensions: """Filter the local display dimensions based on remote display dimensions. Determines the optimal display dimensions when sharing braille output by @@ -294,7 +298,7 @@ def _handleFilterDisplayDimensions(self, value: braille.DisplayDimensions) -> br # There is no point storing the number of rows if we are always going to set it to 1. sizes = self._cachedSizes + [value.numCols] try: - return braille.DisplayDimensions(numRows=1, numCols=min(i for i in sizes if i > 0)) + return braille.display.DisplayDimensions(numRows=1, numCols=min(i for i in sizes if i > 0)) except ValueError: return value._replace(numRows=1) diff --git a/source/_remoteClient/session.py b/source/_remoteClient/session.py index 8f3427f3681..508ba78d814 100644 --- a/source/_remoteClient/session.py +++ b/source/_remoteClient/session.py @@ -69,6 +69,7 @@ from typing import Any, Final import braille +import braille.display import braille.display.driver import braille.display.gesture import brailleInput @@ -593,7 +594,7 @@ def handleClientDisconnected(self, client: dict[str, Any] | None = None): def sendBrailleInfo( self, display: braille.display.driver.BrailleDisplayDriver | None = None, - displayDimensions: braille.DisplayDimensions | None = None, + displayDimensions: braille.display.DisplayDimensions | None = None, ) -> None: if display is None: display = braille.handler.display diff --git a/source/bdDetect.py b/source/bdDetect.py index b9929f766ca..d34d070ce11 100644 --- a/source/bdDetect.py +++ b/source/bdDetect.py @@ -726,7 +726,7 @@ def driverIsEnabledForAutoDetection(driver: str) -> bool: def getSupportedBrailleDisplayDrivers( onlyEnabled: bool = False, ) -> Generator[type["braille.display.driver.BrailleDisplayDriver"], Any, Any]: - return braille.getDisplayDrivers( + return braille.display.getDisplayDrivers( lambda d: ( d.isThreadSafe and d.supportsAutomaticDetection diff --git a/source/braille/__init__.py b/source/braille/__init__.py index 4cfb39e699e..d9099bbd46d 100644 --- a/source/braille/__init__.py +++ b/source/braille/__init__.py @@ -42,11 +42,11 @@ def terminate(): __getattr__ = handleDeprecations( # MovedSymbol("BrailleDisplayDriver", "braille.display.driver"), # MovedSymbol("BrailleDisplayGesture", "braille.display.gesture"), - MovedSymbol("getSerialPorts", "braille.display"), - MovedSymbol("getDisplayList", "braille.display"), - MovedSymbol("getDisplayDrivers", "braille.display"), - MovedSymbol("RENAMED_DRIVERS", "braille.display"), - MovedSymbol("DisplayDimensions", "braille.display"), + # MovedSymbol("getSerialPorts", "braille.display"), + # MovedSymbol("getDisplayList", "braille.display"), + # MovedSymbol("getDisplayDrivers", "braille.display"), + # MovedSymbol("RENAMED_DRIVERS", "braille.display"), + # MovedSymbol("DisplayDimensions", "braille.display"), MovedSymbol("Region", "braille.regions.base"), MovedSymbol("RegionWithPositions", "braille.regions.base"), MovedSymbol("TextRegion", "braille.regions.base"), diff --git a/source/brailleDisplayDrivers/albatross/driver.py b/source/brailleDisplayDrivers/albatross/driver.py index c879ffe6cab..27e0c75198c 100644 --- a/source/brailleDisplayDrivers/albatross/driver.py +++ b/source/brailleDisplayDrivers/albatross/driver.py @@ -31,6 +31,7 @@ ) import braille +import braille.display import braille.display.driver import inputCore import ui @@ -94,7 +95,7 @@ def registerAutomaticDetection(cls, driverRegistrar: DriverRegistrar): @classmethod def getManualPorts(cls): - return braille.getSerialPorts() + return braille.display.getSerialPorts() def __init__(self, port: str = "auto"): super().__init__() diff --git a/source/brailleDisplayDrivers/alva.py b/source/brailleDisplayDrivers/alva.py index ee493f4b236..ee1fd9bb85f 100644 --- a/source/brailleDisplayDrivers/alva.py +++ b/source/brailleDisplayDrivers/alva.py @@ -7,6 +7,7 @@ import bdDetect import braille +import braille.display import braille.display.driver import braille.display.gesture from logHandler import log @@ -171,7 +172,7 @@ def registerAutomaticDetection(cls, driverRegistrar: bdDetect.DriverRegistrar): @classmethod def getManualPorts(cls): - return braille.getSerialPorts( + return braille.display.getSerialPorts( filterFunc=lambda info: info.get("bluetoothName", "").startswith("ALVA "), ) diff --git a/source/brailleDisplayDrivers/baum.py b/source/brailleDisplayDrivers/baum.py index eac01d76c89..4098d375a0e 100644 --- a/source/brailleDisplayDrivers/baum.py +++ b/source/brailleDisplayDrivers/baum.py @@ -7,6 +7,7 @@ from typing import Union, List, Optional import braille +import braille.display import braille.display.driver import braille.display.gesture from hwIo import intToByte, boolToByte @@ -156,7 +157,7 @@ def registerAutomaticDetection(cls, driverRegistrar: bdDetect.DriverRegistrar): @classmethod def getManualPorts(cls): - return braille.getSerialPorts() + return braille.display.getSerialPorts() def __init__(self, port="auto"): super(BrailleDisplayDriver, self).__init__() diff --git a/source/brailleDisplayDrivers/brailleNote.py b/source/brailleDisplayDrivers/brailleNote.py index a4401de0506..29ecb7d8fbb 100644 --- a/source/brailleDisplayDrivers/brailleNote.py +++ b/source/brailleDisplayDrivers/brailleNote.py @@ -14,6 +14,7 @@ import serial import bdDetect import braille +import braille.display import braille.display.driver import braille.display.gesture import brailleInput @@ -151,7 +152,7 @@ def registerAutomaticDetection(cls, driverRegistrar: bdDetect.DriverRegistrar): @classmethod def getManualPorts(cls): - return braille.getSerialPorts() + return braille.display.getSerialPorts() def __init__(self, port="auto"): super(BrailleDisplayDriver, self).__init__() diff --git a/source/brailleDisplayDrivers/brailliantB.py b/source/brailleDisplayDrivers/brailliantB.py index 31c383429f2..f1333e5e8bf 100644 --- a/source/brailleDisplayDrivers/brailliantB.py +++ b/source/brailleDisplayDrivers/brailliantB.py @@ -8,6 +8,7 @@ import serial import braille +import braille.display import braille.display.driver import braille.display.gesture import inputCore @@ -157,7 +158,7 @@ def registerAutomaticDetection(cls, driverRegistrar: bdDetect.DriverRegistrar): @classmethod def getManualPorts(cls): - return braille.getSerialPorts() + return braille.display.getSerialPorts() def __init__(self, port="auto"): super(BrailleDisplayDriver, self).__init__() diff --git a/source/brailleDisplayDrivers/dotPad/driver.py b/source/brailleDisplayDrivers/dotPad/driver.py index 45c638a6875..a64a87b710f 100644 --- a/source/brailleDisplayDrivers/dotPad/driver.py +++ b/source/brailleDisplayDrivers/dotPad/driver.py @@ -12,6 +12,7 @@ import serial import inputCore import braille +import braille.display import braille.display.driver import braille.display.gesture import winBindings.kernel32 @@ -99,7 +100,7 @@ class BrailleDisplayDriver(braille.display.driver.BrailleDisplayDriver): @classmethod def getManualPorts(cls): - return braille.getSerialPorts() + return braille.display.getSerialPorts() @classmethod def registerAutomaticDetection(cls, driverRegistrar: bdDetect.DriverRegistrar): diff --git a/source/brailleDisplayDrivers/eurobraille/driver.py b/source/brailleDisplayDrivers/eurobraille/driver.py index 702d1cece80..5ff62fb52e5 100644 --- a/source/brailleDisplayDrivers/eurobraille/driver.py +++ b/source/brailleDisplayDrivers/eurobraille/driver.py @@ -11,6 +11,7 @@ import serial import bdDetect import braille +import braille.display import braille.display.driver import inputCore from logHandler import log @@ -81,7 +82,7 @@ def registerAutomaticDetection(cls, driverRegistrar: bdDetect.DriverRegistrar): @classmethod def getManualPorts(cls): - return braille.getSerialPorts() + return braille.display.getSerialPorts() def __init__(self, port="Auto"): super().__init__() diff --git a/source/brailleDisplayDrivers/handyTech.py b/source/brailleDisplayDrivers/handyTech.py index 20093473701..828d1f477a5 100644 --- a/source/brailleDisplayDrivers/handyTech.py +++ b/source/brailleDisplayDrivers/handyTech.py @@ -22,6 +22,7 @@ import hwIo from hwIo import intToByte, boolToByte import braille +import braille.display import braille.display.driver import braille.display.gesture import brailleInput @@ -758,7 +759,7 @@ def registerAutomaticDetection(cls, driverRegistrar: bdDetect.DriverRegistrar): @classmethod def getManualPorts(cls): - return braille.getSerialPorts() + return braille.display.getSerialPorts() _dev: Optional[Union[hwIo.Hid, hwIo.Serial]] diff --git a/source/brailleDisplayDrivers/hims.py b/source/brailleDisplayDrivers/hims.py index e082862e105..464e8e259fa 100644 --- a/source/brailleDisplayDrivers/hims.py +++ b/source/brailleDisplayDrivers/hims.py @@ -10,6 +10,7 @@ import hwIo from hwIo import intToByte import braille +import braille.display import braille.display.driver import braille.display.gesture from logHandler import log @@ -320,7 +321,7 @@ def registerAutomaticDetection(cls, driverRegistrar: bdDetect.DriverRegistrar): @classmethod def getManualPorts(cls) -> Iterator[tuple[str, str]]: - return braille.getSerialPorts() + return braille.display.getSerialPorts() def __init__(self, port="auto"): super(BrailleDisplayDriver, self).__init__() diff --git a/source/brailleDisplayDrivers/nattiqbraille.py b/source/brailleDisplayDrivers/nattiqbraille.py index 611184d00ec..b0eab29994b 100644 --- a/source/brailleDisplayDrivers/nattiqbraille.py +++ b/source/brailleDisplayDrivers/nattiqbraille.py @@ -7,6 +7,7 @@ import serial import bdDetect import braille +import braille.display import braille.display.driver import braille.display.gesture import inputCore @@ -49,7 +50,7 @@ def registerAutomaticDetection(cls, driverRegistrar: bdDetect.DriverRegistrar): @classmethod def getManualPorts(cls): - return braille.getSerialPorts() + return braille.display.getSerialPorts() def __init__(self, port="auto"): super(BrailleDisplayDriver, self).__init__() diff --git a/source/brailleDisplayDrivers/seikantk.py b/source/brailleDisplayDrivers/seikantk.py index 90d1d65e63d..c286c2639fd 100644 --- a/source/brailleDisplayDrivers/seikantk.py +++ b/source/brailleDisplayDrivers/seikantk.py @@ -16,6 +16,7 @@ import serial import braille +import braille.display import braille.display.driver import braille.display.gesture from bdDetect import DeviceMatch, DriverRegistrar @@ -120,7 +121,7 @@ def registerAutomaticDetection(cls, driverRegistrar: DriverRegistrar): @classmethod def getManualPorts(cls) -> typing.Iterator[typing.Tuple[str, str]]: """@return: An iterator containing the name and description for each port.""" - return braille.getSerialPorts(isSeikaBluetoothDeviceInfo) + return braille.display.getSerialPorts(isSeikaBluetoothDeviceInfo) def __init__(self, port: typing.Union[None, str, DeviceMatch]): super().__init__() diff --git a/source/brailleDisplayDrivers/superBrl.py b/source/brailleDisplayDrivers/superBrl.py index 5f0a70cf7f8..10f0bc32c5b 100644 --- a/source/brailleDisplayDrivers/superBrl.py +++ b/source/brailleDisplayDrivers/superBrl.py @@ -8,6 +8,7 @@ import serial import bdDetect import braille +import braille.display import braille.display.driver import hwIo from hwIo import intToByte @@ -43,7 +44,7 @@ def registerAutomaticDetection(cls, driverRegistrar: bdDetect.DriverRegistrar): @classmethod def getManualPorts(cls): - return braille.getSerialPorts() + return braille.display.getSerialPorts() def __init__(self, port="Auto"): super(BrailleDisplayDriver, self).__init__() diff --git a/source/brailleViewer/__init__.py b/source/brailleViewer/__init__.py index b1df1ca5df9..1339f54182a 100644 --- a/source/brailleViewer/__init__.py +++ b/source/brailleViewer/__init__.py @@ -12,7 +12,7 @@ from .brailleViewerGui import BrailleViewerFrame if typing.TYPE_CHECKING: - from braille import DisplayDimensions + from braille.display import DisplayDimensions """ ### Overview @@ -94,7 +94,7 @@ def _onGuiDestroyed(): def _getDisplayDimensions(dimensions: "DisplayDimensions") -> "DisplayDimensions": """Called by the :attr:`braille.filter_displayDimensions` extension point to get the display dimensions.""" - from braille import DisplayDimensions # imported late to avoid a circular import. + from braille.display import DisplayDimensions # imported late to avoid a circular import. return DisplayDimensions( numRows=1, diff --git a/source/gui/settingsDialogs.py b/source/gui/settingsDialogs.py index 5deff2d1f7b..66909d90b22 100644 --- a/source/gui/settingsDialogs.py +++ b/source/gui/settingsDialogs.py @@ -5098,7 +5098,7 @@ def getCurrentAutoDisplayDescription(): def updateBrailleDisplayLists(self): driverList = [(braille.AUTO_DISPLAY_NAME, self.getCurrentAutoDisplayDescription())] - driverList.extend(braille.getDisplayList()) + driverList.extend(braille.display.getDisplayList()) self.displayNames = [driver[0] for driver in driverList] displayChoices = [driver[1] for driver in driverList] self.displayList.Clear() diff --git a/tests/system/libraries/SystemTestSpy/speechSpyGlobalPlugin.py b/tests/system/libraries/SystemTestSpy/speechSpyGlobalPlugin.py index ea251d30326..bb2cfa6be0a 100644 --- a/tests/system/libraries/SystemTestSpy/speechSpyGlobalPlugin.py +++ b/tests/system/libraries/SystemTestSpy/speechSpyGlobalPlugin.py @@ -15,7 +15,7 @@ Optional, Tuple, ) -from braille import DisplayDimensions +from braille.display import DisplayDimensions import core import globalPluginHandler import threading diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py index c5626f4fb17..db30b3960d0 100644 --- a/tests/unit/__init__.py +++ b/tests/unit/__init__.py @@ -88,6 +88,7 @@ speech.initialize() import braille # noqa: E402 +import braille.display # noqa: E402 # Disable auto detection of braille displays when unit testing. config.conf["braille"]["display"] = "noBraille" @@ -96,8 +97,10 @@ # For braille unit tests, we need to enable the braille handler by providing it display dimensions # Give the display one row with 40 cells -def getFakeDisplayDimensions(dimensions: braille.DisplayDimensions) -> braille.DisplayDimensions: - return braille.DisplayDimensions(numRows=1, numCols=40) +def getFakeDisplayDimensions( + dimensions: braille.display.DisplayDimensions, +) -> braille.display.DisplayDimensions: + return braille.display.DisplayDimensions(numRows=1, numCols=40) braille.filter_displayDimensions.register(getFakeDisplayDimensions) diff --git a/tests/unit/test_braille/test_brailleDisplayDrivers.py b/tests/unit/test_braille/test_brailleDisplayDrivers.py index 9e7be92bce6..1a1d9bc0254 100644 --- a/tests/unit/test_braille/test_brailleDisplayDrivers.py +++ b/tests/unit/test_braille/test_brailleDisplayDrivers.py @@ -170,7 +170,7 @@ class TestGestureMap(unittest.TestCase): def test_identifiers(self): """Checks whether all defined braille display gestures contain valid braille display key identifiers.""" - for name, description in braille.getDisplayList(excludeNegativeChecks=False): + for name, description in braille.display.getDisplayList(excludeNegativeChecks=False): driver = braille.display._getDisplayDriver(name) gmap = driver.gestureMap if not gmap: diff --git a/tests/unit/test_braille/test_calculateWindowRowBufferOffsets.py b/tests/unit/test_braille/test_calculateWindowRowBufferOffsets.py index 9f56b93c566..e3ec379eb4b 100644 --- a/tests/unit/test_braille/test_calculateWindowRowBufferOffsets.py +++ b/tests/unit/test_braille/test_calculateWindowRowBufferOffsets.py @@ -10,14 +10,15 @@ import braille import braille.buffers +import braille.display import config from config.featureFlag import FeatureFlag from config.featureFlagEnums import BrailleTextWrapFlag -def _getDisplayDimensions(dimensions: braille.DisplayDimensions) -> braille.DisplayDimensions: +def _getDisplayDimensions(dimensions: braille.display.DisplayDimensions) -> braille.display.DisplayDimensions: """Used to build a braille handler with particular dimensions.""" - return braille.DisplayDimensions( + return braille.display.DisplayDimensions( numRows=2, numCols=20, ) diff --git a/tests/unit/test_braille/test_handlerExtensionPoints.py b/tests/unit/test_braille/test_handlerExtensionPoints.py index 3a4927e6894..d0898a9db05 100644 --- a/tests/unit/test_braille/test_handlerExtensionPoints.py +++ b/tests/unit/test_braille/test_handlerExtensionPoints.py @@ -6,6 +6,7 @@ """Unit tests for the extension points in the braille module.""" import braille +import braille.display from ..extensionPointTestHelpers import actionTester, deciderTester, filterTester import unittest @@ -34,7 +35,7 @@ def test_displaySizeChanged(self): with actionTester(self, braille.displaySizeChanged, **expectedKwargs): # Change the internal cache of the display size to trigger the action when getting the display size. - braille.handler._displayDimensions = braille.DisplayDimensions(1, 0) + braille.handler._displayDimensions = braille.display.DisplayDimensions(1, 0) # The getter should now trigger the action. braille.handler._get_displaySize() @@ -56,7 +57,7 @@ def test_filter_displayDimensions(self): self, braille.filter_displayDimensions, cachedDisplayDimensions, - braille.DisplayDimensions(5, 20), + braille.display.DisplayDimensions(5, 20), ) as expectedOutput: self.assertEqual(braille.handler.displayDimensions, expectedOutput) self.assertEqual( diff --git a/tests/unit/test_braille/test_windowBrailleCells.py b/tests/unit/test_braille/test_windowBrailleCells.py index 1aa1968385f..5ae7f144b63 100644 --- a/tests/unit/test_braille/test_windowBrailleCells.py +++ b/tests/unit/test_braille/test_windowBrailleCells.py @@ -9,11 +9,12 @@ import braille import braille.buffers +import braille.display -def _getDisplayDimensions(dimensions: braille.DisplayDimensions) -> braille.DisplayDimensions: +def _getDisplayDimensions(dimensions: braille.display.DisplayDimensions) -> braille.display.DisplayDimensions: """Used to build a braille handler with particular dimensions.""" - return braille.DisplayDimensions( + return braille.display.DisplayDimensions( numRows=2, numCols=20, ) From cdb445d2b7b9fa1d3158e7b477e9fbafda6c4cab Mon Sep 17 00:00:00 2001 From: Sascha Cowley <16543535+SaschaCowley@users.noreply.github.com> Date: Thu, 9 Jul 2026 13:00:54 +1000 Subject: [PATCH 05/15] braille.regions.base.Region --- source/braille/__init__.py | 8 ++++---- source/mathPres/MathCAT/MathCAT.py | 7 ++++--- tests/unit/test_braille/test_regionLanguageIndexes.py | 7 ++++--- tests/unit/test_braille/test_routing.py | 3 ++- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/source/braille/__init__.py b/source/braille/__init__.py index d9099bbd46d..f7bdc6ede31 100644 --- a/source/braille/__init__.py +++ b/source/braille/__init__.py @@ -47,10 +47,10 @@ def terminate(): # MovedSymbol("getDisplayDrivers", "braille.display"), # MovedSymbol("RENAMED_DRIVERS", "braille.display"), # MovedSymbol("DisplayDimensions", "braille.display"), - MovedSymbol("Region", "braille.regions.base"), - MovedSymbol("RegionWithPositions", "braille.regions.base"), - MovedSymbol("TextRegion", "braille.regions.base"), - MovedSymbol("rindex", "braille.regions.base"), + # MovedSymbol("Region", "braille.regions.base"), + # MovedSymbol("RegionWithPositions", "braille.regions.base"), + # MovedSymbol("TextRegion", "braille.regions.base"), + # MovedSymbol("rindex", "braille.regions.base"), MovedSymbol("NVDAObjectRegion", "braille.regions.NVDAObject"), MovedSymbol("ReviewNVDAObjectRegion", "braille.regions.NVDAObject"), MovedSymbol("NVDAObjectHasUsefulText", "braille.regions.NVDAObject"), diff --git a/source/mathPres/MathCAT/MathCAT.py b/source/mathPres/MathCAT/MathCAT.py index a6c97306e21..f67662cc371 100644 --- a/source/mathPres/MathCAT/MathCAT.py +++ b/source/mathPres/MathCAT/MathCAT.py @@ -15,6 +15,7 @@ from typing import Type import braille +import braille.regions.base import config import gui import libmathcat_py as libmathcat @@ -107,10 +108,10 @@ def reportFocus(self) -> None: def getBrailleRegions( self, review: bool = False, - ) -> Generator[braille.Region, None, None]: + ) -> Generator[braille.regions.base.Region, None, None]: """Yields braille.Region objects for this MathCATInteraction object.""" yield braille.NVDAObjectRegion(self, appendText=" ") - region: braille.Region = braille.Region() + region: braille.regions.base.Region = braille.regions.base.Region() region.focusToHardLeft = True try: region.rawText = _callMathCAT(libmathcat.GetBraille, "") @@ -145,7 +146,7 @@ def _updateBraille(self) -> None: try: navNode: tuple[str, int] = libmathcat.GetNavigationMathMLId() brailleChars = _callMathCAT(libmathcat.GetBraille, navNode[0]) - region: braille.Region = braille.Region() + region: braille.regions.base.Region = braille.regions.base.Region() region.rawText = brailleChars region.focusToHardLeft = True region.update() diff --git a/tests/unit/test_braille/test_regionLanguageIndexes.py b/tests/unit/test_braille/test_regionLanguageIndexes.py index 5db97a9761d..1ea242b3520 100644 --- a/tests/unit/test_braille/test_regionLanguageIndexes.py +++ b/tests/unit/test_braille/test_regionLanguageIndexes.py @@ -9,6 +9,7 @@ from unittest.mock import patch import braille +import braille.regions.base import textInfos @@ -30,7 +31,7 @@ def getTextWithFields(self, formatConfig: dict | None = None): def _makeTextInfoRegion() -> braille.TextInfoRegion: """Build a TextInfoRegion without going through __init__ (which requires an NVDAObject).""" region = braille.TextInfoRegion.__new__(braille.TextInfoRegion) - braille.Region.__init__(region) + braille.regions.base.Region.__init__(region) # Force a deterministic default language so we don't depend on NVDA's configured locale. region._languageIndexes = {0: "en"} return region @@ -40,8 +41,8 @@ class TestLanguageIndexes(unittest.TestCase): def test_freshRegion_defaultLanguageAtAnyPos(self): """A region returns the default language for any non-negative pos.""" # Stub default language so Region.__init__ doesn't depend on NVDA's configured locale. - with patch.object(braille.Region, "_getDefaultRegionLanguage", return_value="en"): - region = braille.Region() + with patch.object(braille.regions.base.Region, "_getDefaultRegionLanguage", return_value="en"): + region = braille.regions.base.Region() self.assertEqual(region._getLanguageAtPos(0), "en") self.assertEqual(region._getLanguageAtPos(5), "en") self.assertEqual(region._getLanguageAtPos(100), "en") diff --git a/tests/unit/test_braille/test_routing.py b/tests/unit/test_braille/test_routing.py index 5b3e0f9540f..0005362a448 100644 --- a/tests/unit/test_braille/test_routing.py +++ b/tests/unit/test_braille/test_routing.py @@ -7,6 +7,7 @@ import config import braille +import braille.regions.base import textInfos import api import controlTypes @@ -56,7 +57,7 @@ def test_chineseWordSegmentationAndUnicodeNormalizationOffsetsAreComposed(self) patch("textUtils._wordSeg.wordSegUtils.WordSegmenter", return_value=wordSegmenter), patch("braille.regions.base.louisHelper.translate", translate), ): - region = braille.Region() + region = braille.regions.base.Region() region.rawText = "你ℌ" region.rawTextTypeforms = [11, 22] region.cursorPos = 1 From 3d91c3493637bc7e43d0c0729b5943b13c272ba8 Mon Sep 17 00:00:00 2001 From: Sascha Cowley <16543535+SaschaCowley@users.noreply.github.com> Date: Thu, 9 Jul 2026 13:20:57 +1000 Subject: [PATCH 06/15] braille.regions.NVDAObject.NVDAObjectRegion --- source/braille/__init__.py | 6 +++--- source/mathPres/MathCAT/MathCAT.py | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/source/braille/__init__.py b/source/braille/__init__.py index f7bdc6ede31..45ac4208170 100644 --- a/source/braille/__init__.py +++ b/source/braille/__init__.py @@ -51,9 +51,9 @@ def terminate(): # MovedSymbol("RegionWithPositions", "braille.regions.base"), # MovedSymbol("TextRegion", "braille.regions.base"), # MovedSymbol("rindex", "braille.regions.base"), - MovedSymbol("NVDAObjectRegion", "braille.regions.NVDAObject"), - MovedSymbol("ReviewNVDAObjectRegion", "braille.regions.NVDAObject"), - MovedSymbol("NVDAObjectHasUsefulText", "braille.regions.NVDAObject"), + # MovedSymbol("NVDAObjectRegion", "braille.regions.NVDAObject"), + # MovedSymbol("ReviewNVDAObjectRegion", "braille.regions.NVDAObject"), + # MovedSymbol("NVDAObjectHasUsefulText", "braille.regions.NVDAObject"), MovedSymbol("TextInfoRegion", "braille.regions.textInfo"), MovedSymbol("CursorManagerRegion", "braille.regions.textInfo"), MovedSymbol("ReviewTextInfoRegion", "braille.regions.textInfo"), diff --git a/source/mathPres/MathCAT/MathCAT.py b/source/mathPres/MathCAT/MathCAT.py index f67662cc371..b901c9283e8 100644 --- a/source/mathPres/MathCAT/MathCAT.py +++ b/source/mathPres/MathCAT/MathCAT.py @@ -16,6 +16,7 @@ import braille import braille.regions.base +import braille.regions.NVDAObject import config import gui import libmathcat_py as libmathcat @@ -110,7 +111,7 @@ def getBrailleRegions( review: bool = False, ) -> Generator[braille.regions.base.Region, None, None]: """Yields braille.Region objects for this MathCATInteraction object.""" - yield braille.NVDAObjectRegion(self, appendText=" ") + yield braille.regions.NVDAObject.NVDAObjectRegion(self, appendText=" ") region: braille.regions.base.Region = braille.regions.base.Region() region.focusToHardLeft = True try: From 86b01331780e2d866e9eeb573c7014c71709fc32 Mon Sep 17 00:00:00 2001 From: Sascha Cowley <16543535+SaschaCowley@users.noreply.github.com> Date: Thu, 9 Jul 2026 14:01:58 +1000 Subject: [PATCH 07/15] braille.regions.textInfo.TextInfoRegion --- source/braille/__init__.py | 8 ++++---- source/brailleInput.py | 5 +++-- .../test_braille/test_regionLanguageIndexes.py | 17 +++++++++++------ tests/unit/test_braille/test_routing.py | 5 +++-- 4 files changed, 21 insertions(+), 14 deletions(-) diff --git a/source/braille/__init__.py b/source/braille/__init__.py index 45ac4208170..9c6192603eb 100644 --- a/source/braille/__init__.py +++ b/source/braille/__init__.py @@ -54,10 +54,10 @@ def terminate(): # MovedSymbol("NVDAObjectRegion", "braille.regions.NVDAObject"), # MovedSymbol("ReviewNVDAObjectRegion", "braille.regions.NVDAObject"), # MovedSymbol("NVDAObjectHasUsefulText", "braille.regions.NVDAObject"), - MovedSymbol("TextInfoRegion", "braille.regions.textInfo"), - MovedSymbol("CursorManagerRegion", "braille.regions.textInfo"), - MovedSymbol("ReviewTextInfoRegion", "braille.regions.textInfo"), - MovedSymbol("ReviewCursorManagerRegion", "braille.regions.textInfo"), + # MovedSymbol("TextInfoRegion", "braille.regions.textInfo"), + # MovedSymbol("CursorManagerRegion", "braille.regions.textInfo"), + # MovedSymbol("ReviewTextInfoRegion", "braille.regions.textInfo"), + # MovedSymbol("ReviewCursorManagerRegion", "braille.regions.textInfo"), MovedSymbol("getControlFieldBraille", "braille.regions.properties"), MovedSymbol("getFormatFieldBraille", "braille.regions.properties"), MovedSymbol("getPropertiesBraille", "braille.regions.properties"), diff --git a/source/brailleInput.py b/source/brailleInput.py index 4b7fedb34c9..1db1872ff6a 100644 --- a/source/brailleInput.py +++ b/source/brailleInput.py @@ -9,6 +9,7 @@ import louis import brailleTables import braille +import braille.regions.textInfo import config from logHandler import log import winUser @@ -311,7 +312,7 @@ def _updateUntranslated(self): def updateDisplay(self): """Update the braille display to reflect untranslated input.""" region = braille.handler.mainBuffer.regions[-1] if braille.handler.mainBuffer.regions else None - if isinstance(region, braille.TextInfoRegion): + if isinstance(region, braille.regions.textInfo.TextInfoRegion): braille.handler._regionsPendingUpdate.add(region) braille.handler._handlePendingUpdate() @@ -332,7 +333,7 @@ def eraseLastCell(self): self.bufferText = self.bufferText[:-1] region = braille.handler.mainBuffer.regions[-1] if braille.handler.mainBuffer.regions else None if ( - not isinstance(region, braille.TextInfoRegion) + not isinstance(region, braille.regions.textInfo.TextInfoRegion) or region.cursorPos is None or region.rawText[region.cursorPos - 1] != char ): diff --git a/tests/unit/test_braille/test_regionLanguageIndexes.py b/tests/unit/test_braille/test_regionLanguageIndexes.py index 1ea242b3520..a50315a60af 100644 --- a/tests/unit/test_braille/test_regionLanguageIndexes.py +++ b/tests/unit/test_braille/test_regionLanguageIndexes.py @@ -10,6 +10,7 @@ import braille import braille.regions.base +import braille.regions.textInfo import textInfos @@ -28,9 +29,9 @@ def getTextWithFields(self, formatConfig: dict | None = None): return self._commands -def _makeTextInfoRegion() -> braille.TextInfoRegion: +def _makeTextInfoRegion() -> braille.regions.textInfo.TextInfoRegion: """Build a TextInfoRegion without going through __init__ (which requires an NVDAObject).""" - region = braille.TextInfoRegion.__new__(braille.TextInfoRegion) + region = braille.regions.textInfo.TextInfoRegion.__new__(braille.regions.textInfo.TextInfoRegion) braille.regions.base.Region.__init__(region) # Force a deterministic default language so we don't depend on NVDA's configured locale. region._languageIndexes = {0: "en"} @@ -94,7 +95,7 @@ def test_addTextWithFields_formatChangeInsertsLanguageIndex(self): with ( patch("braille.regions.textInfo.getFormatFieldBraille", return_value=""), patch.object( - braille.TextInfoRegion, + braille.regions.textInfo.TextInfoRegion, "_getTypeformFromFormatField", return_value=0, ), @@ -115,14 +116,18 @@ def test_textInfoRegion_update_resetsLanguageIndexes(self): # Using side_effect to halt execution mid-method avoids needing the full NVDA environment # that the rest of update() requires. with ( - patch.object(braille.TextInfoRegion, "_getDefaultRegionLanguage", return_value="en"), patch.object( - braille.TextInfoRegion, + braille.regions.textInfo.TextInfoRegion, + "_getDefaultRegionLanguage", + return_value="en", + ), + patch.object( + braille.regions.textInfo.TextInfoRegion, "_getReadingUnit", return_value=textInfos.UNIT_LINE, ), patch.object( - braille.TextInfoRegion, + braille.regions.textInfo.TextInfoRegion, "_getSelection", side_effect=RuntimeError("stop-after-reset"), ), diff --git a/tests/unit/test_braille/test_routing.py b/tests/unit/test_braille/test_routing.py index 0005362a448..0a0eba75a57 100644 --- a/tests/unit/test_braille/test_routing.py +++ b/tests/unit/test_braille/test_routing.py @@ -8,6 +8,7 @@ import config import braille import braille.regions.base +import braille.regions.textInfo import textInfos import api import controlTypes @@ -207,7 +208,7 @@ def test_routeToEmoji(self): ti.collapse(end=True) ti.expand(textInfos.UNIT_CHARACTER) self.assertEqual(ti.text, testText[2]) - region = braille.TextInfoRegion(obj) + region = braille.regions.textInfo.TextInfoRegion(obj) region.update() index = 3 # Position of e pos = region.rawToBraillePos[index] @@ -228,7 +229,7 @@ def test_routeToComposite(self): ti.collapse(end=True) ti.expand(textInfos.UNIT_CHARACTER) self.assertEqual(ti.text, testText[4]) - region = braille.TextInfoRegion(obj) + region = braille.regions.textInfo.TextInfoRegion(obj) region.update() index = 1 # Position of ב pos = region.rawToBraillePos[index] From 063094deff66dc04e24582816e5e3fb21c1da7aa Mon Sep 17 00:00:00 2001 From: Sascha Cowley <16543535+SaschaCowley@users.noreply.github.com> Date: Thu, 9 Jul 2026 14:50:59 +1000 Subject: [PATCH 08/15] braille.regions.properties.{getControlFieldBraille, getPropertiesBraille} --- source/NVDAObjects/IAccessible/__init__.py | 9 +++++++-- source/NVDAObjects/UIA/VisualStudio.py | 3 ++- source/NVDAObjects/UIA/__init__.py | 5 ++++- source/NVDAObjects/__init__.py | 3 ++- source/NVDAObjects/behaviors.py | 9 +++++++-- source/appModules/eclipse.py | 3 ++- source/appModules/explorer.py | 3 ++- source/appModules/notepad.py | 3 ++- ...l_composableshell_experiences_textinput_inputapp.py | 3 ++- source/braille/__init__.py | 6 +++--- source/textInfos/__init__.py | 10 ++++++++-- 11 files changed, 41 insertions(+), 16 deletions(-) diff --git a/source/NVDAObjects/IAccessible/__init__.py b/source/NVDAObjects/IAccessible/__init__.py index 79d6ff495e0..9d7158e79b0 100644 --- a/source/NVDAObjects/IAccessible/__init__.py +++ b/source/NVDAObjects/IAccessible/__init__.py @@ -47,6 +47,7 @@ from logHandler import log import speech import braille +import braille.regions.properties import api import config import controlTypes @@ -2037,7 +2038,9 @@ def event_alert(self) -> None: if self in api.getFocusAncestors(): return speech.speakObject(self, reason=controlTypes.OutputReason.FOCUS, priority=speech.Spri.NOW) - braille.handler.message(braille.getPropertiesBraille(name=self.name, role=self.role)) + braille.handler.message( + braille.regions.properties.getPropertiesBraille(name=self.name, role=self.role), + ) hasDescription = bool(self.description) for child in self.recursiveDescendants: isFocusable = controlTypes.State.FOCUSABLE in child.states @@ -2060,7 +2063,9 @@ def event_alert(self) -> None: ) if shouldSpeak: speech.speakObject(child, reason=controlTypes.OutputReason.FOCUS, priority=speech.Spri.NOW) - braille.handler.message(braille.getPropertiesBraille(name=self.name, role=self.role)) + braille.handler.message( + braille.regions.properties.getPropertiesBraille(name=self.name, role=self.role), + ) def event_caret(self): focus = api.getFocusObject() diff --git a/source/NVDAObjects/UIA/VisualStudio.py b/source/NVDAObjects/UIA/VisualStudio.py index 1ecfc7ba256..98578783e8c 100644 --- a/source/NVDAObjects/UIA/VisualStudio.py +++ b/source/NVDAObjects/UIA/VisualStudio.py @@ -10,6 +10,7 @@ from . import UIA, ToolTip import speech import braille +import braille.regions.properties import api import time @@ -28,7 +29,7 @@ def event_UIA_elementSelected(self): self.reportFocus() # Display results as flash messages. braille.handler.message( - braille.getPropertiesBraille( + braille.regions.properties.getPropertiesBraille( name=self.name, role=self.role, positionInfo=self.positionInfo, diff --git a/source/NVDAObjects/UIA/__init__.py b/source/NVDAObjects/UIA/__init__.py index 5f9ff822901..378e9d4be39 100644 --- a/source/NVDAObjects/UIA/__init__.py +++ b/source/NVDAObjects/UIA/__init__.py @@ -65,6 +65,7 @@ ToolTip, ) import braille +import braille.regions.properties import locationHelper import ui import winVersion @@ -2466,7 +2467,9 @@ def event_UIA_systemAlert(self): """ speech.speakObject(self, reason=controlTypes.OutputReason.FOCUS) # Ideally, we wouldn't use getPropertiesBraille directly. - braille.handler.message(braille.getPropertiesBraille(name=self.name, role=self.role)) + braille.handler.message( + braille.regions.properties.getPropertiesBraille(name=self.name, role=self.role), + ) def event_UIA_notification( self, diff --git a/source/NVDAObjects/__init__.py b/source/NVDAObjects/__init__.py index d741c51196c..052950c6ee8 100644 --- a/source/NVDAObjects/__init__.py +++ b/source/NVDAObjects/__init__.py @@ -37,6 +37,7 @@ TreeInterceptor, ) import braille +import braille.regions.properties from utils.security import _isObjectBelowLockScreen import vision import globalPluginHandler @@ -1333,7 +1334,7 @@ def event_selection(self): self.reportFocus() # Display results as flash messages. braille.handler.message( - braille.getPropertiesBraille( + braille.regions.properties.getPropertiesBraille( name=self.name, role=self.role, positionInfo=self.positionInfo, diff --git a/source/NVDAObjects/behaviors.py b/source/NVDAObjects/behaviors.py index 2c90948b5f3..5714c89ba62 100755 --- a/source/NVDAObjects/behaviors.py +++ b/source/NVDAObjects/behaviors.py @@ -27,6 +27,7 @@ import api import ui import braille +import braille.regions.properties import core import nvwave import globalVars @@ -1057,7 +1058,9 @@ def event_show(self): return speech.speakObject(self, reason=controlTypes.OutputReason.FOCUS) # Ideally, we wouldn't use getPropertiesBraille directly. - braille.handler.message(braille.getPropertiesBraille(name=self.name, role=self.role)) + braille.handler.message( + braille.regions.properties.getPropertiesBraille(name=self.name, role=self.role), + ) class Notification(NVDAObject): @@ -1071,7 +1074,9 @@ def event_alert(self): return speech.speakObject(self, reason=controlTypes.OutputReason.FOCUS) # Ideally, we wouldn't use getPropertiesBraille directly. - braille.handler.message(braille.getPropertiesBraille(name=self.name, role=self.role)) + braille.handler.message( + braille.regions.properties.getPropertiesBraille(name=self.name, role=self.role), + ) event_show = event_alert diff --git a/source/appModules/eclipse.py b/source/appModules/eclipse.py index 1942c332834..417e388943f 100644 --- a/source/appModules/eclipse.py +++ b/source/appModules/eclipse.py @@ -9,6 +9,7 @@ from NVDAObjects.behaviors import EditableTextWithSuggestions import speech import braille +import braille.regions.properties import ui import api from speech import sayAll @@ -155,7 +156,7 @@ def event_selection(self): # Simply calling `reportFocus` doesn't output the text in braille # and reporting with `ui.message` needs an extra translation string when reporting position info braille.handler.message( - braille.getPropertiesBraille( + braille.regions.properties.getPropertiesBraille( name=self.name, role=self.role, positionInfo=self.positionInfo, diff --git a/source/appModules/explorer.py b/source/appModules/explorer.py index 9ad19359852..f9b83bc6cc5 100644 --- a/source/appModules/explorer.py +++ b/source/appModules/explorer.py @@ -17,6 +17,7 @@ import api import speech import braille +import braille.regions.properties import eventHandler import mouseHandler from NVDAObjects import NVDAObject @@ -506,7 +507,7 @@ def event_UIA_elementSelected(self, obj: NVDAObject, nextHandler: Callable[[], N ): speech.speakObject(obj, reason=controlTypes.OutputReason.FOCUS) braille.handler.message( - braille.getPropertiesBraille( + braille.regions.properties.getPropertiesBraille( name=obj.name, role=obj.role, states=obj.states, diff --git a/source/appModules/notepad.py b/source/appModules/notepad.py index 872b46d89d9..c2a856f18f1 100644 --- a/source/appModules/notepad.py +++ b/source/appModules/notepad.py @@ -11,6 +11,7 @@ import appModuleHandler import api import braille +import braille.regions.properties import controlTypes import eventHandler import speech @@ -32,7 +33,7 @@ def event_UIA_elementSelected(self, obj: NVDAObject, nextHandler: Callable[[], N speech.cancelSpeech() speech.speakObject(obj, reason=controlTypes.OutputReason.FOCUS) braille.handler.message( - braille.getPropertiesBraille( + braille.regions.properties.getPropertiesBraille( name=obj.name, role=obj.role, states=obj.states, diff --git a/source/appModules/windowsinternal_composableshell_experiences_textinput_inputapp.py b/source/appModules/windowsinternal_composableshell_experiences_textinput_inputapp.py index 0416fc267b1..352b5afc802 100644 --- a/source/appModules/windowsinternal_composableshell_experiences_textinput_inputapp.py +++ b/source/appModules/windowsinternal_composableshell_experiences_textinput_inputapp.py @@ -16,6 +16,7 @@ import eventHandler import speech import braille +import braille.regions.properties import ui import config import winVersion @@ -226,7 +227,7 @@ def event_UIA_elementSelected(self, obj: NVDAObject, nextHandler: Callable[[], N if obj is not None and api.setNavigatorObject(obj): obj.reportFocus() braille.handler.message( - braille.getPropertiesBraille( + braille.regions.properties.getPropertiesBraille( name=obj.name, role=obj.role, positionInfo=obj.positionInfo, diff --git a/source/braille/__init__.py b/source/braille/__init__.py index 9c6192603eb..eb460cad565 100644 --- a/source/braille/__init__.py +++ b/source/braille/__init__.py @@ -58,9 +58,9 @@ def terminate(): # MovedSymbol("CursorManagerRegion", "braille.regions.textInfo"), # MovedSymbol("ReviewTextInfoRegion", "braille.regions.textInfo"), # MovedSymbol("ReviewCursorManagerRegion", "braille.regions.textInfo"), - MovedSymbol("getControlFieldBraille", "braille.regions.properties"), - MovedSymbol("getFormatFieldBraille", "braille.regions.properties"), - MovedSymbol("getPropertiesBraille", "braille.regions.properties"), + # MovedSymbol("getControlFieldBraille", "braille.regions.properties"), + # MovedSymbol("getFormatFieldBraille", "braille.regions.properties"), + # MovedSymbol("getPropertiesBraille", "braille.regions.properties"), MovedSymbol("getFocusContextRegions", "braille.regions.focus"), MovedSymbol("getFocusRegions", "braille.regions.focus"), MovedSymbol("invalidateCachedFocusAncestors", "braille.regions.focus"), diff --git a/source/textInfos/__init__.py b/source/textInfos/__init__.py index 9d42276ac80..40c05ba5262 100755 --- a/source/textInfos/__init__.py +++ b/source/textInfos/__init__.py @@ -657,9 +657,15 @@ def getControlFieldSpeech( def getControlFieldBraille(self, field, ancestors, reportStart, formatConfig): # Import late to avoid circular import. - import braille + import braille.regions.properties - return braille.getControlFieldBraille(self, field, ancestors, reportStart, formatConfig) + return braille.regions.properties.getControlFieldBraille( + self, + field, + ancestors, + reportStart, + formatConfig, + ) def getFormatFieldSpeech( self, From 73348935a82b662602df9c093173ee501ec1e35a Mon Sep 17 00:00:00 2001 From: Sascha Cowley <16543535+SaschaCowley@users.noreply.github.com> Date: Thu, 9 Jul 2026 15:03:34 +1000 Subject: [PATCH 09/15] braille.regions.focus.invalidateCachedFocusAncestors --- source/api.py | 3 ++- source/appModules/logonui.py | 3 ++- source/braille/__init__.py | 6 +++--- source/globalCommands.py | 3 ++- tests/unit/test_braille/test_focusContextPresentation.py | 5 +++-- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/source/api.py b/source/api.py index 976dc454e30..4fa2c862774 100644 --- a/source/api.py +++ b/source/api.py @@ -23,6 +23,7 @@ import controlTypes import eventHandler import braille +import braille.regions.focus import vision import watchdog import exceptions @@ -184,7 +185,7 @@ def setFocusObject(obj: NVDAObjects.NVDAObject) -> bool: # noqa: C901 globalVars.focusDifferenceLevel = focusDifferenceLevel globalVars.focusObject = obj globalVars.focusAncestors = ancestors - braille.invalidateCachedFocusAncestors(focusDifferenceLevel) + braille.regions.focus.invalidateCachedFocusAncestors(focusDifferenceLevel) if config.conf["reviewCursor"]["followFocus"]: setNavigatorObject(obj, isFocus=True) # Fire focusExited event for all old focus ancestors not common with the new focus diff --git a/source/appModules/logonui.py b/source/appModules/logonui.py index b959b803666..c93211a833b 100644 --- a/source/appModules/logonui.py +++ b/source/appModules/logonui.py @@ -7,6 +7,7 @@ import speech import api import braille +import braille.regions.focus import controlTypes from NVDAObjects.IAccessible import IAccessible from NVDAObjects.behaviors import Dialog @@ -124,5 +125,5 @@ def event_gainFocus(self, obj, nextHandler): role=True, description=True, ) - braille.invalidateCachedFocusAncestors(1) + braille.regions.focus.invalidateCachedFocusAncestors(1) nextHandler() diff --git a/source/braille/__init__.py b/source/braille/__init__.py index eb460cad565..296407b7996 100644 --- a/source/braille/__init__.py +++ b/source/braille/__init__.py @@ -61,9 +61,9 @@ def terminate(): # MovedSymbol("getControlFieldBraille", "braille.regions.properties"), # MovedSymbol("getFormatFieldBraille", "braille.regions.properties"), # MovedSymbol("getPropertiesBraille", "braille.regions.properties"), - MovedSymbol("getFocusContextRegions", "braille.regions.focus"), - MovedSymbol("getFocusRegions", "braille.regions.focus"), - MovedSymbol("invalidateCachedFocusAncestors", "braille.regions.focus"), + # MovedSymbol("getFocusContextRegions", "braille.regions.focus"), + # MovedSymbol("getFocusRegions", "braille.regions.focus"), + # MovedSymbol("invalidateCachedFocusAncestors", "braille.regions.focus"), MovedSymbol("BrailleBuffer", "braille.buffers"), MovedSymbol("BrailleHandler", "braille.brailleHandler"), MovedSymbol("formatCellsForLog", "braille.brailleHandler"), diff --git a/source/globalCommands.py b/source/globalCommands.py index a68a75ccb50..c9550410323 100755 --- a/source/globalCommands.py +++ b/source/globalCommands.py @@ -63,6 +63,7 @@ import ui import braille import braille.display.gesture +import braille.regions.focus import brailleInput import inputCore import characterProcessing @@ -3918,7 +3919,7 @@ def script_braille_toggleFocusContextPresentation(self, gesture): index = 0 newIndex = (index + 1) % len(values) config.conf["braille"]["focusContextPresentation"] = values[newIndex] - braille.invalidateCachedFocusAncestors(0) + braille.regions.focus.invalidateCachedFocusAncestors(0) braille.handler.handleGainFocus(api.getFocusObject()) # Translators: Reports the new state of braille focus context presentation. # %s will be replaced with the context presentation setting. diff --git a/tests/unit/test_braille/test_focusContextPresentation.py b/tests/unit/test_braille/test_focusContextPresentation.py index e3117d94945..4381c01270c 100644 --- a/tests/unit/test_braille/test_focusContextPresentation.py +++ b/tests/unit/test_braille/test_focusContextPresentation.py @@ -7,6 +7,7 @@ import api import braille +import braille.regions.focus import controlTypes import globalVars from config import conf @@ -68,7 +69,7 @@ def test_changedContext(self): """Test for the case where the focus object as well as ancestry differences should be visible on the display""" conf["braille"]["focusContextPresentation"] = braille.CONTEXTPRES_CHANGEDCONTEXT # Clean up the cached ancestry regions - braille.invalidateCachedFocusAncestors(0) + braille.regions.focus.invalidateCachedFocusAncestors(0) # Regenerate the regions braille.handler.handleGainFocus(self.obj) # Both the focus object and its parents should be visible, equivalent to always fill display @@ -87,7 +88,7 @@ def test_changedContext(self): # Clean up the cached focus ancestors # specifically, the desktop object (ancestor 0) has no associated region # We will keep the region for the dialog (ancestor 1) and consider the list (ancestor 2) as new for this test - braille.invalidateCachedFocusAncestors(2) + braille.regions.focus.invalidateCachedFocusAncestors(2) # Do another focus to simulate a new focus object with different ancestry braille.handler.handleGainFocus(self.obj) # The list and the list item should be visible From 82d0b6939f3d4f9bf3b7e0cb1d2037f33a5812b8 Mon Sep 17 00:00:00 2001 From: Sascha Cowley <16543535+SaschaCowley@users.noreply.github.com> Date: Thu, 9 Jul 2026 15:27:14 +1000 Subject: [PATCH 10/15] braille.labels.{landmarkLabels, roleLabels} --- source/NVDAObjects/__init__.py | 5 +++-- source/braille/__init__.py | 16 ++++++++-------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/source/NVDAObjects/__init__.py b/source/NVDAObjects/__init__.py index 052950c6ee8..74e07fcbb87 100644 --- a/source/NVDAObjects/__init__.py +++ b/source/NVDAObjects/__init__.py @@ -37,6 +37,7 @@ TreeInterceptor, ) import braille +import braille.labels import braille.regions.properties from utils.security import _isObjectBelowLockScreen import vision @@ -518,8 +519,8 @@ def _get_roleTextBraille(self): which will override the standard label for this object's role property as well as the value of roleText. By default, NVDA falls back to using roleText. """ - if self.landmark and self.landmark in braille.landmarkLabels: - return f"{braille.roleLabels[controlTypes.Role.LANDMARK]} {braille.landmarkLabels[self.landmark]}" + if self.landmark and self.landmark in braille.labels.landmarkLabels: + return f"{braille.labels.roleLabels[controlTypes.Role.LANDMARK]} {braille.labels.landmarkLabels[self.landmark]}" return self.roleText #: Typing information for auto property _get_value diff --git a/source/braille/__init__.py b/source/braille/__init__.py index 296407b7996..fd61f6e3e88 100644 --- a/source/braille/__init__.py +++ b/source/braille/__init__.py @@ -64,14 +64,14 @@ def terminate(): # MovedSymbol("getFocusContextRegions", "braille.regions.focus"), # MovedSymbol("getFocusRegions", "braille.regions.focus"), # MovedSymbol("invalidateCachedFocusAncestors", "braille.regions.focus"), - MovedSymbol("BrailleBuffer", "braille.buffers"), - MovedSymbol("BrailleHandler", "braille.brailleHandler"), - MovedSymbol("formatCellsForLog", "braille.brailleHandler"), - MovedSymbol("FALLBACK_TABLE", "braille.brailleHandler"), - MovedSymbol("roleLabels", "braille.labels"), - MovedSymbol("positiveStateLabels", "braille.labels"), - MovedSymbol("negativeStateLabels", "braille.labels"), - MovedSymbol("landmarkLabels", "braille.labels"), + # MovedSymbol("BrailleBuffer", "braille.buffers"), + # MovedSymbol("BrailleHandler", "braille.brailleHandler"), + # MovedSymbol("formatCellsForLog", "braille.brailleHandler"), + # MovedSymbol("FALLBACK_TABLE", "braille.brailleHandler"), + # MovedSymbol("roleLabels", "braille.labels"), + # MovedSymbol("positiveStateLabels", "braille.labels"), + # MovedSymbol("negativeStateLabels", "braille.labels"), + # MovedSymbol("landmarkLabels", "braille.labels"), MovedSymbol("FormatTagDelimiter", "braille.formatting"), MovedSymbol("FormattingMarker", "braille.formatting"), MovedSymbol("fontAttributeFormattingMarkers", "braille.formatting"), From 3f30546282a86d6e165ba1c8037dea29f127f5f2 Mon Sep 17 00:00:00 2001 From: Sascha Cowley <16543535+SaschaCowley@users.noreply.github.com> Date: Thu, 9 Jul 2026 16:10:53 +1000 Subject: [PATCH 11/15] braille.constants.{AUTO_DISPLAY_NAME, AUTOMATIC_PORT, CONTEXTPRES_CHANGEDCONTEXT, CONTEXTPRES_FILL, CONTEXTPRES_SCROLL, CONTINUATION_SHAPE, CURSOR_SHAPES, TEXT_SEPARATOR, focusContextPresentations} --- source/braille/__init__.py | 40 +++++++++---------- source/globalCommands.py | 13 +++--- source/gui/settingsDialogs.py | 21 +++++----- .../test_focusContextPresentation.py | 7 ++-- .../test_regionLanguageIndexes.py | 3 +- .../test_braille/test_windowBrailleCells.py | 5 ++- 6 files changed, 47 insertions(+), 42 deletions(-) diff --git a/source/braille/__init__.py b/source/braille/__init__.py index fd61f6e3e88..bd2d4eb0904 100644 --- a/source/braille/__init__.py +++ b/source/braille/__init__.py @@ -72,26 +72,26 @@ def terminate(): # MovedSymbol("positiveStateLabels", "braille.labels"), # MovedSymbol("negativeStateLabels", "braille.labels"), # MovedSymbol("landmarkLabels", "braille.labels"), - MovedSymbol("FormatTagDelimiter", "braille.formatting"), - MovedSymbol("FormattingMarker", "braille.formatting"), - MovedSymbol("fontAttributeFormattingMarkers", "braille.formatting"), - MovedSymbol("getParagraphStartMarker", "braille.formatting"), - MovedSymbol("AUTO_DISPLAY_NAME", "braille.constants"), - MovedSymbol("AUTOMATIC_PORT", "braille.constants"), - MovedSymbol("BLUETOOTH_PORT", "braille.constants"), - MovedSymbol("USB_PORT", "braille.constants"), - MovedSymbol("NO_BRAILLE_DISPLAY_NAME", "braille.constants"), - MovedSymbol("CONTINUATION_SHAPE", "braille.constants"), - MovedSymbol("CURSOR_SHAPES", "braille.constants"), - MovedSymbol("SELECTION_SHAPE", "braille.constants"), - MovedSymbol("END_OF_BRAILLE_OUTPUT_SHAPE", "braille.constants"), - MovedSymbol("INPUT_START_IND", "braille.constants"), - MovedSymbol("INPUT_END_IND", "braille.constants"), - MovedSymbol("TEXT_SEPARATOR", "braille.constants"), - MovedSymbol("CONTEXTPRES_CHANGEDCONTEXT", "braille.constants"), - MovedSymbol("CONTEXTPRES_FILL", "braille.constants"), - MovedSymbol("CONTEXTPRES_SCROLL", "braille.constants"), - MovedSymbol("focusContextPresentations", "braille.constants"), + # MovedSymbol("FormatTagDelimiter", "braille.formatting"), + # MovedSymbol("FormattingMarker", "braille.formatting"), + # MovedSymbol("fontAttributeFormattingMarkers", "braille.formatting"), + # MovedSymbol("getParagraphStartMarker", "braille.formatting"), + # MovedSymbol("AUTO_DISPLAY_NAME", "braille.constants"), + # MovedSymbol("AUTOMATIC_PORT", "braille.constants"), + # MovedSymbol("BLUETOOTH_PORT", "braille.constants"), + # MovedSymbol("USB_PORT", "braille.constants"), + # MovedSymbol("NO_BRAILLE_DISPLAY_NAME", "braille.constants"), + # MovedSymbol("CONTINUATION_SHAPE", "braille.constants"), + # MovedSymbol("CURSOR_SHAPES", "braille.constants"), + # MovedSymbol("SELECTION_SHAPE", "braille.constants"), + # MovedSymbol("END_OF_BRAILLE_OUTPUT_SHAPE", "braille.constants"), + # MovedSymbol("INPUT_START_IND", "braille.constants"), + # MovedSymbol("INPUT_END_IND", "braille.constants"), + # MovedSymbol("TEXT_SEPARATOR", "braille.constants"), + # MovedSymbol("CONTEXTPRES_CHANGEDCONTEXT", "braille.constants"), + # MovedSymbol("CONTEXTPRES_FILL", "braille.constants"), + # MovedSymbol("CONTEXTPRES_SCROLL", "braille.constants"), + # MovedSymbol("focusContextPresentations", "braille.constants"), MovedSymbol("pre_writeCells", "braille.extensions"), MovedSymbol("filter_displaySize", "braille.extensions"), MovedSymbol("filter_displayDimensions", "braille.extensions"), diff --git a/source/globalCommands.py b/source/globalCommands.py index c9550410323..bbd94205a8d 100755 --- a/source/globalCommands.py +++ b/source/globalCommands.py @@ -62,6 +62,7 @@ from scriptHandler import script, getLastScriptRepeatCount import ui import braille +import braille.constants import braille.display.gesture import braille.regions.focus import brailleInput @@ -3911,8 +3912,8 @@ def script_braille_cycleReviewRoutingMovesSystemCaret(self, gesture: inputCore.I ) @gui.blockAction.when(gui.blockAction.Context.BRAILLE_MODE_SPEECH_OUTPUT) def script_braille_toggleFocusContextPresentation(self, gesture): - values = [x[0] for x in braille.focusContextPresentations] - labels = [x[1] for x in braille.focusContextPresentations] + values = [x[0] for x in braille.constants.focusContextPresentations] + labels = [x[1] for x in braille.constants.focusContextPresentations] try: index = values.index(config.conf["braille"]["focusContextPresentation"]) except: # noqa: E722 @@ -3988,7 +3989,7 @@ def script_braille_cycleCursorShape(self, gesture): # Translators: A message reported when changing the braille cursor shape when the braille cursor is turned off. ui.message(_("Braille cursor is turned off")) return - shapes = [s[0] for s in braille.CURSOR_SHAPES] + shapes = [s[0] for s in braille.constants.CURSOR_SHAPES] if braille.handler.getTether() == TetherTo.FOCUS.value: cursorShape = "cursorShapeFocus" else: @@ -3997,10 +3998,10 @@ def script_braille_cycleCursorShape(self, gesture): index = shapes.index(config.conf["braille"][cursorShape]) + 1 except: # noqa: E722 index = 1 - if index >= len(braille.CURSOR_SHAPES): + if index >= len(braille.constants.CURSOR_SHAPES): index = 0 - config.conf["braille"][cursorShape] = braille.CURSOR_SHAPES[index][0] - shapeMsg = braille.CURSOR_SHAPES[index][1] + config.conf["braille"][cursorShape] = braille.constants.CURSOR_SHAPES[index][0] + shapeMsg = braille.constants.CURSOR_SHAPES[index][1] # Translators: Reports which braille cursor shape is activated. ui.message(_("Braille cursor %s") % shapeMsg) diff --git a/source/gui/settingsDialogs.py b/source/gui/settingsDialogs.py index 66909d90b22..b1e00ec38a3 100644 --- a/source/gui/settingsDialogs.py +++ b/source/gui/settingsDialogs.py @@ -29,6 +29,7 @@ import audio import audioDucking import braille +import braille.constants import braille.display import brailleInput import brailleTables @@ -5028,7 +5029,7 @@ def onChangeDisplay(self, evt): self.Thaw() def updateCurrentDisplay(self): - if config.conf["braille"]["display"] == braille.AUTO_DISPLAY_NAME: + if config.conf["braille"]["display"] == braille.constants.AUTO_DISPLAY_NAME: displayDesc = BrailleDisplaySelectionDialog.getCurrentAutoDisplayDescription() else: displayDesc = braille.handler.display.description @@ -5088,23 +5089,23 @@ def postInit(self): @staticmethod def getCurrentAutoDisplayDescription(): - description = braille.AUTOMATIC_PORT[1] + description = braille.constants.AUTOMATIC_PORT[1] if ( - config.conf["braille"]["display"] == braille.AUTO_DISPLAY_NAME + config.conf["braille"]["display"] == braille.constants.AUTO_DISPLAY_NAME and braille.handler.display.name != "noBraille" ): description = "%s (%s)" % (description, braille.handler.display.description) return description def updateBrailleDisplayLists(self): - driverList = [(braille.AUTO_DISPLAY_NAME, self.getCurrentAutoDisplayDescription())] + driverList = [(braille.constants.AUTO_DISPLAY_NAME, self.getCurrentAutoDisplayDescription())] driverList.extend(braille.display.getDisplayList()) self.displayNames = [driver[0] for driver in driverList] displayChoices = [driver[1] for driver in driverList] self.displayList.Clear() self.displayList.AppendItems(displayChoices) try: - if config.conf["braille"]["display"] == braille.AUTO_DISPLAY_NAME: + if config.conf["braille"]["display"] == braille.constants.AUTO_DISPLAY_NAME: selection = 0 else: selection = self.displayNames.index(braille.handler.display.name) @@ -5129,7 +5130,7 @@ def updateBrailleDisplayLists(self): def updateStateDependentControls(self): displayName = self.displayNames[self.displayList.GetSelection()] self.possiblePorts = [] - isAutoDisplaySelected = displayName == braille.AUTOMATIC_PORT[0] + isAutoDisplaySelected = displayName == braille.constants.AUTOMATIC_PORT[0] if not isAutoDisplaySelected: displayCls = braille.display._getDisplayDriver(displayName) try: @@ -5332,8 +5333,8 @@ def makeSettings(self, settingsSizer): if not self.showCursorCheckBox.GetValue() or not self.cursorBlinkCheckBox.GetValue(): self.cursorBlinkRateEdit.Disable() - self.cursorShapes = [s[0] for s in braille.CURSOR_SHAPES] - cursorShapeChoices = [s[1] for s in braille.CURSOR_SHAPES] + self.cursorShapes = [s[0] for s in braille.constants.CURSOR_SHAPES] + cursorShapeChoices = [s[1] for s in braille.constants.CURSOR_SHAPES] # Translators: The label for a setting in braille settings to select the cursor shape when tethered to focus. cursorShapeFocusLabelText = _("Cursor shape for &focus:") @@ -5480,8 +5481,8 @@ def makeSettings(self, settingsSizer): # Translators: The label for a setting in braille settings to select how the context for the focus object should be presented on a braille display. focusContextPresentationLabelText = _("Focus context presentation:") - self.focusContextPresentationValues = [x[0] for x in braille.focusContextPresentations] - focusContextPresentationChoices = [x[1] for x in braille.focusContextPresentations] + self.focusContextPresentationValues = [x[0] for x in braille.constants.focusContextPresentations] + focusContextPresentationChoices = [x[1] for x in braille.constants.focusContextPresentations] self.focusContextPresentationList = followCursorGroupHelper.addLabeledControl( focusContextPresentationLabelText, wx.Choice, diff --git a/tests/unit/test_braille/test_focusContextPresentation.py b/tests/unit/test_braille/test_focusContextPresentation.py index 4381c01270c..18e121c5f0b 100644 --- a/tests/unit/test_braille/test_focusContextPresentation.py +++ b/tests/unit/test_braille/test_focusContextPresentation.py @@ -7,6 +7,7 @@ import api import braille +import braille.constants import braille.regions.focus import controlTypes import globalVars @@ -39,7 +40,7 @@ def setUp(self): def test_fillDisplay(self): """Test for the case where both the focus object and all its ancestors should be visible on a 40 cell display.""" - conf["braille"]["focusContextPresentation"] = braille.CONTEXTPRES_FILL + conf["braille"]["focusContextPresentation"] = braille.constants.CONTEXTPRES_FILL # Since we set the presentation mode, simulate another gainFocus so the regions will be updated properly braille.handler.handleGainFocus(self.obj) # WindowEndPos should be retrieved before we attempt to get the start position @@ -52,7 +53,7 @@ def test_fillDisplay(self): def test_scrollOnly(self): """Test for the case where the focus object should be visible hard left on a display.""" - conf["braille"]["focusContextPresentation"] = braille.CONTEXTPRES_SCROLL + conf["braille"]["focusContextPresentation"] = braille.constants.CONTEXTPRES_SCROLL braille.handler.handleGainFocus(self.obj) # Only the focus object should be visible on the display # This means that the window end position is equal to the end position of the 3rd region @@ -67,7 +68,7 @@ def test_scrollOnly(self): def test_changedContext(self): """Test for the case where the focus object as well as ancestry differences should be visible on the display""" - conf["braille"]["focusContextPresentation"] = braille.CONTEXTPRES_CHANGEDCONTEXT + conf["braille"]["focusContextPresentation"] = braille.constants.CONTEXTPRES_CHANGEDCONTEXT # Clean up the cached ancestry regions braille.regions.focus.invalidateCachedFocusAncestors(0) # Regenerate the regions diff --git a/tests/unit/test_braille/test_regionLanguageIndexes.py b/tests/unit/test_braille/test_regionLanguageIndexes.py index a50315a60af..e88ece1a495 100644 --- a/tests/unit/test_braille/test_regionLanguageIndexes.py +++ b/tests/unit/test_braille/test_regionLanguageIndexes.py @@ -9,6 +9,7 @@ from unittest.mock import patch import braille +import braille.constants import braille.regions.base import braille.regions.textInfo import textInfos @@ -60,7 +61,7 @@ def test_addFieldText_insertsSwitchAndRestore(self): with patch("braille.regions.textInfo.languageHandler.getLanguage", return_value="fr"): region._addFieldText(text, contentPos=0) # `_addFieldText` prepends TEXT_SEPARATOR when `separate=True` and there is pre-existing text. - addedLen = len(braille.TEXT_SEPARATOR) + len(text) + addedLen = len(braille.constants.TEXT_SEPARATOR) + len(text) self.assertIn(rawTextLenBefore, region._languageIndexes) self.assertEqual(region._languageIndexes[rawTextLenBefore], "fr") self.assertIn(rawTextLenBefore + addedLen, region._languageIndexes) diff --git a/tests/unit/test_braille/test_windowBrailleCells.py b/tests/unit/test_braille/test_windowBrailleCells.py index 5ae7f144b63..064a203d2d9 100644 --- a/tests/unit/test_braille/test_windowBrailleCells.py +++ b/tests/unit/test_braille/test_windowBrailleCells.py @@ -9,6 +9,7 @@ import braille import braille.buffers +import braille.constants import braille.display @@ -39,7 +40,7 @@ def test_continuationRow_hasContinuationShape(self): cells = buffer.windowBrailleCells # First row: 15 real cells, then CONTINUATION_SHAPE, then 4 padding zeroes. self.assertEqual(len(cells), 40) - self.assertEqual(cells[15], braille.CONTINUATION_SHAPE) + self.assertEqual(cells[15], braille.constants.CONTINUATION_SHAPE) self.assertEqual(cells[16:20], [0, 0, 0, 0]) def test_nonContinuationRow_lastCellIsZero(self): @@ -53,4 +54,4 @@ def test_nonContinuationRow_lastCellIsZero(self): cells = buffer.windowBrailleCells # No continuation marker anywhere; positions 15..19 of row 0 should all be 0. self.assertEqual(cells[15:20], [0, 0, 0, 0, 0]) - self.assertNotIn(braille.CONTINUATION_SHAPE, cells) + self.assertNotIn(braille.constants.CONTINUATION_SHAPE, cells) From a4e2338307ed3881f3139b014b03226af5f502a7 Mon Sep 17 00:00:00 2001 From: Sascha Cowley <16543535+SaschaCowley@users.noreply.github.com> Date: Thu, 9 Jul 2026 18:41:34 +1000 Subject: [PATCH 12/15] braille.extensions.{decide_enabled, displayChanged, displaySizeChanged, filter_displayDimensions, filter_displaySize, pre_writeCells} --- source/_remoteClient/localMachine.py | 4 ++-- source/_remoteClient/session.py | 15 ++++++++------- source/braille/__init__.py | 12 ++++++------ source/brailleViewer/__init__.py | 14 ++++++++++---- .../SystemTestSpy/speechSpyGlobalPlugin.py | 5 +++-- tests/unit/__init__.py | 3 ++- .../test_calculateWindowRowBufferOffsets.py | 5 +++-- .../test_handlerExtensionPoints.py | 18 ++++++++++++------ .../test_braille/test_windowBrailleCells.py | 5 +++-- 9 files changed, 49 insertions(+), 32 deletions(-) diff --git a/source/_remoteClient/localMachine.py b/source/_remoteClient/localMachine.py index b0c5cedc186..f2ffe66194d 100644 --- a/source/_remoteClient/localMachine.py +++ b/source/_remoteClient/localMachine.py @@ -140,7 +140,7 @@ def __init__(self) -> None: self._lastCells: list[int] = [] """Cached cells for display when we return from controling the local computer, or displaying a `ui.message`.""" - braille.decide_enabled.register(self.handleDecideEnabled) + braille.extensions.decide_enabled.register(self.handleDecideEnabled) braille.extensions._pre_showBrailleMessage.register(self._handleShowBrailleMessage) braille.extensions._post_dismissBrailleMessage.register(self._handleDismissBrailleMessage) braille.extensions._decide_disabledIncludesMessages.register( @@ -153,7 +153,7 @@ def terminate(self) -> None: :note: Unregisters the braille display handler to prevent memory leaks and ensure proper cleanup when the remote connection ends. """ - braille.decide_enabled.unregister(self.handleDecideEnabled) + braille.extensions.decide_enabled.unregister(self.handleDecideEnabled) braille.extensions._pre_showBrailleMessage.unregister(self._handleShowBrailleMessage) braille.extensions._post_dismissBrailleMessage.unregister(self._handleDismissBrailleMessage) braille.extensions._decide_disabledIncludesMessages.unregister( diff --git a/source/_remoteClient/session.py b/source/_remoteClient/session.py index 508ba78d814..661e58ce9d5 100644 --- a/source/_remoteClient/session.py +++ b/source/_remoteClient/session.py @@ -72,6 +72,7 @@ import braille.display import braille.display.driver import braille.display.gesture +import braille.extensions import brailleInput import gui import inputCore @@ -319,7 +320,7 @@ def __init__( RemoteMessageType.SET_DISPLAY_SIZE, self.setDisplaySize, ) - braille.filter_displayDimensions.register( + braille.extensions.filter_displayDimensions.register( self.localMachine._handleFilterDisplayDimensions, ) self.transport.registerInbound( @@ -344,7 +345,7 @@ def registerCallbacks(self) -> None: ) self.transport.registerOutbound(decide_playWaveFile, RemoteMessageType.WAVE) self.transport.registerOutbound(post_speechPaused, RemoteMessageType.PAUSE_SPEECH) - braille.pre_writeCells.register(self.display) + braille.extensions.pre_writeCells.register(self.display) pre_speechQueued.register(self.sendSpeech) self.callbacksAdded = True @@ -355,7 +356,7 @@ def unregisterCallbacks(self) -> None: self.transport.unregisterOutbound(RemoteMessageType.CANCEL) self.transport.unregisterOutbound(RemoteMessageType.WAVE) self.transport.unregisterOutbound(RemoteMessageType.PAUSE_SPEECH) - braille.pre_writeCells.unregister(self.display) + braille.extensions.pre_writeCells.unregister(self.display) pre_speechQueued.unregister(self.sendSpeech) self.callbacksAdded = False @@ -538,15 +539,15 @@ def __init__( def registerCallbacks(self) -> None: if self.callbacksAdded: return - braille.displayChanged.register(self.sendBrailleInfo) - braille.displaySizeChanged.register(self.sendBrailleInfo) + braille.extensions.displayChanged.register(self.sendBrailleInfo) + braille.extensions.displaySizeChanged.register(self.sendBrailleInfo) self.callbacksAdded = True def unregisterCallbacks(self) -> None: if not self.callbacksAdded: return - braille.displayChanged.unregister(self.sendBrailleInfo) - braille.displaySizeChanged.unregister(self.sendBrailleInfo) + braille.extensions.displayChanged.unregister(self.sendBrailleInfo) + braille.extensions.displaySizeChanged.unregister(self.sendBrailleInfo) self.callbacksAdded = False def handleNVDANotConnected(self) -> None: diff --git a/source/braille/__init__.py b/source/braille/__init__.py index bd2d4eb0904..75ab54277b2 100644 --- a/source/braille/__init__.py +++ b/source/braille/__init__.py @@ -92,13 +92,13 @@ def terminate(): # MovedSymbol("CONTEXTPRES_FILL", "braille.constants"), # MovedSymbol("CONTEXTPRES_SCROLL", "braille.constants"), # MovedSymbol("focusContextPresentations", "braille.constants"), - MovedSymbol("pre_writeCells", "braille.extensions"), - MovedSymbol("filter_displaySize", "braille.extensions"), - MovedSymbol("filter_displayDimensions", "braille.extensions"), - MovedSymbol("displaySizeChanged", "braille.extensions"), - MovedSymbol("displayChanged", "braille.extensions"), - MovedSymbol("decide_enabled", "braille.extensions"), MovedSymbol("BrailleMode", "config.configFlags"), MovedSymbol("TetherTo", "config.configFlags"), + # MovedSymbol("pre_writeCells", "braille.extensions"), + # MovedSymbol("filter_displaySize", "braille.extensions"), + # MovedSymbol("filter_displayDimensions", "braille.extensions"), + # MovedSymbol("displaySizeChanged", "braille.extensions"), + # MovedSymbol("displayChanged", "braille.extensions"), + # MovedSymbol("decide_enabled", "braille.extensions"), ) """Module level `__getattr__` used to preserve backward compatibility.""" diff --git a/source/brailleViewer/__init__.py b/source/brailleViewer/__init__.py index 1339f54182a..1dae9ab3c51 100644 --- a/source/brailleViewer/__init__.py +++ b/source/brailleViewer/__init__.py @@ -73,12 +73,17 @@ def destroyBrailleViewer(): _brailleGui = None # protect against re-entrance if d is not None: import braille # imported late to avoid a circular import. + import braille.extensions # imported late to avoid a circular import. if not d.isDestroyed: - updateBrailleDisplayedUnregistered = braille.pre_writeCells.unregister(d.updateBrailleDisplayed) + updateBrailleDisplayedUnregistered = braille.extensions.pre_writeCells.unregister( + d.updateBrailleDisplayed, + ) assert updateBrailleDisplayedUnregistered d.saveInfoAndDestroy() - getDisplayDimensionsUnregistered = braille.filter_displayDimensions.unregister(_getDisplayDimensions) + getDisplayDimensionsUnregistered = braille.extensions.filter_displayDimensions.unregister( + _getDisplayDimensions, + ) assert getDisplayDimensionsUnregistered @@ -108,11 +113,12 @@ def createBrailleViewerTool(): raise RuntimeError("Can not initialise the BrailleViewerGui: gui.mainFrame not yet initialised") import braille # imported late to avoid a circular import. + import braille.extensions # imported late to avoid a circular import. if not braille.handler: raise RuntimeError("Can not initialise the BrailleViewerGui: braille.handler not yet initialised") - braille.filter_displayDimensions.register(_getDisplayDimensions) + braille.extensions.filter_displayDimensions.register(_getDisplayDimensions) global _brailleGui if _brailleGui: @@ -122,5 +128,5 @@ def createBrailleViewerTool(): braille.handler.displaySize, _onGuiDestroyed, ) - braille.pre_writeCells.register(_brailleGui.updateBrailleDisplayed) + braille.extensions.pre_writeCells.register(_brailleGui.updateBrailleDisplayed) postBrailleViewerToolToggledAction.notify(created=True) diff --git a/tests/system/libraries/SystemTestSpy/speechSpyGlobalPlugin.py b/tests/system/libraries/SystemTestSpy/speechSpyGlobalPlugin.py index bb2cfa6be0a..c4a90ebc6ba 100644 --- a/tests/system/libraries/SystemTestSpy/speechSpyGlobalPlugin.py +++ b/tests/system/libraries/SystemTestSpy/speechSpyGlobalPlugin.py @@ -197,9 +197,10 @@ def queueNVDAUIAHandlerThreadCrash(self): def _onNvdaStartupComplete(self): self._isNvdaStartupComplete = True import braille + import braille.extensions - braille.filter_displayDimensions.register(self.getBrailleDisplayDimensions) - braille.pre_writeCells.register(self._onNvdaBraille) + braille.extensions.filter_displayDimensions.register(self.getBrailleDisplayDimensions) + braille.extensions.pre_writeCells.register(self._onNvdaBraille) def _onNvdaBraille(self, rawText: str): if not rawText: diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py index db30b3960d0..45ae6a68837 100644 --- a/tests/unit/__init__.py +++ b/tests/unit/__init__.py @@ -89,6 +89,7 @@ import braille # noqa: E402 import braille.display # noqa: E402 +import braille.extensions # noqa: E402 # Disable auto detection of braille displays when unit testing. config.conf["braille"]["display"] = "noBraille" @@ -103,7 +104,7 @@ def getFakeDisplayDimensions( return braille.display.DisplayDimensions(numRows=1, numCols=40) -braille.filter_displayDimensions.register(getFakeDisplayDimensions) +braille.extensions.filter_displayDimensions.register(getFakeDisplayDimensions) _original_handleReviewMove = braille.handler.handleReviewMove diff --git a/tests/unit/test_braille/test_calculateWindowRowBufferOffsets.py b/tests/unit/test_braille/test_calculateWindowRowBufferOffsets.py index e3ec379eb4b..7d9b22f6ca6 100644 --- a/tests/unit/test_braille/test_calculateWindowRowBufferOffsets.py +++ b/tests/unit/test_braille/test_calculateWindowRowBufferOffsets.py @@ -11,6 +11,7 @@ import braille import braille.buffers import braille.display +import braille.extensions import config from config.featureFlag import FeatureFlag from config.featureFlagEnums import BrailleTextWrapFlag @@ -40,10 +41,10 @@ def _setTextWrap(mode: BrailleTextWrapFlag) -> None: class TestCalculate(unittest.TestCase): def setUp(self): - braille.filter_displayDimensions.register(_getDisplayDimensions) + braille.extensions.filter_displayDimensions.register(_getDisplayDimensions) def tearDown(self): - braille.filter_displayDimensions.unregister(_getDisplayDimensions) + braille.extensions.filter_displayDimensions.unregister(_getDisplayDimensions) _setTextWrap(BrailleTextWrapFlag.NONE) # Remove instance-level overrides of auto-properties set by syllable-boundary tests. for attr in ("rawToBraillePos", "brailleToRawPos"): diff --git a/tests/unit/test_braille/test_handlerExtensionPoints.py b/tests/unit/test_braille/test_handlerExtensionPoints.py index d0898a9db05..91b704ce279 100644 --- a/tests/unit/test_braille/test_handlerExtensionPoints.py +++ b/tests/unit/test_braille/test_handlerExtensionPoints.py @@ -7,6 +7,7 @@ import braille import braille.display +import braille.extensions from ..extensionPointTestHelpers import actionTester, deciderTester, filterTester import unittest @@ -23,7 +24,7 @@ def test_pre_writeCells(self): currentCellCount=braille.handler.displaySize, ) - with actionTester(self, braille.pre_writeCells, **expectedKwargs): + with actionTester(self, braille.extensions.pre_writeCells, **expectedKwargs): braille.handler._writeCells(cells) def test_displaySizeChanged(self): @@ -33,7 +34,7 @@ def test_displaySizeChanged(self): numCols=braille.handler.displaySize, ) - with actionTester(self, braille.displaySizeChanged, **expectedKwargs): + with actionTester(self, braille.extensions.displaySizeChanged, **expectedKwargs): # Change the internal cache of the display size to trigger the action when getting the display size. braille.handler._displayDimensions = braille.display.DisplayDimensions(1, 0) # The getter should now trigger the action. @@ -45,7 +46,12 @@ def test_displayChanged(self): detected=None, ) - with actionTester(self, braille.displayChanged, useAssertDictContainsSubset=True, **expectedKwargs): + with actionTester( + self, + braille.extensions.displayChanged, + useAssertDictContainsSubset=True, + **expectedKwargs, + ): # Terminate the current noBraille instance to ensure that the action is triggered when choosing it again. braille.handler.display.terminate() braille.handler.display = None @@ -55,7 +61,7 @@ def test_filter_displayDimensions(self): cachedDisplayDimensions = braille.handler.displayDimensions with filterTester( self, - braille.filter_displayDimensions, + braille.extensions.filter_displayDimensions, cachedDisplayDimensions, braille.display.DisplayDimensions(5, 20), ) as expectedOutput: @@ -69,7 +75,7 @@ def test_filter_displaySize(self): cachedDisplaySize = braille.handler.displaySize with filterTester( self, - braille.filter_displaySize, + braille.extensions.filter_displaySize, cachedDisplaySize, # The currently cached display size 20, # The filter handler should change the display size to 20 ) as expectedOutput: @@ -80,7 +86,7 @@ def test_filter_displaySize(self): def test_decide_enabled(self): with deciderTester( self, - braille.decide_enabled, + braille.extensions.decide_enabled, expectedDecision=False, ) as expectedDecision: # Ensure that disabling braille by the decider doesn't try to call _handleEnabledDecisionFalse, diff --git a/tests/unit/test_braille/test_windowBrailleCells.py b/tests/unit/test_braille/test_windowBrailleCells.py index 064a203d2d9..04c19279444 100644 --- a/tests/unit/test_braille/test_windowBrailleCells.py +++ b/tests/unit/test_braille/test_windowBrailleCells.py @@ -11,6 +11,7 @@ import braille.buffers import braille.constants import braille.display +import braille.extensions def _getDisplayDimensions(dimensions: braille.display.DisplayDimensions) -> braille.display.DisplayDimensions: @@ -23,10 +24,10 @@ def _getDisplayDimensions(dimensions: braille.display.DisplayDimensions) -> brai class TestWindowBrailleCells(unittest.TestCase): def setUp(self): - braille.filter_displayDimensions.register(_getDisplayDimensions) + braille.extensions.filter_displayDimensions.register(_getDisplayDimensions) def tearDown(self): - braille.filter_displayDimensions.unregister(_getDisplayDimensions) + braille.extensions.filter_displayDimensions.unregister(_getDisplayDimensions) def test_continuationRow_hasContinuationShape(self): """A row with hasContinuation=True gets CONTINUATION_SHAPE as its last cell.""" From 76a47ffdf0a5bc83bd9ab9aec5016f7533ed21e9 Mon Sep 17 00:00:00 2001 From: Sascha Cowley <16543535+SaschaCowley@users.noreply.github.com> Date: Thu, 9 Jul 2026 18:46:46 +1000 Subject: [PATCH 13/15] config.configFlags.{BrailleMode, TetherTo} --- source/braille/__init__.py | 4 ++-- source/gui/settingsDialogs.py | 11 ++++++----- tests/unit/test_braille/test_routing.py | 3 ++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/source/braille/__init__.py b/source/braille/__init__.py index 75ab54277b2..6eb5cf027f9 100644 --- a/source/braille/__init__.py +++ b/source/braille/__init__.py @@ -92,13 +92,13 @@ def terminate(): # MovedSymbol("CONTEXTPRES_FILL", "braille.constants"), # MovedSymbol("CONTEXTPRES_SCROLL", "braille.constants"), # MovedSymbol("focusContextPresentations", "braille.constants"), - MovedSymbol("BrailleMode", "config.configFlags"), - MovedSymbol("TetherTo", "config.configFlags"), # MovedSymbol("pre_writeCells", "braille.extensions"), # MovedSymbol("filter_displaySize", "braille.extensions"), # MovedSymbol("filter_displayDimensions", "braille.extensions"), # MovedSymbol("displaySizeChanged", "braille.extensions"), # MovedSymbol("displayChanged", "braille.extensions"), # MovedSymbol("decide_enabled", "braille.extensions"), + # MovedSymbol("BrailleMode", "config.configFlags"), + # MovedSymbol("TetherTo", "config.configFlags"), ) """Module level `__getattr__` used to preserve backward compatibility.""" diff --git a/source/gui/settingsDialogs.py b/source/gui/settingsDialogs.py index b1e00ec38a3..101a3a48d81 100644 --- a/source/gui/settingsDialogs.py +++ b/source/gui/settingsDialogs.py @@ -82,6 +82,7 @@ TetherTo, TypingEcho, LoggingLevel, + BrailleMode, ) from logHandler import log from synthDriverHandler import SynthDriver, changeVoice, getSynth, getSynthList, setSynth @@ -5273,12 +5274,12 @@ def makeSettings(self, settingsSizer): ) # Translators: The label for a setting in braille settings to select which braille mode to use modeListText = _("Braille mode:") - modeChoices = [x.displayString for x in braille.BrailleMode] + modeChoices = [x.displayString for x in BrailleMode] self.brailleModes = sHelper.addLabeledControl(modeListText, wx.Choice, choices=modeChoices) self.bindHelpEvent("BrailleMode", self.brailleModes) self.brailleModes.Bind(wx.EVT_CHOICE, self._onModeChange) - current = braille.BrailleMode(config.conf["braille"]["mode"]) - modeList = list(braille.BrailleMode) + current = BrailleMode(config.conf["braille"]["mode"]) + modeList = list(BrailleMode) index = modeList.index(current) self.brailleModes.SetSelection(index) followCursorGroupSizer = wx.StaticBoxSizer(wx.VERTICAL, self) @@ -5538,7 +5539,7 @@ def makeSettings(self, settingsSizer): self.speakOnNavigatingCheckBox.Value = config.conf["braille"]["speakOnNavigatingByUnit"] self.followCursorGroupBox.Enable( - list(braille.BrailleMode)[self.brailleModes.GetSelection()] is braille.BrailleMode.FOLLOW_CURSORS, + list(BrailleMode)[self.brailleModes.GetSelection()] is BrailleMode.FOLLOW_CURSORS, ) self.textWrapComboBox: nvdaControls.FeatureFlagCombo = sHelper.addLabeledControl( @@ -5606,7 +5607,7 @@ def onSave(self): else: brailleInput.handler.table = self.inTableForCurLang config.conf["braille"]["inputTable"] = "auto" - mode = list(braille.BrailleMode)[self.brailleModes.GetSelection()] + mode = list(BrailleMode)[self.brailleModes.GetSelection()] config.conf["braille"]["mode"] = mode.value braille.handler.mainBuffer.clear() config.conf["braille"]["expandAtCursor"] = self.expandAtCursorCheckBox.GetValue() diff --git a/tests/unit/test_braille/test_routing.py b/tests/unit/test_braille/test_routing.py index 0a0eba75a57..ed4a158b8ad 100644 --- a/tests/unit/test_braille/test_routing.py +++ b/tests/unit/test_braille/test_routing.py @@ -9,6 +9,7 @@ import braille import braille.regions.base import braille.regions.textInfo +from config.configFlags import TetherTo import textInfos import api import controlTypes @@ -81,7 +82,7 @@ class TestReviewRoutingMovesSystemCaretInNavigableText(unittest.TestCase): def setUp(self): # Set tethering to review. - braille.handler.setTether(braille.TetherTo.REVIEW.value) + braille.handler.setTether(TetherTo.REVIEW.value) cmText = "the quick brown fox jumps over the lazy dog" cm = self.cm = CursorManager(text=cmText) cm.role = controlTypes.Role.EDITABLETEXT From a5097d5408903654fc36fdf614f4a2f4bdfb8b82 Mon Sep 17 00:00:00 2001 From: Sascha Cowley <16543535+SaschaCowley@users.noreply.github.com> Date: Thu, 9 Jul 2026 19:11:14 +1000 Subject: [PATCH 14/15] Replace backcompat shim and tests --- source/braille/__init__.py | 120 +++++++++--------- tests/unit/test_braille/test_publicSurface.py | 1 - 2 files changed, 60 insertions(+), 61 deletions(-) diff --git a/source/braille/__init__.py b/source/braille/__init__.py index 6eb5cf027f9..01bcbe9c935 100644 --- a/source/braille/__init__.py +++ b/source/braille/__init__.py @@ -40,65 +40,65 @@ def terminate(): # Deprecated in 2026.3. __getattr__ = handleDeprecations( - # MovedSymbol("BrailleDisplayDriver", "braille.display.driver"), - # MovedSymbol("BrailleDisplayGesture", "braille.display.gesture"), - # MovedSymbol("getSerialPorts", "braille.display"), - # MovedSymbol("getDisplayList", "braille.display"), - # MovedSymbol("getDisplayDrivers", "braille.display"), - # MovedSymbol("RENAMED_DRIVERS", "braille.display"), - # MovedSymbol("DisplayDimensions", "braille.display"), - # MovedSymbol("Region", "braille.regions.base"), - # MovedSymbol("RegionWithPositions", "braille.regions.base"), - # MovedSymbol("TextRegion", "braille.regions.base"), - # MovedSymbol("rindex", "braille.regions.base"), - # MovedSymbol("NVDAObjectRegion", "braille.regions.NVDAObject"), - # MovedSymbol("ReviewNVDAObjectRegion", "braille.regions.NVDAObject"), - # MovedSymbol("NVDAObjectHasUsefulText", "braille.regions.NVDAObject"), - # MovedSymbol("TextInfoRegion", "braille.regions.textInfo"), - # MovedSymbol("CursorManagerRegion", "braille.regions.textInfo"), - # MovedSymbol("ReviewTextInfoRegion", "braille.regions.textInfo"), - # MovedSymbol("ReviewCursorManagerRegion", "braille.regions.textInfo"), - # MovedSymbol("getControlFieldBraille", "braille.regions.properties"), - # MovedSymbol("getFormatFieldBraille", "braille.regions.properties"), - # MovedSymbol("getPropertiesBraille", "braille.regions.properties"), - # MovedSymbol("getFocusContextRegions", "braille.regions.focus"), - # MovedSymbol("getFocusRegions", "braille.regions.focus"), - # MovedSymbol("invalidateCachedFocusAncestors", "braille.regions.focus"), - # MovedSymbol("BrailleBuffer", "braille.buffers"), - # MovedSymbol("BrailleHandler", "braille.brailleHandler"), - # MovedSymbol("formatCellsForLog", "braille.brailleHandler"), - # MovedSymbol("FALLBACK_TABLE", "braille.brailleHandler"), - # MovedSymbol("roleLabels", "braille.labels"), - # MovedSymbol("positiveStateLabels", "braille.labels"), - # MovedSymbol("negativeStateLabels", "braille.labels"), - # MovedSymbol("landmarkLabels", "braille.labels"), - # MovedSymbol("FormatTagDelimiter", "braille.formatting"), - # MovedSymbol("FormattingMarker", "braille.formatting"), - # MovedSymbol("fontAttributeFormattingMarkers", "braille.formatting"), - # MovedSymbol("getParagraphStartMarker", "braille.formatting"), - # MovedSymbol("AUTO_DISPLAY_NAME", "braille.constants"), - # MovedSymbol("AUTOMATIC_PORT", "braille.constants"), - # MovedSymbol("BLUETOOTH_PORT", "braille.constants"), - # MovedSymbol("USB_PORT", "braille.constants"), - # MovedSymbol("NO_BRAILLE_DISPLAY_NAME", "braille.constants"), - # MovedSymbol("CONTINUATION_SHAPE", "braille.constants"), - # MovedSymbol("CURSOR_SHAPES", "braille.constants"), - # MovedSymbol("SELECTION_SHAPE", "braille.constants"), - # MovedSymbol("END_OF_BRAILLE_OUTPUT_SHAPE", "braille.constants"), - # MovedSymbol("INPUT_START_IND", "braille.constants"), - # MovedSymbol("INPUT_END_IND", "braille.constants"), - # MovedSymbol("TEXT_SEPARATOR", "braille.constants"), - # MovedSymbol("CONTEXTPRES_CHANGEDCONTEXT", "braille.constants"), - # MovedSymbol("CONTEXTPRES_FILL", "braille.constants"), - # MovedSymbol("CONTEXTPRES_SCROLL", "braille.constants"), - # MovedSymbol("focusContextPresentations", "braille.constants"), - # MovedSymbol("pre_writeCells", "braille.extensions"), - # MovedSymbol("filter_displaySize", "braille.extensions"), - # MovedSymbol("filter_displayDimensions", "braille.extensions"), - # MovedSymbol("displaySizeChanged", "braille.extensions"), - # MovedSymbol("displayChanged", "braille.extensions"), - # MovedSymbol("decide_enabled", "braille.extensions"), - # MovedSymbol("BrailleMode", "config.configFlags"), - # MovedSymbol("TetherTo", "config.configFlags"), + MovedSymbol("BrailleDisplayDriver", "braille.display.driver"), + MovedSymbol("BrailleDisplayGesture", "braille.display.gesture"), + MovedSymbol("getSerialPorts", "braille.display"), + MovedSymbol("getDisplayList", "braille.display"), + MovedSymbol("getDisplayDrivers", "braille.display"), + MovedSymbol("RENAMED_DRIVERS", "braille.display"), + MovedSymbol("DisplayDimensions", "braille.display"), + MovedSymbol("Region", "braille.regions.base"), + MovedSymbol("RegionWithPositions", "braille.regions.base"), + MovedSymbol("TextRegion", "braille.regions.base"), + MovedSymbol("rindex", "braille.regions.base"), + MovedSymbol("NVDAObjectRegion", "braille.regions.NVDAObject"), + MovedSymbol("ReviewNVDAObjectRegion", "braille.regions.NVDAObject"), + MovedSymbol("NVDAObjectHasUsefulText", "braille.regions.NVDAObject"), + MovedSymbol("TextInfoRegion", "braille.regions.textInfo"), + MovedSymbol("CursorManagerRegion", "braille.regions.textInfo"), + MovedSymbol("ReviewTextInfoRegion", "braille.regions.textInfo"), + MovedSymbol("ReviewCursorManagerRegion", "braille.regions.textInfo"), + MovedSymbol("getControlFieldBraille", "braille.regions.properties"), + MovedSymbol("getFormatFieldBraille", "braille.regions.properties"), + MovedSymbol("getPropertiesBraille", "braille.regions.properties"), + MovedSymbol("getFocusContextRegions", "braille.regions.focus"), + MovedSymbol("getFocusRegions", "braille.regions.focus"), + MovedSymbol("invalidateCachedFocusAncestors", "braille.regions.focus"), + MovedSymbol("BrailleBuffer", "braille.buffers"), + MovedSymbol("BrailleHandler", "braille.brailleHandler"), + MovedSymbol("formatCellsForLog", "braille.brailleHandler"), + MovedSymbol("FALLBACK_TABLE", "braille.brailleHandler"), + MovedSymbol("roleLabels", "braille.labels"), + MovedSymbol("positiveStateLabels", "braille.labels"), + MovedSymbol("negativeStateLabels", "braille.labels"), + MovedSymbol("landmarkLabels", "braille.labels"), + MovedSymbol("FormatTagDelimiter", "braille.formatting"), + MovedSymbol("FormattingMarker", "braille.formatting"), + MovedSymbol("fontAttributeFormattingMarkers", "braille.formatting"), + MovedSymbol("getParagraphStartMarker", "braille.formatting"), + MovedSymbol("AUTO_DISPLAY_NAME", "braille.constants"), + MovedSymbol("AUTOMATIC_PORT", "braille.constants"), + MovedSymbol("BLUETOOTH_PORT", "braille.constants"), + MovedSymbol("USB_PORT", "braille.constants"), + MovedSymbol("NO_BRAILLE_DISPLAY_NAME", "braille.constants"), + MovedSymbol("CONTINUATION_SHAPE", "braille.constants"), + MovedSymbol("CURSOR_SHAPES", "braille.constants"), + MovedSymbol("SELECTION_SHAPE", "braille.constants"), + MovedSymbol("END_OF_BRAILLE_OUTPUT_SHAPE", "braille.constants"), + MovedSymbol("INPUT_START_IND", "braille.constants"), + MovedSymbol("INPUT_END_IND", "braille.constants"), + MovedSymbol("TEXT_SEPARATOR", "braille.constants"), + MovedSymbol("CONTEXTPRES_CHANGEDCONTEXT", "braille.constants"), + MovedSymbol("CONTEXTPRES_FILL", "braille.constants"), + MovedSymbol("CONTEXTPRES_SCROLL", "braille.constants"), + MovedSymbol("focusContextPresentations", "braille.constants"), + MovedSymbol("pre_writeCells", "braille.extensions"), + MovedSymbol("filter_displaySize", "braille.extensions"), + MovedSymbol("filter_displayDimensions", "braille.extensions"), + MovedSymbol("displaySizeChanged", "braille.extensions"), + MovedSymbol("displayChanged", "braille.extensions"), + MovedSymbol("decide_enabled", "braille.extensions"), + MovedSymbol("BrailleMode", "config.configFlags"), + MovedSymbol("TetherTo", "config.configFlags"), ) """Module level `__getattr__` used to preserve backward compatibility.""" diff --git a/tests/unit/test_braille/test_publicSurface.py b/tests/unit/test_braille/test_publicSurface.py index deb0e542b5c..002d62797df 100644 --- a/tests/unit/test_braille/test_publicSurface.py +++ b/tests/unit/test_braille/test_publicSurface.py @@ -126,7 +126,6 @@ def test_residentNamesAccessibleWithoutWarning(self): ) mockLog.warning.assert_not_called() - @unittest.skip def test_deprecatedNamesReturnCorrectObject(self): """Each deprecated name must resolve to the same object as the new-home import.""" for name, expected in DEPRECATED.items(): From c64c463bb01aaec8690e36c76354bea86d4bedf2 Mon Sep 17 00:00:00 2001 From: Sascha Cowley <16543535+SaschaCowley@users.noreply.github.com> Date: Thu, 16 Jul 2026 12:06:20 +1000 Subject: [PATCH 15/15] Add PR reference to changes --- user_docs/en/changes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_docs/en/changes.md b/user_docs/en/changes.md index 6befac7d53e..0b7594442ae 100644 --- a/user_docs/en/changes.md +++ b/user_docs/en/changes.md @@ -65,7 +65,7 @@ Please refer to [the developer guide](https://download.nvaccess.org/documentatio * In the `installTasks` module, add-on developers can add a spec for each configuration section to be registered. * The `config.configSections.registerSection` method can be used in the `onInstall` function. * To register a section to be used in the normal configuration, regardless of profiles, the `isBaseOnly` parameter should be set to `True`. -* The `braille` module is now a package, split into focused submodules such as `braille.constants`, `braille.labels`, `braille.formatting`, `braille.regions`, `braille.display`, `braille.buffers`, `braille.brailleHandler` and `braille.extensions`. (#12772, @LeonarddeR) +* The `braille` module is now a package, split into focused submodules such as `braille.constants`, `braille.labels`, `braille.formatting`, `braille.regions`, `braille.display`, `braille.buffers`, `braille.brailleHandler` and `braille.extensions`. (#12772, #20458, @LeonarddeR) * Added `gui.message.HtmlMessageDialog`, a `MessageDialog` subclass that renders a full HTML document in a `wx.html2.WebView`. (#18878, @LeonarddeR) * The WebView backend can be overridden via the `_webViewBackend` class attribute, which defaults to the IE backend. * JavaScript in the message can trigger NVDA actions by navigating to `nvda-action://` URLs; `close` is handled internally and other actions can be registered with `registerAction`.