1
2
3
4
5
6
7 """Module that contains the base NVDA object type"""
8 from new import instancemethod
9 import time
10 import re
11 import weakref
12 from logHandler import log
13 import eventHandler
14 from displayModel import DisplayModelTextInfo
15 import baseObject
16 import speech
17 import api
18 import textInfos.offsets
19 import config
20 import controlTypes
21 import appModuleHandler
22 import treeInterceptorHandler
23 import braille
24 import globalPluginHandler
25
26 -class NVDAObjectTextInfo(textInfos.offsets.OffsetsTextInfo):
27 """A default TextInfo which is used to enable text review of information about widgets that don't support text content.
28 The L{NVDAObject.basicText} attribute is used as the text to expose.
29 """
30
33
34 - def _getStoryText(self):
35 return self.obj.basicText
36
38 return len(self._getStoryText())
39
41 text=self._getStoryText()
42 return text[start:end]
43
45 """Raised by NVDAObjects during construction to inform that this object is invalid.
46 In this case, for the purposes of NVDA, the object should be considered non-existent.
47 Therefore, L{DynamicNVDAObjectType} will return C{None} if this exception is raised.
48 """
49
51 _dynamicClassCache={}
52
53 - def __call__(self,chooseBestAPI=True,**kwargs):
54 if chooseBestAPI:
55 APIClass=self.findBestAPIClass(kwargs)
56 if not APIClass: return None
57 else:
58 APIClass=self
59
60
61 try:
62 obj=APIClass.__new__(APIClass,**kwargs)
63 obj.APIClass=APIClass
64 if isinstance(obj,self):
65 obj.__init__(**kwargs)
66 except InvalidNVDAObject, e:
67 log.debugWarning("Invalid NVDAObject: %s" % e, stack_info=True)
68 return None
69
70 clsList = []
71 if "findOverlayClasses" in APIClass.__dict__:
72 obj.findOverlayClasses(clsList)
73 else:
74 clsList.append(APIClass)
75
76 appModule=obj.appModule
77 if appModule and "chooseNVDAObjectOverlayClasses" in appModule.__class__.__dict__:
78 appModule.chooseNVDAObjectOverlayClasses(obj, clsList)
79
80 for plugin in globalPluginHandler.runningPlugins:
81 if "chooseNVDAObjectOverlayClasses" in plugin.__class__.__dict__:
82 plugin.chooseNVDAObjectOverlayClasses(obj, clsList)
83
84
85 bases=[]
86 for index in xrange(len(clsList)):
87
88 if index==0 or not issubclass(clsList[index-1],clsList[index]):
89 bases.append(clsList[index])
90
91
92 if len(bases) == 1:
93
94 newCls=bases[0]
95 else:
96 bases=tuple(bases)
97 newCls=self._dynamicClassCache.get(bases,None)
98 if not newCls:
99 name="Dynamic_%s"%"".join([x.__name__ for x in clsList])
100 newCls=type(name,bases,{})
101 self._dynamicClassCache[bases]=newCls
102
103 oldMro=frozenset(obj.__class__.__mro__)
104
105 obj.__class__=newCls
106
107
108 for cls in reversed(newCls.__mro__):
109 if cls in oldMro:
110
111 continue
112 initFunc=cls.__dict__.get("initOverlayClass")
113 if initFunc:
114 initFunc(obj)
115
116 try:
117 obj.bindGestures(getattr(cls, "_%s__gestures" % cls.__name__))
118 except AttributeError:
119 pass
120
121
122 if appModule and hasattr(appModule,"event_NVDAObject_init"):
123 appModule.event_NVDAObject_init(obj)
124
125 return obj
126
127 @classmethod
129 """Clear the dynamic class cache.
130 This should be called when a plugin is unloaded so that any used overlay classes in the unloaded plugin can be garbage collected.
131 """
132 cls._dynamicClassCache.clear()
133
135 """NVDA's representation of a single control/widget.
136 Every widget, regardless of how it is exposed by an application or the operating system, is represented by a single NVDAObject instance.
137 This allows NVDA to work with all widgets in a uniform way.
138 An NVDAObject provides information about the widget (e.g. its name, role and value),
139 as well as functionality to manipulate it (e.g. perform an action or set focus).
140 Events for the widget are handled by special event methods on the object.
141 Commands triggered by input from the user can also be handled by special methods called scripts.
142 See L{ScriptableObject} for more details.
143
144 The only attribute that absolutely must be provided is L{processID}.
145 However, subclasses should provide at least the L{name} and L{role} attributes in order for the object to be meaningful to the user.
146 Attributes such as L{parent}, L{firstChild}, L{next} and L{previous} link an instance to other NVDAObjects in the hierarchy.
147 In order to facilitate access to text exposed by a widget which supports text content (e.g. an editable text control),
148 a L{textInfos.TextInfo} should be implemented and the L{TextInfo} attribute should specify this class.
149
150 There are two main types of NVDAObject classes:
151 * API classes, which provide the core functionality to work with objects exposed using a particular API (e.g. MSAA/IAccessible).
152 * Overlay classes, which supplement the core functionality provided by an API class to handle a specific widget or type of widget.
153 Most developers need only be concerned with overlay classes.
154 The overlay classes to be used for an instance are determined using the L{findOverlayClasses} method on the API class.
155 An L{AppModule} can also choose overlay classes for an instance using the L{AppModule.chooseNVDAObjectOverlayClasses} method.
156 """
157
158 __metaclass__=DynamicNVDAObjectType
159 cachePropertiesByDefault = True
160
161
162
163 TextInfo=NVDAObjectTextInfo
164
165 @classmethod
167 """
168 Finds out the highest-level APIClass this object can get to given these kwargs, and updates the kwargs and returns the APIClass.
169 @param relation: the relationship of a possible new object of this type to another object creating it (e.g. parent).
170 @param type: string
171 @param kwargs: the arguments necessary to construct an object of the class this method was called on.
172 @type kwargs: dictionary
173 @returns: the new APIClass
174 @rtype: DynamicNVDAObjectType
175 """
176 newAPIClass=cls
177 if 'getPossibleAPIClasses' in newAPIClass.__dict__:
178 for possibleAPIClass in newAPIClass.getPossibleAPIClasses(kwargs,relation=relation):
179 if 'kwargsFromSuper' not in possibleAPIClass.__dict__:
180 log.error("possible API class %s does not implement kwargsFromSuper"%possibleAPIClass)
181 continue
182 if possibleAPIClass.kwargsFromSuper(kwargs,relation=relation):
183 return possibleAPIClass.findBestAPIClass(kwargs,relation=relation)
184 return newAPIClass if newAPIClass is not NVDAObject else None
185
186
187 @classmethod
189 """
190 Provides a generator which can generate all the possible API classes (in priority order) that inherit directly from the class it was called on.
191 @param relation: the relationship of a possible new object of this type to another object creating it (e.g. parent).
192 @param type: string
193 @param kwargs: the arguments necessary to construct an object of the class this method was called on.
194 @type kwargs: dictionary
195 @returns: a generator
196 @rtype: generator
197 """
198 import NVDAObjects.window
199 yield NVDAObjects.window.Window
200
201 @classmethod
203 """
204 Finds out if this class can be instanciated from the given super kwargs.
205 If so it updates the kwargs to contain everything it will need to instanciate this class, and returns True.
206 If this class can not be instanciated, it returns False and kwargs is not touched.
207 @param relation: why is this class being instanciated? parent, focus, foreground etc...
208 @type relation: string
209 @param kwargs: the kwargs for constructing this class's super class.
210 @type kwargs: dict
211 @rtype: boolean
212 """
213 raise NotImplementedError
214
215
217 """Chooses overlay classes which should be added to this object's class structure after the object has been initially instantiated.
218 After an NVDAObject class (normally an API-level class) is instantiated, this method is called on the instance to choose appropriate overlay classes.
219 This method may use properties, etc. on the instance to make this choice.
220 The object's class structure is then mutated to contain these classes.
221 L{initOverlayClass} is then called for each class which was not part of the initially instantiated object.
222 This process allows an NVDAObject to be dynamically created using the most appropriate NVDAObject subclass at each API level.
223 Classes should be listed with subclasses first. That is, subclasses should generally call super and then append their own classes to the list.
224 For example: Called on an IAccessible NVDAObjectThe list might contain DialogIaccessible (a subclass of IAccessible), Edit (a subclass of Window).
225 @param clsList: The list of classes, which will be modified by this method if appropriate.
226 @type clsList: list of L{NVDAObject}
227 """
228 clsList.append(NVDAObject)
229
230 beTransparentToMouse=False
231
232 @staticmethod
234 """Retreaves an NVDAObject instance representing a control in the Operating System at the given x and y coordinates.
235 @param x: the x coordinate.
236 @type x: int
237 @param y: the y coordinate.
238 @param y: int
239 @return: The object at the given x and y coordinates.
240 @rtype: L{NVDAObject}
241 """
242 kwargs={}
243 APIClass=NVDAObject.findBestAPIClass(kwargs,relation=(x,y))
244 return APIClass(chooseBestAPI=False,**kwargs) if APIClass else None
245
246 @staticmethod
248 """Retreaves the object representing the control currently with focus in the Operating System. This differens from NVDA's focus object as this focus object is the real focus object according to the Operating System, not according to NVDA.
249 @return: the object with focus.
250 @rtype: L{NVDAObject}
251 """
252 kwargs={}
253 APIClass=NVDAObject.findBestAPIClass(kwargs,relation="focus")
254 return APIClass(chooseBestAPI=False,**kwargs) if APIClass else None
255
256 @staticmethod
258 """Retreaves the object representing the current foreground control according to the Operating System. This differes from NVDA's foreground object as this object is the real foreground object according to the Operating System, not according to NVDA.
259 @return: the foreground object
260 @rtype: L{NVDAObject}
261 """
262 kwargs={}
263 APIClass=NVDAObject.findBestAPIClass(kwargs,relation="foreground")
264 return APIClass(chooseBestAPI=False,**kwargs) if APIClass else None
265
266
268 super(NVDAObject,self).__init__()
269 self._mouseEntered=False
270 self.textRepresentationLineLength=None
271
273 """Calculates if this object is equal to another object. Used by L{NVDAObject.__eq__}.
274 @param other: the other object to compare with.
275 @type other: L{NVDAObject}
276 @return: True if equal, false otherwise.
277 @rtype: boolean
278 """
279 return True
280
282 """Compaires the objects' memory addresses, their type, and uses L{NVDAObject._isEqual} to see if they are equal.
283 """
284 if self is other:
285 return True
286 if type(self) is not type(other):
287 return False
288 return self._isEqual(other)
289
291 """The opposite to L{NVDAObject.__eq__}
292 """
293 return not self.__eq__(other)
294
296 """
297 If this NVDAObject should use a treeInterceptor, then this property provides the L{treeInterceptorHandler.TreeInterceptor} class it should use.
298 If not then it should be not implemented.
299 """
300 raise NotImplementedError
301
303 """Retreaves the treeInterceptor associated with this object.
304 If a treeInterceptor has not been specifically set, the L{treeInterceptorHandler} is asked if it can find a treeInterceptor containing this object.
305 @return: the treeInterceptor
306 @rtype: L{treeInterceptorHandler.TreeInterceptor}
307 """
308 if hasattr(self,'_treeInterceptor'):
309 ti=self._treeInterceptor
310 if isinstance(ti,weakref.ref):
311 ti=ti()
312 if ti and ti in treeInterceptorHandler.runningTable:
313 return ti
314 else:
315 self._treeInterceptor=None
316 return None
317 else:
318 ti=treeInterceptorHandler.getTreeInterceptor(self)
319 if ti:
320 self._treeInterceptor=weakref.ref(ti)
321 return ti
322
324 """Specifically sets a treeInterceptor to be associated with this object.
325 """
326 if obj:
327 self._treeInterceptor=weakref.ref(obj)
328 else:
329 self._treeInterceptor=None
330
332 """Retreaves the appModule representing the application this object is a part of by asking L{appModuleHandler}.
333 @return: the appModule
334 @rtype: L{appModuleHandler.AppModule}
335 """
336 if not hasattr(self,'_appModuleRef'):
337 a=appModuleHandler.getAppModuleForNVDAObject(self)
338 if a:
339 self._appModuleRef=weakref.ref(a)
340 return a
341 else:
342 return self._appModuleRef()
343
345 """The name or label of this object (example: the text of a button).
346 @rtype: basestring
347 """
348 return ""
349
351 """The role or type of control this object represents (example: button, list, dialog).
352 @return: a ROLE_* constant from L{controlTypes}
353 @rtype: int
354 """
355 return controlTypes.ROLE_UNKNOWN
356
358 """The value of this object (example: the current percentage of a scrollbar, the selected option in a combo box).
359 @rtype: basestring
360 """
361 return ""
362
364 """The description or help text of this object.
365 @rtype: basestring
366 """
367 return ""
368
370 """Retreaves the number of actions supported by this object."""
371 return 0
372
374 """Retreaves the name of an action supported by this object.
375 If index is not given then the default action will be used if it exists.
376 @param index: the optional 0-based index of the wanted action.
377 @type index: int
378 @return: the action's name
379 @rtype: basestring
380 """
381 raise NotImplementedError
382
384 """Performs an action supported by this object.
385 If index is not given then the default action will be used if it exists.
386 """
387 raise NotImplementedError
388
390 """Retreaves the index of the action that is the default."""
391 return 0
392
394 """The shortcut key that activates this object(example: alt+t).
395 @rtype: basestring
396 """
397 return ""
398
400 """
401 Finds out if this object is currently within the foreground.
402 """
403 raise NotImplementedError
404
406 """Retreaves the current states of this object (example: selected, focused).
407 @return: a set of STATE_* constants from L{controlTypes}.
408 @rtype: set of int
409 """
410 return set()
411
413 """The location of this object on the screen.
414 @return: left, top, width and height of the object.
415 @rtype: tuple of int
416 """
417 raise NotImplementedError
418
420 """Retreaves this object's parent (the object that contains this object).
421 @return: the parent object if it exists else None.
422 @rtype: L{NVDAObject} or None
423 """
424 return None
425
427 """
428 Exactly like parent, however another object at this same sibling level may be retreaved first (e.g. a groupbox). Mostly used when presenting context such as focus ancestry.
429 """
430 return self.parent
431
433 """Retreaves the object directly after this object with the same parent.
434 @return: the next object if it exists else None.
435 @rtype: L{NVDAObject} or None
436 """
437 return None
438
440 """Retreaves the object directly before this object with the same parent.
441 @return: the previous object if it exists else None.
442 @rtype: L{NVDAObject} or None
443 """
444 return None
445
447 """Retreaves the first object that this object contains.
448 @return: the first child object if it exists else None.
449 @rtype: L{NVDAObject} or None
450 """
451 return None
452
454 """Retreaves the last object that this object contains.
455 @return: the last child object if it exists else None.
456 @rtype: L{NVDAObject} or None
457 """
458 return None
459
461 """Retreaves a list of all the objects directly contained by this object (who's parent is this object).
462 @rtype: list of L{NVDAObject}
463 """
464 children=[]
465 child=self.firstChild
466 while child:
467 children.append(child)
468 child=child.next
469 return children
470
472 """Retreaves the row number of this object if it is in a table.
473 @rtype: int
474 """
475 raise NotImplementedError
476
478 """Retreaves the column number of this object if it is in a table.
479 @rtype: int
480 """
481 raise NotImplementedError
482
484 """Retreaves the number of rows this object contains if its a table.
485 @rtype: int
486 """
487 raise NotImplementedError
488
490 """Retreaves the number of columns this object contains if its a table.
491 @rtype: int
492 """
493 raise NotImplementedError
494
495 tableCellCoordsInName=False
496
498 """Retreaves the object that represents the table that this object is contained in, if this object is a table cell.
499 @rtype: L{NVDAObject}
500 """
501 raise NotImplementedError
502
504 """Recursively traverse and return the descendants of this object.
505 This is a depth-first forward traversal.
506 @return: The recursive descendants of this object.
507 @rtype: generator of L{NVDAObject}
508 """
509 for child in self.children:
510 yield child
511 for recursiveChild in child.recursiveDescendants:
512 yield recursiveChild
513
514 presType_unavailable="unavailable"
515 presType_layout="layout"
516 presType_content="content"
517
519 states=self.states
520 if controlTypes.STATE_INVISIBLE in states or controlTypes.STATE_UNAVAILABLE in states:
521 return self.presType_unavailable
522 role=self.role
523
524
525 if role==controlTypes.ROLE_STATICTEXT:
526 text=self.makeTextInfo(textInfos.POSITION_ALL).text
527 return self.presType_content if text and not text.isspace() else self.presType_layout
528
529 if role in (controlTypes.ROLE_UNKNOWN, controlTypes.ROLE_PANE, controlTypes.ROLE_TEXTFRAME, controlTypes.ROLE_ROOTPANE, controlTypes.ROLE_LAYEREDPANE, controlTypes.ROLE_SCROLLPANE, controlTypes.ROLE_SECTION,controlTypes.ROLE_PARAGRAPH,controlTypes.ROLE_TITLEBAR,controlTypes.ROLE_LABEL):
530 return self.presType_layout
531 name = self.name
532 description = self.description
533 if not name and not description:
534 if role in (controlTypes.ROLE_WINDOW,controlTypes.ROLE_PANEL, controlTypes.ROLE_PROPERTYPAGE, controlTypes.ROLE_TEXTFRAME, controlTypes.ROLE_GROUPING,controlTypes.ROLE_OPTIONPANE,controlTypes.ROLE_INTERNALFRAME,controlTypes.ROLE_FORM,controlTypes.ROLE_TABLEBODY):
535 return self.presType_layout
536 if role == controlTypes.ROLE_TABLE and not config.conf["documentFormatting"]["reportTables"]:
537 return self.presType_layout
538 if role in (controlTypes.ROLE_TABLEROW,controlTypes.ROLE_TABLECOLUMN,controlTypes.ROLE_TABLECELL) and (not config.conf["documentFormatting"]["reportTables"] or not config.conf["documentFormatting"]["reportTableCellCoords"]):
539 return self.presType_layout
540 if role in (controlTypes.ROLE_TABLEROW,controlTypes.ROLE_TABLECOLUMN):
541 try:
542 table=self.table
543 except NotImplementedError:
544 table=None
545 if table:
546
547
548 return self.presType_layout
549 return self.presType_content
550
556
558 nextPrevAttrib="next" if not goPrevious else "previous"
559 firstLastChildAttrib="firstChild" if not goPrevious else "lastChild"
560 found=None
561 if useChild:
562 child=getattr(self,firstLastChildAttrib)
563 childPresType=child.presentationType if child else None
564 if childPresType==self.presType_content:
565 found=child
566 elif childPresType==self.presType_layout:
567 found=child._findSimpleNext(useChild=True,useParent=False,goPrevious=goPrevious)
568 elif child:
569 found=child._findSimpleNext(useChild=False,useParent=False,goPrevious=goPrevious)
570 if found:
571 return found
572 next=getattr(self,nextPrevAttrib)
573 nextPresType=next.presentationType if next else None
574 if nextPresType==self.presType_content:
575 found=next
576 elif nextPresType==self.presType_layout:
577 found=next._findSimpleNext(useChild=True,useParent=False,goPrevious=goPrevious)
578 elif next:
579 found=next._findSimpleNext(useChild=False,useParent=False,goPrevious=goPrevious)
580 if found:
581 return found
582 parent=self.parent if useParent else None
583 while parent and parent.presentationType!=self.presType_content:
584 next=parent._findSimpleNext(useChild=False,useParent=False,goPrevious=goPrevious)
585 if next:
586 return next
587 parent=parent.parent
588
591
594
602
610
612 """Retreaves the number of children this object contains.
613 @rtype: int
614 """
615 return len(self.children)
616
618 """Retreaves the child of this object that currently has, or contains, the focus.
619 @return: the active child if it has one else None
620 @rtype: L{NVDAObject} or None
621 """
622 return None
623
625 """
626 Tries to force this object to take the focus.
627 """
628 pass
629
634
636 """Retreaves the object that this object is labeled by (example: the static text label beside an edit field).
637 @return: the label object if it has one else None.
638 @rtype: L{NVDAObject} or None
639 """
640 return None
641
643 """Retreaves position information for this object such as its level, its index with in a group, and the number of items in that group.
644 @return: a dictionary containing any of level, groupIndex and similarItemsInGroup.
645 @rtype: dict
646 """
647 return {}
648
650 """Retreaves an identifyer of the process this object is a part of.
651 @rtype: int
652 """
653 raise NotImplementedError
654
656 """
657 @return: True if this object is protected (hides its input for passwords), or false otherwise
658 @rtype: boolean
659 """
660 return False
661
663 """The index of this object in its parent object.
664 @return: The 0 based index, C{None} if there is no parent.
665 @rtype: int
666 @raise NotImplementedError: If not supported by the underlying object.
667 """
668 raise NotImplementedError
669
671 """The object to which content flows from this object.
672 @return: The object to which this object flows, C{None} if none.
673 @rtype: L{NVDAObject}
674 @raise NotImplementedError: If not supported by the underlying object.
675 """
676 raise NotImplementedError
677
679 """The object from which content flows to this object.
680 @return: The object from which this object flows, C{None} if none.
681 @rtype: L{NVDAObject}
682 @raise NotImplementedError: If not supported by the underlying object.
683 """
684 raise NotImplementedError
685
687 """Retrieve the parent text range which embeds this object.
688 The returned text range will have its start positioned on the embedded object character associated with this object.
689 That is, calling L{textInfos.TextInfo.getEmbeddedObject}() on the returned text range will return this object.
690 @return: The text range for the embedded object character associated with this object or C{None} if this is not an embedded object.
691 @rtype: L{textInfos.TextInfo}
692 @raise NotImplementedError: If not supported.
693 """
694 raise NotImplementedError
695
706
708 """Finds the closest status bar in relation to this object.
709 @return: the found status bar else None
710 @rtype: L{NVDAObject} or None
711 """
712 return None
713
718
725
756
761
768
775
777 """Called when the foreground window changes.
778 This method should only perform tasks specific to the foreground window changing.
779 L{event_focusEntered} or L{event_gainFocus} will be called for this object, so this method should not speak/braille the object, etc.
780 """
781 speech.cancelSpeech()
782
787
792
797
802
811
813 """Locates a TextInfo positioned at this object, in the closest flat review."""
814 parent=self.simpleParent
815 while parent:
816 ti=parent.treeInterceptor
817 if ti and self in ti and ti.rootNVDAObject==parent:
818 return ti.makeTextInfo(self)
819 if issubclass(parent.TextInfo,DisplayModelTextInfo):
820 try:
821 return parent.makeTextInfo(api.getReviewPosition().pointAtStart)
822 except (NotImplementedError,LookupError):
823 pass
824 try:
825 return parent.makeTextInfo(self)
826 except (NotImplementedError,RuntimeError):
827 pass
828 return parent.makeTextInfo(textInfos.POSITION_FIRST)
829 parent=parent.simpleParent
830
831 - def _get_basicText(self):
832 newTime=time.time()
833 oldTime=getattr(self,'_basicTextTime',0)
834 if newTime-oldTime>0.5:
835 self._basicText=u" ".join([x for x in self.name, self.value, self.description if isinstance(x, basestring) and len(x) > 0 and not x.isspace()])
836 if len(self._basicText)==0:
837 self._basicText=u""
838 else:
839 self._basicTextTime=newTime
840 return self._basicText
841
842 - def makeTextInfo(self,position):
843 return self.TextInfo(self,position)
844
846 """Information about this object useful to developers.
847 Subclasses may extend this, calling the superclass property first.
848 @return: A list of text strings providing information about this object useful to developers.
849 @rtype: list of str
850 """
851 info = []
852 try:
853 ret = repr(self.name)
854 except Exception as e:
855 ret = "exception: %s" % e
856 info.append("name: %s" % ret)
857 try:
858 ret = self.role
859 for name, const in controlTypes.__dict__.iteritems():
860 if name.startswith("ROLE_") and ret == const:
861 ret = name
862 break
863 except Exception as e:
864 ret = "exception: %s" % e
865 info.append("role: %s" % ret)
866 try:
867 stateConsts = dict((const, name) for name, const in controlTypes.__dict__.iteritems() if name.startswith("STATE_"))
868 ret = ", ".join(
869 stateConsts.get(state) or str(state)
870 for state in self.states)
871 except Exception as e:
872 ret = "exception: %s" % e
873 info.append("states: %s" % ret)
874 try:
875 ret = repr(self)
876 except Exception as e:
877 ret = "exception: %s" % e
878 info.append("Python object: %s" % ret)
879 try:
880 ret = repr(self.__class__.__mro__)
881 except Exception as e:
882 ret = "exception: %s" % e
883 info.append("Python class mro: %s" % ret)
884 try:
885 ret = repr(self.description)
886 except Exception as e:
887 ret = "exception: %s" % e
888 info.append("description: %s" % ret)
889 try:
890 ret = repr(self.location)
891 except Exception as e:
892 ret = "exception: %s" % e
893 info.append("location: %s" % ret)
894 try:
895 ret = self.value
896 if isinstance(ret, basestring) and len(ret) > 100:
897 ret = "%r (truncated)" % ret[:100]
898 else:
899 ret = repr(ret)
900 except Exception as e:
901 ret = "exception: %s" % e
902 info.append("value: %s" % ret)
903 try:
904 ret = repr(self.appModule)
905 except Exception as e:
906 ret = "exception: %s" % e
907 info.append("appModule: %s" % ret)
908 try:
909 ret = repr(self.TextInfo)
910 except Exception as e:
911 ret = "exception: %s" % e
912 info.append("TextInfo: %s" % ret)
913 return info
914