Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support IAccessible2 labelled-by relation (#17437)
* Support IAccessible2 labelled-by relation ### Link to issue number: Fixes #17436 ### Summary of the issue: IAccessible2 has an IA2_RELATION_LABELLED_BY relation type, see https://accessibility.linuxfoundation.org/a11yspecs/ia2/docs/html/group__grp_relations.html#ga7bbace7ffb57476b75d621af2e27d1ff . However, that one was not taken into account by NVDA's "labeledBy" property for objects. This could could be seen for example with LibreOffice that implements handling of that IAccessible2 relation. Additionally, a `None` return value from IAccessibleHandler.accNavigate wasn't handled in `IAccessible._get_labeledBy`, triggering an error, e.g.: >>> focus.labeledBy Traceback (most recent call last): File "<console>", line 1, in <module> File "C:\tools\cygwin\home\user\development\git\nvda\source\baseObject.py", line 59, in __get__ return instance._getPropertyViaCache(self.fget) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\tools\cygwin\home\user\development\git\nvda\source\baseObject.py", line 167, in _getPropertyViaCache val = getterMethod(self) ^^^^^^^^^^^^^^^^^^ File "C:\tools\cygwin\home\user\development\git\nvda\source\NVDAObjects\IAccessible\__init__.py", line 1167, in _get_labeledBy (pacc, accChild) = IAccessibleHandler.accNavigate( ^^^^^^^^^^^^^^^^ TypeError: cannot unpack non-iterable NoneType object ### Description of user facing changes In NVDA's Python console, retrieving the "labeledBy" property now works for objects in applications implementing the "labelled-by" IAccessible2 relation and no longer triggers an error. ### Description of development approach * Extend `IAccessibleHandler.RelationType` with the `LABELLED_BY` relation as defined in the IAccessible2 spec. * Use this relation in `IAccessible._get_labeledBy` before falling back to trying a custom Mozilla/Gecko specific NAVRELATION. * Add handling for the case where `IAccessibleHandler.accNavigate` for the custom Mozilla/Geck approach returns `None` to fix the error triggered otherwise when no relation is set. ### Testing strategy: 1. start NVDA 2. Start LibreOffice Writer 3. open the options dialog: "Tools" -> "Options", go to the "User Data" page 4. move focus to the "Company" text edit 5. open NVDA's Python console (Ctrl+Insert+Z) 6. print the object that the currently focused edit is labelled by, and it's accessible name and role: >>> focus.labeledBy <NVDAObjects.IAccessible.IAccessible object at 0x0BC55A70> >>> focus.labeledBy.name 'Company:' >>> focus.labeledBy.role <Role.STATICTEXT: 7> ### Known issues with pull request: None ### Code Review Checklist: - [x] Documentation: - Change log entry - User Documentation - Developer / Technical Documentation - Context sensitive help for GUI changes - [x] Testing: - Unit tests - System (end to end) tests - Manual testing - [x] UX of all users considered: - Speech - Braille - Low Vision - Different web browsers - Localization in other languages / culture than English - [x] API is compatible with existing add-ons. - [x] Security precautions taken. <!-- Please keep the following --> @coderabbitai summary * Add type annotation * Move changelog entry to "Changes for Developers" section * Avoid type clash due to typing.List import Use qualified name. Otherwise the newly introduced from __future__ import annotations in commit feea4aa Author: Michael Weghorn <[email protected]> Date: Wed Nov 27 09:12:38 2024 +0000 Add type annotation causes source/NVDAObjects/IAccessible/__init__.py:2391:7: F811 Redefinition of unused `List` from line 13 | 2391 | class List(IAccessible): | ^^^^ F811 2392 | def _get_role(self): 2393 | return controlTypes.Role.LIST | = help: Remove definition: `List` Found 1 error. * Apply suggestions from code review * Add comment why import is needed Without deferred evaluation (s. PEPs mentioned in the newly added comment): $ ./runlint.bat Ensuring NVDA Python virtual environment call ruff check --fix source\NVDAObjects\IAccessible\__init__.py:1165:30: F821 Undefined name `IAccessible` | 1163 | return True 1164 | 1165 | def _get_labeledBy(self) -> IAccessible | None: | ^^^^^^^^^^^ F821 1166 | label = self._getIA2RelationFirstTarget(IAccessibleHandler.RelationType.LABELLED_BY) 1167 | if label: | Found 1 error. Deactivating NVDA Python virtual environment * Apply suggestions from code review * Update source/NVDAObjects/IAccessible/__init__.py * Update source/NVDAObjects/IAccessible/__init__.py --------- Co-authored-by: Sean Budd <[email protected]> Co-authored-by: Sean Budd <[email protected]>
- Loading branch information