Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions source/IAccessibleHandler/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@

import re
import struct
from typing import Optional, Tuple
from typing import (
Optional,
Tuple,
Dict,
Union,
)
import weakref
from ctypes import (
wintypes,
Expand Down Expand Up @@ -1114,15 +1119,15 @@ def getRecursiveTextFromIAccessibleTextObject(obj, startOffset=0, endOffset=-1):


# C901: splitIA2Attribs is too complex
def splitIA2Attribs(attribsString): # noqa: C901
def splitIA2Attribs( # noqa: C901
attribsString: str
) -> Dict[str, Union[str, Dict]]:
"""Split an IAccessible2 attributes string into a dict of attribute keys and values.
An invalid attributes string does not cause an error, but strange results may be returned.
Subattributes are handled. Subattribute keys and values are placed into a dict which becomes the value
of the attribute.
@param attribsString: The IAccessible2 attributes string to convert.
@type attribsString: str
@return: A dict of the attribute keys and values, where values are strings or dicts.
@rtype: {str: str or {str: str}}
"""
# Do not treat huge base64 data as it might freeze NVDA in Google Chrome (#10227)
if len(attribsString) >= ATTRIBS_STRING_BASE64_THRESHOLD:
Expand Down
26 changes: 21 additions & 5 deletions source/NVDAObjects/IAccessible/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1101,7 +1101,10 @@ def getChild(self, index):
event_windowHandle=self.event_windowHandle, event_objectID=self.event_objectID, event_childID=child[1])
return self.correctAPIForRelation(IAccessible(IAccessibleObject=child[0], IAccessibleChildID=child[1]))

def _get_IA2Attributes(self):
#: Type definition for auto prop '_get_IA2Attributes'
IA2Attributes: typing.Dict[str, str]

def _get_IA2Attributes(self) -> typing.Dict[str, str]:
if not isinstance(self.IAccessibleObject, IA2.IAccessible2):
return {}
try:
Expand Down Expand Up @@ -1442,7 +1445,10 @@ def _get_indexInParent(self):
pass
raise NotImplementedError

def _get__IA2Relations(self):
#: Type definition for auto prop '_get__IA2Relations'
_IA2Relations: typing.List[IA2.IAccessibleRelation]

def _get__IA2Relations(self) -> typing.List[IA2.IAccessibleRelation]:
if not isinstance(self.IAccessibleObject, IA2.IAccessible2):
raise NotImplementedError
import ctypes
Expand All @@ -1452,7 +1458,7 @@ def _get__IA2Relations(self):
except COMError:
raise NotImplementedError
if size <= 0:
return ()
return list()
relations = (ctypes.POINTER(IA2.IAccessibleRelation) * size)()
count = ctypes.c_int()
# The client allocated relations array is an [out] parameter instead of [in, out], so we need to use the raw COM method.
Expand All @@ -1461,11 +1467,21 @@ def _get__IA2Relations(self):
raise NotImplementedError
return list(relations)

def _getIA2RelationFirstTarget(self, relationType):
def _getIA2RelationFirstTarget(
self,
relationType: str
) -> typing.Optional["IAccessible"]:
""" Get the first target for the relation of type.
@param relationType: A IAccessibleHandler.IA2_RELATION_* constant.
"""

for relation in self._IA2Relations:
try:
if relation.relationType == relationType:
return IAccessible(IAccessibleObject=IAccessibleHandler.normalizeIAccessible(relation.target(0)), IAccessibleChildID=0)
return IAccessible(
IAccessibleObject=IAccessibleHandler.normalizeIAccessible(relation.target(0)),
IAccessibleChildID=0
)
except COMError:
pass
return None
Expand Down
16 changes: 15 additions & 1 deletion source/NVDAObjects/IAccessible/sysListView32.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,24 @@ class LVCOLUMN64(Structure):
('cxIdeal',c_int),
]


class AutoFreeBSTR(BSTR):
"""A BSTR that *always* frees itself on deletion."""
"""A BSTR that *always* frees itself on deletion.
A BSTR (Basic string or binary string) is a string data type that is used by COM,
Automation, and Interop functions.

AutoFreeBSTR is useful where another library allocates (SysAllocString/SysAllocStringLen)
and you want to ensure that it will be deallocated (SysFreeString).
@note The conditions requiring the use of this class are not clear.
The current usage is considered legacy.
@note The BSTR (base class) from comtypes will free the string when it
is from an outparam (indicating that memory was allocated in the library).
@warning Don't use this unless you are certain about taking ownership of the memory.
@warning Deprecated, may be removed in future versions.
"""
_needsfree=True


class List(List):

def getListGroupInfo(self,groupIndex):
Expand Down
9 changes: 6 additions & 3 deletions source/NVDAObjects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,11 +372,14 @@ def _get_treeInterceptorClass(self):
#: @type: bool
shouldCreateTreeInterceptor = True

def _get_treeInterceptor(self):
#: Type definition for auto prop '_get_treeInterceptor'
treeInterceptor: treeInterceptorHandler.TreeInterceptor

def _get_treeInterceptor(self) -> treeInterceptorHandler.TreeInterceptor:
"""Retrieves the treeInterceptor associated with this object.
If a treeInterceptor has not been specifically set, the L{treeInterceptorHandler} is asked if it can find a treeInterceptor containing this object.
If a treeInterceptor has not been specifically set,
the L{treeInterceptorHandler} is asked if it can find a treeInterceptor containing this object.
@return: the treeInterceptor
@rtype: L{treeInterceptorHandler.TreeInterceptor}
"""
if hasattr(self,'_treeInterceptor'):
ti=self._treeInterceptor
Expand Down
6 changes: 4 additions & 2 deletions source/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,10 @@ def setDesktopObject(obj):
"""Tells NVDA to remember the given object as the desktop object"""
globalVars.desktopObject=obj

def getReviewPosition():
"""Retreaves the current TextInfo instance representing the user's review position. If it is not set, it uses the user's set navigator object and creates a TextInfo from that.

def getReviewPosition() -> textInfos.TextInfo:
"""Retrieves the current TextInfo instance representing the user's review position.
If it is not set, it uses navigator object to create a TextInfo.
"""
if globalVars.reviewPosition:
return globalVars.reviewPosition
Expand Down
4 changes: 2 additions & 2 deletions source/documentBase.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ class TextContainerObject(AutoPropertyObject):

def _get_TextInfo(self):
raise NotImplementedError
def makeTextInfo(self,position):

def makeTextInfo(self, position) -> textInfos.TextInfo:
return self.TextInfo(self,position)

def _get_selection(self):
Expand Down
8 changes: 6 additions & 2 deletions source/textInfos/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -506,8 +506,12 @@ def find(self,text,caseSensitive=False,reverse=False):
"""
raise NotImplementedError

def _get_NVDAObjectAtStart(self):
"""retreaves the NVDAObject related to the start of the range. Usually it is just the owner NVDAObject, but in the case of virtualBuffers it may be a descendant object.
#: Typing information for auto-property: _get_NVDAObjectAtStart
NVDAObjectAtStart: "NVDAObjects.NVDAObject"

def _get_NVDAObjectAtStart(self) -> "NVDAObjects.NVDAObject":
"""Get the NVDAObject related to the start of the range.
Usually it is just the owner NVDAObject, but in the case of virtualBuffers it may be a descendant object.
@returns: the NVDAObject at the start
"""
return self.obj
Expand Down