After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 585643 - Bad assumption about len(utterances[0]) in soffice script
Bad assumption about len(utterances[0]) in soffice script
Status: RESOLVED FIXED
Product: orca
Classification: Applications
Component: general
unspecified
Other All
: Normal normal
: 2.28.0
Assigned To: Joanmarie Diggs (IRC: joanie)
Orca Maintainers
Depends on:
Blocks:
 
 
Reported: 2009-06-13 12:40 UTC by Willie Walker
Modified: 2009-11-09 21:35 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
move the decision to the speech generator (1.77 KB, patch)
2009-06-13 19:03 UTC, Joanmarie Diggs (IRC: joanie)
committed Details | Review

Description Willie Walker 2009-06-13 12:40:09 UTC
This is an offshoot of bug #585417.  The addition of pause capability to the formatting strings has exposed a bad piece of code that is digging into utterances to make a decision.  This is generally a bad thing to do (pre and post speech generator) -- unless absolutely 100% necessary, the generator output should typically be treated as a black box of stuff to be sent to speech.

The suspect code is in src/orca/scripts/apps/soffice/script.py:

        # [[[TODO: WDW - need to make sure assumption about utterances[0]
        # is still correct with the new speech generator stuff.]]]
        #
        if not len(utterances[0]) and self.speakBlankLine(newFocus):

The original code looks like it may have been added sometime around 2008-09-06, though it may have just been moved there as the result of a bigger code change that happened that day.

Joanie - that change has your name on it.  Can you help me out here, please?  I'm wondering if we can move the above decision into the speech generator and/or formatting string for soffice.
Comment 1 Willie Walker 2009-06-13 12:55:13 UTC
PS - in reading the opener, I didn't mean for it to sound like I'm jumping on Joanie for this.  Many many many apologies if it comes across that way.  :-( The intended tone is more of noticing that Joanie had been in this area of code.  I need her help solving the problem because I'm not fully familiar with the intended user experience for this portion of the code.
Comment 2 Willie Walker 2009-06-13 13:20:50 UTC
In particular, soffice's script.py has a 'presentTableInfo' method that might be moved to a _generateTableInfo method in soffice's speech_generator.  We that, we might add a tableInfo section to the formatting strings somewhere (e.g., a new ROLE_PARAGRAPH).

soffice's locusfFocusChanged method is pretty extensive, however, so I think this might end up being rather involved.
Comment 3 Joanmarie Diggs (IRC: joanie) 2009-06-13 19:03:28 UTC
Created attachment 136517 [details] [review]
move the decision to the speech generator

It would/will be nice to move the logic currently in presentTableInfo into a _generateWhatever method. Because we have a similar method/need in structural_navigation.py, I will look at doing so as part of that refactor.

In the meantime, to address this bug, why not just move the logic into the speech generator for soffice?

Pylinted and regression tested. Will, please review. Thanks!
Comment 4 Willie Walker 2009-06-13 23:51:26 UTC
(In reply to comment #3)
> In the meantime, to address this bug, why not just move the logic into the
> speech generator for soffice?

Sounds good.

> Pylinted and regression tested. Will, please review. Thanks!

So, I see two things when looking at these two lines (the first is the logic from the old code and the second is the new logic added to the speech generator):

-        if not len(utterances[0]) and self.speakBlankLine(newFocus):
+            if not len(result) and settings.speakBlankLines:

1) The old logic looks at the length of the very first string returned by the generator whereas the new logic just looks at the length of the utterances. I'm not sure if there was any significance to looking at just utterances[0] and not just len(utterances).

2) The old logic calls soffice's speakBlankLine method, which performs some extra logic to determine if the line is blank.  I dunno if this is still needed with the new generator or not.
Comment 5 Joanmarie Diggs (IRC: joanie) 2009-06-14 02:12:48 UTC
(In reply to comment #4)

> So, I see two things when looking at these two lines (the first is the logic
> from the old code and the second is the new logic added to the speech
> generator):
> 
> -        if not len(utterances[0]) and self.speakBlankLine(newFocus):
> +            if not len(result) and settings.speakBlankLines:
> 
> 1) The old logic looks at the length of the very first string returned by the
> generator whereas the new logic just looks at the length of the utterances. I'm
> not sure if there was any significance to looking at just utterances[0] and not
> just len(utterances).

Prior to the speechgenerator refactor, getSpeech would result in _getSpeechForTableCellRow being called which would in turn call _getSpeechForTableCell, which would eventually get around to doing this:

        displayedText = self._script.getDisplayedText( \
                          self._script.getRealActiveDescendant(obj))
        if not already_focused and not displayedText in utterances:
            utterances.append(displayedText)

getDisplayedText would return an empty string. Therefore, utterances wound up being [''].

Post speechgenerator refactor, we're getting a truly empty result/utterances under the same conditions -- or a result/utterances beginning with a pause. Hence the traceback.

> 2) The old logic calls soffice's speakBlankLine method, which performs some
> extra logic to determine if the line is blank.  I dunno if this is still needed
> with the new generator or not.

I don't believe it is needed. 

The old logic called speakBlankLines with newFocus (a paragraph within the cell) which would implement the accessible text interface). The new logic is in the speechgenerator which is looking at the cell itself, which does not implement the accessible text interface. So calling the soffice script's speakBlankLine would bail automatically unless we do additional work so that speakBlankLine can consider the child of cell which we care about:

    def speakBlankLine(self, obj):
        """Returns True if a blank line should be spoken.
        Otherwise, returns False.
        """

        # Get the the AccessibleText interface.
        try:
            text = obj.queryText()
        except NotImplementedError:
            return False

And if we did decide to do that work I don't see how things would be different. If len(result) == 0, it is because there is no text in the cell. Therefore, for the empty child paragraph, getTextAtOffset would return ('', 0, 0).

        # Get the line containing the caret
        caretOffset = text.caretOffset
        line = text.getTextAtOffset(caretOffset, \
            pyatspi.TEXT_BOUNDARY_LINE_START)

        # If this is a blank line, announce it if the user requested
        # that blank lines be spoken.
        if line[1] == 0 and line[2] == 0:
            return settings.speakBlankLines

which would cause speakBlankLine to return settings.speakBlankLines, which is what the new logic does.

Right??? <she says, popping more migraine meds and hoping she's not lost her mind> :-)
Comment 6 Willie Walker 2009-06-14 16:10:29 UTC
(In reply to comment #5)
> Right??? <she says, popping more migraine meds and hoping she's not lost her
> mind> :-)

Sounds right to me.  Many thanks for the analysis.  :-)
Comment 7 Joanmarie Diggs (IRC: joanie) 2009-06-14 16:53:42 UTC
(In reply to comment #6)
> (In reply to comment #5)
> > Right??? <she says, popping more migraine meds and hoping she's not lost her
> > mind> :-)
> 
> Sounds right to me.  Many thanks for the analysis.  :-)

Phew! :-) Thanks.

Patch committed to master. Closing as FIXED.