Skip to content

added toLWTH conversion if startLocation is rectLTRB#14671

Merged
seanbudd merged 8 commits into
nvaccess:masterfrom
FalkoBabbage:rectConversionFix12424
Apr 3, 2023
Merged

added toLWTH conversion if startLocation is rectLTRB#14671
seanbudd merged 8 commits into
nvaccess:masterfrom
FalkoBabbage:rectConversionFix12424

Conversation

@FalkoBabbage

@FalkoBabbage FalkoBabbage commented Feb 24, 2023

Copy link
Copy Markdown
Contributor

Link to issue number:

Fixes #12424

Summary of the issue:

JABTextInfo can return rectLTRB which is then used in the boudingRects property. this can be an issue for functions that expect rectLTWH types to be returned.

Description of user facing changes

None

Description of development approach

walked through where JABTextInfo could return a rectLTRB instance. found it

Testing strategy:

Ran runnvda.bat with adjusted code. Followed the steps in issue 12424 to reproduce the error and got a valid answer instead.

Known issues with pull request:

Change log entries:

New features
Changes
Bug fixes
For Developers
-offsets.OffsetsTextInfo._get_boundingRects return type is specified to List[locationHelper.rectLTWH] as conform to textInfos.TextInfo._get_boundingRects. offsets.OffsetsTextInfo._get_boundingRects is adjusted to always return the specified type.

Code Review Checklist:

  • Pull Request description:
    • description is up to date
    • change log entries
  • Testing:
    • Unit tests
    • System (end to end) tests
    • Manual testing
  • API is compatible with existing add-ons.
  • Documentation:
    • User Documentation
    • Developer / Technical Documentation
    • Context sensitive help for GUI changes
  • UX of all users considered:
    • Speech
    • Braille
    • Low Vision
    • Different web browsers
    • Localization in other languages / culture than English
  • Security precautions taken.

@FalkoBabbage FalkoBabbage requested a review from a team as a code owner February 24, 2023 14:13
@AppVeyorBot

Copy link
Copy Markdown

See test results for failed build of commit a60df41c12

@seanbudd

Copy link
Copy Markdown
Member

Hi @FalkoBabbage, I don't think that change log description is appropriate for bug fixes.
If there are user facing changes, list them there.
Otherwise can we put in "changes for developers"?

I'm also not sure if this description is specific enough:

-OffsetsTextInfo.boundingRects sometimes returned rectLTRB instances in some JAB textInfo objects, this is no longer the case.

What does it return instead now?

Can you add typing information to _get_boundingRects?

Considering that rectLTRB was returned previously, will changing this return type be an API breakage?
What do other parts of NVDA expect as a type here?

@seanbudd seanbudd marked this pull request as draft February 27, 2023 22:41
@FalkoBabbage

Copy link
Copy Markdown
Contributor Author

Hi @seanbudd.
I agree that this should be in "changes for developers", since the bugs that it fixes occur later down the line.

I'm also not sure if this description is specific enough:

The origin of the error that I occurred is as follows:

  1. I try to retrieve the boundingRects property of a JAB text info. The _get_boundingRects method that is used is from textInfos.offsets.OffsetsTextInfo
  2. the _get_boundingRects method uses _getBoundingRectFromOffset for with the startoffset to get the startLocation. If the endoffset is bigger than startOffset + 1, all rectangles that are obtained from _getBoundingRectFromOffset for each offset are put through the function locationHelper.RectLTWH.fromCollection, making it automatically a rectLTWH.
  3. If the endoffset is not bigger than startOffset + 1, the startLocation is only checked if this is a point. If it is not a point, the start location is put into the rects list as is.
  4. _getBoundingRectFromOffset does not have any type hinting. In JABTextInfo in NVDAObjects/JAB/init.py this function explicitly returns a rectLTRB.

Maybe the following is better to describe the changes:
"_get_boundingRects" is assumed to return locationHelper.rectLTWH types, but for textInfos.offsets.OffsetsTextInfo there there can be situations where a instance of locationHelper.rectLTRB is returned. This is solved by adding an explicit conversion to rectLTWH on the location where a rectLTRB can occur.

Can you add typing information to _get_boundingRects?

In textInfos/init.py the _get_boundingRects method of the class TextInfo already specifies the return type locationHelper.RectLTWH in its comment. This is not enforced by the typing module and is just a comment.

Considering that rectLTRB was returned previously, will changing this return type be an API breakage?
What do other parts of NVDA expect as a type here?

