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
11 changes: 4 additions & 7 deletions source/baseObject.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,8 @@ class AutoPropertyObject(object, metaclass=AutoPropertyType):
"""

#: Tracks the instances of this class; used by L{invalidateCaches}.
#: @type: weakref.WeakValueDictionary
# We really just want to store the instances as a set of weak references,
# but as there is no easy way to have NVDAObjects and TextInfos remain hashable in Python3, as they override equality,
# We store them on a WeakValueDictionary, keyed by their id (address).
__instances=weakref.WeakValueDictionary()
#: @type: weakref.WeakKeyDictionary
__instances=weakref.WeakKeyDictionary()
#: Specifies whether properties are cached by default;
#: can be overridden for individual properties by setting _cache_propertyName.
#: @type: bool
Expand All @@ -137,7 +134,7 @@ def __new__(cls, *args, **kwargs):
#: Maps properties to cached values.
#: @type: dict
self._propertyCache={}
self.__instances[id(self)]=self
self.__instances[self]=None
return self

def _getPropertyViaCache(self,getterMethod=None):
Expand All @@ -160,7 +157,7 @@ def invalidateCaches(cls):
# We use keys() here instead of iterkeys(), as invalidating the cache on an object may cause instances to disappear,
# which would in turn cause an exception due to the dictionary changing size during iteration.
# #9067 (Py3 review required): because of this, wrap this in a list, as dict.keys() in Python 3 returns iterators.
for instance in list(cls.__instances.values()):
for instance in list(cls.__instances.keys()):
instance.invalidateCache()

class ScriptableType(AutoPropertyType):
Expand Down
26 changes: 12 additions & 14 deletions source/eventHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@

#Some dicts to store event counts by name and or obj
_pendingEventCountsByName={}
# Note that due to the fact it is hard to keep NVDAObjects remaining hashable in Python3 due to their equality method being overridden,
# the id (address) of the NVDAObject will be used as the key in the dict, not the NVDAObject itself.
_pendingEventCountsByObjID={}
_pendingEventCountsByNameAndObjID={}
_pendingEventCountsByObj={}
_pendingEventCountsByNameAndObj={}
# Needed to ensure updates are atomic, as these might be updated from multiple threads simultaneously.
_pendingEventCountsLock=threading.RLock()

Expand All @@ -40,8 +38,8 @@ def queueEvent(eventName,obj,**kwargs):
lastQueuedFocusObject=obj
with _pendingEventCountsLock:
_pendingEventCountsByName[eventName]=_pendingEventCountsByName.get(eventName,0)+1
_pendingEventCountsByObjID[id(obj)]=_pendingEventCountsByObjID.get(id(obj),0)+1
_pendingEventCountsByNameAndObjID[(eventName,id(obj))]=_pendingEventCountsByNameAndObjID.get((eventName,id(obj)),0)+1
_pendingEventCountsByObj[obj]=_pendingEventCountsByObj.get(obj,0)+1
_pendingEventCountsByNameAndObj[(eventName,obj)]=_pendingEventCountsByNameAndObj.get((eventName,obj),0)+1
queueHandler.queueFunction(queueHandler.eventQueue,_queueEventCallback,eventName,obj,kwargs)

def _queueEventCallback(eventName,obj,kwargs):
Expand All @@ -51,16 +49,16 @@ def _queueEventCallback(eventName,obj,kwargs):
_pendingEventCountsByName[eventName]=(curCount-1)
elif curCount==1:
del _pendingEventCountsByName[eventName]
curCount=_pendingEventCountsByObjID.get(id(obj),0)
curCount=_pendingEventCountsByObj.get(obj,0)
if curCount>1:
_pendingEventCountsByObjID[id(obj)]=(curCount-1)
_pendingEventCountsByObj[obj]=(curCount-1)
elif curCount==1:
del _pendingEventCountsByObjID[id(obj)]
curCount=_pendingEventCountsByNameAndObjID.get((eventName,id(obj)),0)
del _pendingEventCountsByObj[obj]
curCount=_pendingEventCountsByNameAndObj.get((eventName,obj),0)
if curCount>1:
_pendingEventCountsByNameAndObjID[(eventName,id(obj))]=(curCount-1)
_pendingEventCountsByNameAndObj[(eventName,obj)]=(curCount-1)
elif curCount==1:
del _pendingEventCountsByNameAndObjID[(eventName,id(obj))]
del _pendingEventCountsByNameAndObj[(eventName,obj)]
executeEvent(eventName,obj,**kwargs)

def isPendingEvents(eventName=None,obj=None):
Expand All @@ -75,11 +73,11 @@ def isPendingEvents(eventName=None,obj=None):
if not eventName and not obj:
return bool(len(_pendingEventCountsByName))
elif not eventName and obj:
return id(obj) in _pendingEventCountsByObjID
return obj in _pendingEventCountsByObj
elif eventName and not obj:
return eventName in _pendingEventCountsByName
elif eventName and obj:
return (eventName,id(obj)) in _pendingEventCountsByNameAndObjID
return (eventName,obj) in _pendingEventCountsByNameAndObj

class _EventExecuter(object):
"""Facilitates execution of a chain of event functions.
Expand Down