Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IAccessible2 "labelled-by" property not supported #17436

Closed
michaelweghorn opened this issue Nov 26, 2024 · 1 comment · Fixed by #17437
Closed

IAccessible2 "labelled-by" property not supported #17436

michaelweghorn opened this issue Nov 26, 2024 · 1 comment · Fixed by #17437
Milestone

Comments

@michaelweghorn
Copy link
Contributor

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 is not taken into account by NVDA's "labeledBy" property for objects, as can be seen for example with LibreOffice that implements handling of the IAccessible2 property.

Steps to reproduce:

  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. try to print the object that the currently focused edit is labelled by:
>>> 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

Actual behavior:

An error occurs, s. above

Expected behavior:

The label that is referenced by the IA2_RELATION_LABELLED_BY relation should be returned/printed in the Python console.

NVDA logs, crash dumps and other attachments:

System configuration

NVDA installed/portable/running from source:

running from source

NVDA version:

git master as of commit c32e0e7

Windows version:

Windows 10 22H2

Name and version of other software in use when reproducing the issue:

LibreOffice

Version: 25.2.0.0.alpha1+ (X86_64) / LibreOffice Community
Build ID: 4049405dcde61fa66852dae72d811562c69b3920
CPU threads: 12; OS: Windows 10 X86_64 (10.0 build 19045); UI render: default; VCL: win
Locale: en-GB (en_GB); UI: en-US
Calc: threaded

Other information about your system:

Other questions

Does the issue still occur after restarting your computer?

n/a

Have you tried any other versions of NVDA? If so, please report their behaviors.

NVDA 2024.3, same behavior

If NVDA add-ons are disabled, is your problem still occurring?

n/a

Does the issue still occur after you run the COM Registration Fixing Tool in NVDA's tools menu?

n/a

@michaelweghorn
Copy link
Contributor Author

I plan to submit a PR to fix this.

michaelweghorn added a commit to michaelweghorn/nvda that referenced this issue Nov 26, 2024
 ### Link to issue number:

Fixes nvaccess#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 target of 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
michaelweghorn added a commit to michaelweghorn/nvda that referenced this issue Nov 26, 2024
 ### Link to issue number:

Fixes nvaccess#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 target of 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
michaelweghorn added a commit to michaelweghorn/nvda that referenced this issue Nov 26, 2024
 ### Link to issue number:

Fixes nvaccess#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
seanbudd added a commit that referenced this issue Dec 2, 2024
* 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]>
@github-actions github-actions bot added this to the 2025.1 milestone Dec 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant