Skip to content

Commit 582cb55

Browse files
committed
Split speakObject to return a speech sequence
Must flatten the results from getTextInfoSpeech generator. Rename _speakPlaceholderIfEmpty -> _getPlaceholderSpeechIfTextEmpty
1 parent afe087c commit 582cb55

1 file changed

Lines changed: 64 additions & 25 deletions

File tree

‎source/speech/__init__.py‎

Lines changed: 64 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252

5353
from . import types
5454
from .types import SpeechSequence, SequenceItemT
55-
from typing import Optional, Dict, List, Any, Generator, Callable, Union
55+
from typing import Optional, Dict, List, Any, Generator, Union, Callable, Iterator, Tuple
5656
from logHandler import log
5757
import config
5858
import aria
@@ -421,31 +421,48 @@ def getObjectPropertiesSpeech( # noqa: C901
421421
return speechSequence
422422

423423

424-
def _speakPlaceholderIfEmpty(
425-
info: textInfos.TextInfo,
424+
def _getPlaceholderSpeechIfTextEmpty(
426425
obj,
427426
reason: str,
428-
priority: Optional[Spri] = None
429-
) -> bool:
430-
""" attempt to speak placeholder attribute if the textInfo 'info' is empty
431-
@return: True if info was considered empty, and we attempted to speak the placeholder value.
432-
False if info was not considered empty.
427+
) -> Tuple[bool, SpeechSequence]:
428+
""" Attempt to get speech for placeholder attribute if text for 'obj' is empty. Don't report the placeholder
429+
value unless the text is empty, because it is confusing to hear the current value (presumably typed by the
430+
user) *and* the placeholder. The placeholder should "disappear" once the user types a value.
431+
@return: (True, SpeechSequence) if text for obj was considered empty and we attempted to get speech for the
432+
placeholder value. (False, []) if text for obj was not considered empty.
433433
"""
434434
textEmpty = obj._isTextEmpty
435435
if textEmpty:
436-
speakObjectProperties(obj,reason=reason,placeholder=True,priority=priority)
437-
return True
438-
return False
436+
return True, getObjectPropertiesSpeech(obj, reason=reason, placeholder=True)
437+
return False, []
439438

440439

441-
# C901 'speakObject' is too complex
442-
# Note: when working on speakObject, look for opportunities to simplify
443-
# and move logic out into smaller helper functions.
444-
def speakObject( # noqa: C901
440+
def speakObject(
445441
obj,
446442
reason: str = controlTypes.REASON_QUERY,
447443
_prefixSpeechCommand: Optional[SpeechCommand] = None,
448444
priority: Optional[Spri] = None
445+
):
446+
sequence = getObjectSpeech(
447+
obj,
448+
reason,
449+
_prefixSpeechCommand,
450+
)
451+
if sequence:
452+
speak(sequence, priority=priority)
453+
454+
455+
def _flattenNestedSequences(nestedSequences: Iterator[SpeechSequence]) -> Iterator[SequenceItemT]:
456+
return [i for seq in nestedSequences for i in seq]
457+
458+
459+
# C901 'getObjectSpeech' is too complex
460+
# Note: when working on getObjectSpeech, look for opportunities to simplify
461+
# and move logic out into smaller helper functions.
462+
def getObjectSpeech( # noqa: C901
463+
obj,
464+
reason: str = controlTypes.REASON_QUERY,
465+
_prefixSpeechCommand: Optional[SpeechCommand] = None,
449466
):
450467
from NVDAObjects import NVDAObjectTextInfo
451468
role=obj.role
@@ -462,35 +479,57 @@ def speakObject( # noqa: C901
462479

463480
allowProperties = _objectSpeech_calculateAllowedProps(reason, shouldReportTextContent)
464481

465-
if reason==controlTypes.REASON_FOCUSENTERED:
482+
if reason == controlTypes.REASON_FOCUSENTERED:
466483
# Aside from excluding some properties, focus entered should be spoken like focus.
467-
reason=controlTypes.REASON_FOCUS
484+
reason = controlTypes.REASON_FOCUS
468485

469-
speakObjectProperties(obj, reason=reason, _prefixSpeechCommand=_prefixSpeechCommand, priority=priority, **allowProperties)
486+
sequence = getObjectPropertiesSpeech(
487+
obj,
488+
reason=reason,
489+
_prefixSpeechCommand=_prefixSpeechCommand,
490+
**allowProperties
491+
)
470492
if reason == controlTypes.REASON_ONLYCACHE:
471-
return
493+
return sequence
472494
if shouldReportTextContent:
473495
try:
474496
info = obj.makeTextInfo(textInfos.POSITION_SELECTION)
475497
if not info.isCollapsed:
476498
# if there is selected text, then there is a value and we do not report placeholder
477-
speakPreselectedText(info.text, priority=priority)
499+
sequence.extend(getPreselectedTextSpeech(info.text))
478500
else:
479501
info.expand(textInfos.UNIT_LINE)
480-
_speakPlaceholderIfEmpty(info, obj, reason,priority=priority)
481-
speakTextInfo(info,unit=textInfos.UNIT_LINE,reason=controlTypes.REASON_CARET,priority=priority)
502+
textEmpty, placeholderSeq = _getPlaceholderSpeechIfTextEmpty(obj, reason)
503+
sequence.extend(placeholderSeq)
504+
speechGen = getTextInfoSpeech(
505+
info,
506+
unit=textInfos.UNIT_LINE,
507+
reason=controlTypes.REASON_CARET
508+
)
509+
sequence.extend(_flattenNestedSequences(speechGen))
482510
except: # noqa E722 legacy bare except. Unknown what exceptions may be raised.
483511
newInfo = obj.makeTextInfo(textInfos.POSITION_ALL)
484-
if not _speakPlaceholderIfEmpty(newInfo, obj, reason,priority=priority):
485-
speakTextInfo(newInfo,unit=textInfos.UNIT_PARAGRAPH,reason=controlTypes.REASON_CARET,priority=priority)
512+
textEmpty, placeholderSeq = _getPlaceholderSpeechIfTextEmpty(obj, reason)
513+
if textEmpty:
514+
sequence.extend(placeholderSeq)
515+
else:
516+
speechGen = getTextInfoSpeech(
517+
newInfo,
518+
unit=textInfos.UNIT_PARAGRAPH,
519+
reason=controlTypes.REASON_CARET,
520+
)
521+
sequence.extend(_flattenNestedSequences(speechGen))
486522
elif role == controlTypes.ROLE_MATH:
487523
import mathPres
488524
mathPres.ensureInit()
489525
if mathPres.speechProvider:
490526
try:
491-
speak(mathPres.speechProvider.getSpeechForMathMl(obj.mathMl),priority=priority)
527+
sequence.extend(
528+
mathPres.speechProvider.getSpeechForMathMl(obj.mathMl)
529+
)
492530
except (NotImplementedError, LookupError):
493531
pass
532+
return sequence
494533

495534

496535
def _objectSpeech_calculateAllowedProps(reason, shouldReportTextContent):

0 commit comments

Comments
 (0)