diff --git a/source/appModules/kindle.py b/source/appModules/kindle.py index 8b0216f9d38..c0b6fa358a4 100644 --- a/source/appModules/kindle.py +++ b/source/appModules/kindle.py @@ -12,6 +12,7 @@ import api from scriptHandler import willSayAllResume, isScriptWaiting import controlTypes +from controlTypes import OutputReason import treeInterceptorHandler from cursorManager import ReviewCursorManager import browseMode @@ -277,7 +278,7 @@ def getFormatFieldSpeech( attrs: textInfos.Field, attrsCache: Optional[textInfos.Field] = None, formatConfig: Optional[Dict[str, bool]] = None, - reason: Optional[str] = None, + reason: Optional[OutputReason] = None, unit: Optional[str] = None, extraDetail: bool = False, initialFormat: bool = False diff --git a/source/browseMode.py b/source/browseMode.py index dc4b8a07186..c21c679d2ae 100644 --- a/source/browseMode.py +++ b/source/browseMode.py @@ -25,6 +25,7 @@ from scriptHandler import isScriptWaiting, willSayAllResume import aria import controlTypes +from controlTypes import OutputReason import config import textInfos import braille @@ -39,7 +40,7 @@ from abc import ABCMeta, abstractmethod from typing import Optional -REASON_QUICKNAV = "quickNav" +REASON_QUICKNAV = OutputReason.QUICKNAV def reportPassThrough(treeInterceptor,onlyIfChanged=True): """Reports the pass through mode if it has changed. @@ -304,7 +305,7 @@ def event_treeInterceptor_gainFocus(self): controlTypes.ROLE_CHECKMENUITEM, }) - def shouldPassThrough(self, obj, reason=None): + def shouldPassThrough(self, obj, reason: Optional[OutputReason] = None): """Determine whether pass through mode should be enabled (focus mode) or disabled (browse mode) for a given object. @param obj: The object in question. @type obj: L{NVDAObjects.NVDAObject} diff --git a/source/controlTypes.py b/source/controlTypes.py index aee9aaedae2..3e3366933e4 100644 --- a/source/controlTypes.py +++ b/source/controlTypes.py @@ -4,6 +4,7 @@ #See the file COPYING for more details. #Copyright (C) 2007-2016 NV Access Limited, Babbage B.V. from typing import Dict, Union, Set, Any, Optional, List +from enum import Enum, auto ROLE_UNKNOWN=0 ROLE_WINDOW=1 @@ -622,27 +623,44 @@ ROLE_APPLICATION, } -#{ Output reasons -# These constants are used to specify the reason that a given piece of output was generated. -#: An object to be reported due to a focus change or similar. -REASON_FOCUS="focus" -#: An ancestor of the focus object to be reported due to a focus change or similar. -REASON_FOCUSENTERED="focusEntered" -#: An item under the mouse. -REASON_MOUSE="mouse" -#: A response to a user query. -REASON_QUERY="query" -#: Reporting a change to an object. -REASON_CHANGE="change" -#: A generic, screen reader specific message. -REASON_MESSAGE="message" -#: Text reported as part of a say all. -REASON_SAYALL="sayAll" -#: Content reported due to caret movement or similar. -REASON_CARET="caret" -#: No output, but any state should be cached as if output had occurred. -REASON_ONLYCACHE="onlyCache" -#} + +class OutputReason(Enum): + """Specify the reason that a given piece of output was generated. + """ + #: An object to be reported due to a focus change or similar. + FOCUS = auto() + #: An ancestor of the focus object to be reported due to a focus change or similar. + FOCUSENTERED = auto() + #: An item under the mouse. + MOUSE = auto() + #: A response to a user query. + QUERY = auto() + #: Reporting a change to an object. + CHANGE = auto() + #: A generic, screen reader specific message. + MESSAGE = auto() + #: Text reported as part of a say all. + SAYALL = auto() + #: Content reported due to caret movement or similar. + CARET = auto() + #: No output, but any state should be cached as if output had occurred. + ONLYCACHE = auto() + + QUICKNAV = auto() + +# The following constants are kept for backwards compatibility. +# In future, OutputReason should be used directly + + +REASON_FOCUS = OutputReason.FOCUS +REASON_FOCUSENTERED = OutputReason.FOCUSENTERED +REASON_MOUSE = OutputReason.MOUSE +REASON_QUERY = OutputReason.QUERY +REASON_CHANGE = OutputReason.CHANGE +REASON_MESSAGE = OutputReason.MESSAGE +REASON_SAYALL = OutputReason.SAYALL +REASON_CARET = OutputReason.CARET +REASON_ONLYCACHE = OutputReason.ONLYCACHE #: Text to use for 'current' values. These describe if an item is the current item #: within a particular kind of selection. @@ -661,7 +679,8 @@ "time":_("current time"), } -def processPositiveStates(role, states, reason, positiveStates=None): + +def processPositiveStates(role, states, reason: OutputReason, positiveStates=None): """Processes the states for an object and returns the positive states to output for a specified reason. For example, if C{STATE_CHECKED} is in the returned states, it means that the processed object is checked. @param role: The role of the object to process states for (e.g. C{ROLE_CHECKBOX}. @@ -669,7 +688,6 @@ def processPositiveStates(role, states, reason, positiveStates=None): @param states: The raw states for an object to process. @type states: set @param reason: The reason to process the states (e.g. C{REASON_FOCUS}. - @type reason: str @param positiveStates: Used for C{REASON_CHANGE}, specifies states changed from negative to positive; @type positiveStates: set @return: The processed positive states. @@ -719,7 +737,8 @@ def processPositiveStates(role, states, reason, positiveStates=None): positiveStates.discard(STATE_EDITABLE) return positiveStates -def processNegativeStates(role, states, reason, negativeStates=None): + +def processNegativeStates(role, states, reason: OutputReason, negativeStates=None): """Processes the states for an object and returns the negative states to output for a specified reason. For example, if C{STATE_CHECKED} is in the returned states, it means that the processed object is not checked. @param role: The role of the object to process states for (e.g. C{ROLE_CHECKBOX}. @@ -727,7 +746,6 @@ def processNegativeStates(role, states, reason, negativeStates=None): @param states: The raw states for an object to process. @type states: set @param reason: The reason to process the states (e.g. C{REASON_FOCUS}. - @type reason: str @param negativeStates: Used for C{REASON_CHANGE}, specifies states changed from positive to negative; @type negativeStates: set @return: The processed negative states. @@ -787,7 +805,7 @@ def processNegativeStates(role, states, reason, negativeStates=None): def processAndLabelStates( role: int, states: Set[Any], - reason: str, + reason: OutputReason, positiveStates: Optional[Set[Any]] = None, negativeStates: Optional[Set[Any]] = None, positiveStateLabelDict: Dict[int, str] = {}, diff --git a/source/speech/__init__.py b/source/speech/__init__.py index a08e5b0360e..f0878ce2f71 100755 --- a/source/speech/__init__.py +++ b/source/speech/__init__.py @@ -14,6 +14,7 @@ import colors import api import controlTypes +from controlTypes import OutputReason import tones import synthDriverHandler from synthDriverHandler import getSynth, setSynth @@ -302,7 +303,7 @@ def getCharDescListFromText(text,locale): def speakObjectProperties( # noqa: C901 obj, - reason: str = controlTypes.REASON_QUERY, + reason: OutputReason = controlTypes.REASON_QUERY, _prefixSpeechCommand: Optional[SpeechCommand] = None, priority: Optional[Spri] = None, **allowedProperties @@ -322,7 +323,7 @@ def speakObjectProperties( # noqa: C901 # and move logic out into smaller helper functions. def getObjectPropertiesSpeech( # noqa: C901 obj, - reason: str = controlTypes.REASON_QUERY, + reason: OutputReason = controlTypes.REASON_QUERY, _prefixSpeechCommand: Optional[SpeechCommand] = None, **allowedProperties ) -> SpeechSequence: @@ -423,7 +424,7 @@ def getObjectPropertiesSpeech( # noqa: C901 def _getPlaceholderSpeechIfTextEmpty( obj, - reason: str, + reason: OutputReason, ) -> Tuple[bool, SpeechSequence]: """ Attempt to get speech for placeholder attribute if text for 'obj' is empty. Don't report the placeholder value unless the text is empty, because it is confusing to hear the current value (presumably typed by the @@ -439,7 +440,7 @@ def _getPlaceholderSpeechIfTextEmpty( def speakObject( obj, - reason: str = controlTypes.REASON_QUERY, + reason: OutputReason = controlTypes.REASON_QUERY, _prefixSpeechCommand: Optional[SpeechCommand] = None, priority: Optional[Spri] = None ): @@ -461,7 +462,7 @@ def _flattenNestedSequences(nestedSequences: Iterator[SpeechSequence]) -> Iterat # and move logic out into smaller helper functions. def getObjectSpeech( # noqa: C901 obj, - reason: str = controlTypes.REASON_QUERY, + reason: OutputReason = controlTypes.REASON_QUERY, _prefixSpeechCommand: Optional[SpeechCommand] = None, ): from NVDAObjects import NVDAObjectTextInfo @@ -598,7 +599,7 @@ def _objectSpeech_calculateAllowedProps(reason, shouldReportTextContent): def speakText( text: str, - reason: str = controlTypes.REASON_MESSAGE, + reason: OutputReason = controlTypes.REASON_MESSAGE, symbolLevel: Optional[int] = None, priority: Optional[Spri] = None ): @@ -1044,7 +1045,7 @@ def speakTextInfo( useCache: Union[bool, SpeakTextInfoState] = True, formatConfig: Dict[str, bool] = None, unit: Optional[str] = None, - reason: str = controlTypes.REASON_QUERY, + reason: OutputReason = controlTypes.REASON_QUERY, _prefixSpeechCommand: Optional[SpeechCommand] = None, onlyInitialFields: bool = False, suppressBlanks: bool = False, @@ -1074,7 +1075,7 @@ def getTextInfoSpeech( # noqa: C901 useCache: Union[bool, SpeakTextInfoState] = True, formatConfig: Dict[str, bool] = None, unit: Optional[str] = None, - reason: str = controlTypes.REASON_QUERY, + reason: OutputReason = controlTypes.REASON_QUERY, _prefixSpeechCommand: Optional[SpeechCommand] = None, onlyInitialFields: bool = False, suppressBlanks: bool = False @@ -1444,7 +1445,7 @@ def isControlEndFieldCommand(x): # Note: when working on getPropertiesSpeech, look for opportunities to simplify # and move logic out into smaller helper functions. def getPropertiesSpeech( # noqa: C901 - reason: str = controlTypes.REASON_QUERY, + reason: OutputReason = controlTypes.REASON_QUERY, **propertyValues ) -> SpeechSequence: global oldTreeLevel, oldTableID, oldRowNumber, oldRowSpan, oldColumnNumber, oldColumnSpan @@ -1629,7 +1630,7 @@ def getControlFieldSpeech( # noqa: C901 fieldType: str, formatConfig: Optional[Dict[str, bool]] = None, extraDetail: bool = False, - reason: Optional[str] = None + reason: Optional[OutputReason] = None ) -> SpeechSequence: if attrs.get('isHidden'): return [] @@ -1894,7 +1895,7 @@ def getFormatFieldSpeech( # noqa: C901 attrs: textInfos.Field, attrsCache: Optional[textInfos.Field] = None, formatConfig: Optional[Dict[str, bool]] = None, - reason: Optional[str] = None, + reason: Optional[OutputReason] = None, unit: Optional[str] = None, extraDetail: bool = False, initialFormat: bool = False, diff --git a/source/textInfos/__init__.py b/source/textInfos/__init__.py index 27bd3f061fc..668bd4a6115 100755 --- a/source/textInfos/__init__.py +++ b/source/textInfos/__init__.py @@ -17,6 +17,7 @@ import baseObject import config import controlTypes +from controlTypes import OutputReason import locationHelper @@ -521,7 +522,7 @@ def getControlFieldSpeech( fieldType: str, formatConfig: Optional[Dict[str, bool]] = None, extraDetail: bool = False, - reason: Optional[str] = None + reason: Optional[OutputReason] = None ) -> SpeechSequence: # Import late to avoid circular import. import speech @@ -541,7 +542,7 @@ def getFormatFieldSpeech( attrs: Field, attrsCache: Optional[Field] = None, formatConfig: Optional[Dict[str, bool]] = None, - reason: Optional[str] = None, + reason: Optional[OutputReason] = None, unit: Optional[str] = None, extraDetail: bool = False, initialFormat: bool = False, diff --git a/source/treeInterceptorHandler.py b/source/treeInterceptorHandler.py index 2752943a9a1..eba67fb80ce 100644 --- a/source/treeInterceptorHandler.py +++ b/source/treeInterceptorHandler.py @@ -15,6 +15,7 @@ import braille import vision from speech.types import SpeechSequence +from controlTypes import OutputReason runningTable=set() @@ -246,7 +247,7 @@ def getFormatFieldSpeech( attrs: textInfos.Field, attrsCache: Optional[textInfos.Field] = None, formatConfig: Optional[Dict[str, bool]] = None, - reason: Optional[str] = None, + reason: Optional[OutputReason] = None, unit: Optional[str] = None, extraDetail: bool = False, initialFormat: bool = False,