Since _get_boundingRects does not have the return type enforced there indeed might be pieces of code that expect a rectLTRB, But considering the indicated return type of _get_boundingRects they shouldn't and therefore I wouldn't consider it a breaking API change.

@seanbudd

seanbudd commented Mar 2, 2023

Copy link
Copy Markdown
Member

Thanks for explaining the bug in more detail.

In textInfos/init.py the _get_boundingRects method of the class TextInfo already specifies the return type locationHelper.RectLTWH in its comment. This is not enforced by the typing module and is just a comment.

Can you please add typing information to the function header here. For example def func(self) -> List[locationHelper.RectLTWH]:

def _get_boundingRects(self):

Since _get_boundingRects does not have the return type enforced there indeed might be pieces of code that expect a rectLTRB, But considering the indicated return type of _get_boundingRects they shouldn't and therefore I wouldn't consider it a breaking API change.

Ah I see, makes sense. Thanks for explaining

@FalkoBabbage

Copy link
Copy Markdown
Contributor Author

Can you please add typing information to the function header here. For example def func(self) -> List[locationHelper.RectLTWH]:

_get_boundingRects is defined in textInfos.TextInfo. I suggest to add the correct typing there if that is desired since I assume that any override would also be "forced" to use this type. Should
I also add typing for all other overrides for _get_boundingRects?

@seanbudd

seanbudd commented Mar 6, 2023

Copy link
Copy Markdown
Member

I think it would be sufficient to just add it for the function you updated.

… only startLocation is used to make _get_boundingRects
@AppVeyorBot

Copy link
Copy Markdown

See test results for failed build of commit 9cac227d01

@AppVeyorBot

Copy link
Copy Markdown

See test results for failed build of commit bd715df7a1

@FalkoBabbage

Copy link
Copy Markdown
Contributor Author

I do not understand the failed link check from appveyor:

source/textInfos/offsets.py:183:2: C901 'OffsetsTextInfo._get_boundingRects' is too complex (19)
def _get_boundingRects(self) -> List[locationHelper.RectLTWH]:
^
1 C901 'OffsetsTextInfo._get_boundingRects' is too complex (19)

Should I also reduce complexity of the function in order to do finish this pr?

@FalkoBabbage

Copy link
Copy Markdown
Contributor Author

I have looked into reducing the complexity but as far as I know that would mean that I have to split up the function into different subfunctions. In that case we would end up with more methods in the OffsetsTextInfo class which should also make sense for its child-classes downstream.
Besides, I am not sure why appveyor flags my code as to complex. I have already reduced the existing complexity of this function by removing an if/else statement.

@CyrilleB79

Copy link
Copy Markdown
Contributor

Besides, I am not sure why appveyor flags my code as to complex. I have already reduced the existing complexity of this function by removing an if/else statement.

The linter only checks the code that you have modified. And among others, it checks the complexity of the functions that you have modified. It does not care if you reduced the complexity, it just check if it is too high or not. The original function was very too complex. But it has probably been written before the linter check was introduced.

You have two options:

  • Either you split the function to reduce its complexity
  • Or (if NVAccess agrees with it), given you have modified only few lines of this function, you may add a #noqa directive to ignore the complexity.

If it's not too much work and depending on the impact of the modifications, the first solution is preferred. This allows the code to converge towards a linted code.

@seanbudd

Copy link
Copy Markdown
Member

Either option @CyrilleB79 suggested here is appropriate. Search for C901 for functions handled in a similar way.

@FalkoBabbage

FalkoBabbage commented Mar 28, 2023

Copy link
Copy Markdown
Contributor Author

I have decided to add a #noqa to the function. Splitting this function into multiple functions would mean that these new functions should also make sense for all classes that inherent this class, which would take quite some time to figure out on my part.

@seanbudd seanbudd marked this pull request as ready for review March 29, 2023 01:07
return ", ".join(textList)

def _get_boundingRects(self):
def _get_boundingRects(self) -> List[locationHelper.RectLTWH]: # noqa: C901

@seanbudd seanbudd Mar 29, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please see similar comments in the NVDA code base and apply the full message (search C901)

@seanbudd seanbudd left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @FalkoBabbage

@seanbudd seanbudd merged commit bf676b5 into nvaccess:master Apr 3, 2023
@nvaccessAuto nvaccessAuto added this to the 2023.2 milestone Apr 3, 2023
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 this pull request may close these issues.

vision Rect conversion bug

5 participants