1 '''
2 Defines L{Tools} for registering, unregistering, introspecting, and otherwise
3 manging L{Tier}s, L{Perk}s, and L{Task}s.
4
5 @author: Peter Parente
6 @author: Scott Haeger
7 @organization: IBM Corporation
8 @copyright: Copyright (c) 2005, 2007 IBM Corporation
9 @license: The BSD License
10
11 All rights reserved. This program and the accompanying materials are made
12 available under the terms of the BSD license which accompanies
13 this distribution, and is available at
14 U{http://www.opensource.org/licenses/bsd-license.php}
15 '''
16 import weakref, sys
17 from Error import *
18 import AEEvent
19 import Base
20 import AEConstants, UIRegistrar
21
23 '''
24 Provides methods for managing L{Tier}s, L{Perk}s, and L{Task}s.
25 '''
27 '''
28 Gets the name of the profile LSR is running under.
29
30 @return: Profile name
31 @rtype: string
32 '''
33 return self.acc_eng.getProfile()
34
36 '''
37 Adds one or more L{Perk}s to the top of the stack. If more than one L{Perk}
38 is specified, the last specified L{Perk} will be at the top of the stack
39 when this method completes. That is, the behavior of pushing more than one
40 L{Perk} at a time is the same as if each L{Perk} were pushed individually.
41
42 @param names: Names of L{Perk}s to add
43 @type names: string
44 '''
45 reg = UIRegistrar
46 perks = []
47 for name in names:
48 perk = reg.loadOne(name)
49 if perk is not None:
50 perks.append(perk)
51 self.tier.pushPerk(self.acc_eng, *perks)
52
54 '''
55 Adds one L{Perk} to the stack at the insertion index. Negative indices are
56 valid per Python list convention.
57
58 @param index: Index at which the L{Perk} should be inserted into the stack
59 where zero is the bottom
60 @type index: integer
61 @param perk: L{Perk} to add
62 @type perk: L{Perk}
63 '''
64 reg = UIRegistrar
65 perk = reg.loadOne(perk)
66 if perk is not None:
67 self.tier.insertPerk(self.acc_eng, index, perk)
68
70 '''
71 Removes one or more L{Perk}s from the stack given their indices.
72
73 @param indices: Indices of L{Perk}s to remove
74 @type indices: list of integer
75 @raise IndexError: When the stack is empty
76 @raise ValueError: When specified L{Perk} is not found
77 '''
78 self.tier.popPerk(*indices)
79
81 '''
82 Removes the current L{Perk} from the L{Tier}. No L{Task.Tools} methods
83 should be invoked after this call.
84 '''
85 perks = self.tier.getPerks()
86 i = perks.index(self.perk)
87 self.tier.popPerk(i)
88
90 '''
91 Reloads all L{Perk}s in the current L{Tier}. Any changes made to the
92 L{Perk} logic will take effect immediately after the reload. This method
93 does not refer to the L{Perk}s associated with the current profile. It
94 simply reloads all currently loaded L{Perk}s.
95 '''
96 reg = UIRegistrar
97
98 names = self.getPerkClassNames()
99 names.reverse()
100
101 tier = self.tier
102 acc_eng = self.acc_eng
103
104 self.tier.clearPerks()
105
106 self.tier = tier
107 self.acc_eng = acc_eng
108
109 self.pushPerk(*names)
110
111 self.tier = None
112 self.acc_eng = None
113
115 '''
116 Internal method for getting instances of all installed or associated
117 L{UIElement}s for the given kind.
118
119 @note: Installed UIEs that are not importable because of missing
120 dependencies or other errors are not included in the list.
121 @note: Getting loaded chooser names is not currently supported.
122 @param kind: Kind of L{UIElement} to fetch metadata for, one of
123 L{UIRegistrar.ALL_KINDS}
124 @type kind: string
125 @param which: Which names to get, one of the UIE_ constants in
126 L{AEConstants}
127 @type which: integer
128 @return: All descriptions
129 @rtype: list of string
130 '''
131 reg = UIRegistrar
132 if which == AEConstants.UIE_LOADED:
133
134
135 if kind == reg.PERK:
136
137 uies = self.tier.getPerks()
138 elif kind == reg.DEVICE:
139
140 uies = self.device_man.getDevices()
141 elif kind == reg.CHOOSER:
142
143 uies = []
144 elif kind == reg.MONITOR:
145 imons, omons = self.device_man.getMonitors()
146 uies = list(set(imons) + set(omons) + set(self.tier_man.getMonitors())
147 + set(self.event_man.getMonitors()))
148
149 return uies
150
151
152 if which == AEConstants.UIE_INSTALLED:
153 names = reg.listInstalled(kind)
154 elif which == AEConstants.UIE_ALL_ASSOCIATED:
155 names = reg.listAssociated(kind, self.acc_eng.getProfile())
156 elif which == AEConstants.UIE_TIER_ASSOCIATED and kind == reg.PERK:
157 names = reg.listAssociated(kind, self.acc_eng.getProfile(),
158 self.tier.getName())
159
160
161 l = []
162 for name in names:
163 uie = reg.loadOne(name)
164 if uie is not None:
165 l.append(uie)
166 return l
167
169 '''
170 Internal method for getting class names of all installed or associated
171 L{UIElement}s for the given kind.
172
173 @note: Installed UIEs that are not importable because of missing
174 dependencies are not listed as installed to maintain parity with
175 L{_getNames} and L{_getDescriptions}.
176 @param kind: Kind of L{UIElement} to fetch metadata for, one of
177 L{UIRegistrar.ALL_KINDS}
178 @type kind: string
179 @param which: Which names to get, one of the UIE_ constants in
180 L{AEConstants}
181 @type which: integer
182 @return: All descriptions
183 @rtype: list of string
184 '''
185 reg = UIRegistrar
186 if which == AEConstants.UIE_INSTALLED:
187 names = reg.listInstalled(kind)
188 elif which == AEConstants.UIE_ALL_ASSOCIATED:
189 names = reg.listAssociated(kind, self.acc_eng.getProfile())
190 elif which == AEConstants.UIE_TIER_ASSOCIATED and kind == reg.PERK:
191 names = reg.listAssociated(kind, self.acc_eng.getProfile(),
192 self.tier.getName())
193
194 return filter(lambda x: reg.loadOne(x) is not None, names)
195
197 '''
198 Internal method for getting names of all installed or associated
199 L{UIElement}s for the given kind.
200
201 @param kind: Kind of L{UIElement} to fetch metadata for, one of
202 L{UIRegistrar.ALL_KINDS}
203 @type kind: string
204 @param which: Which names to get, one of the UIE_ constants in
205 L{AEConstants}
206 @type which: integer
207 @return: All descriptions
208 @rtype: list of string
209 '''
210 reg = UIRegistrar
211 if which == AEConstants.UIE_INSTALLED:
212 return [uie.getName() for uie in (reg.loadOne(name) for name in
213 reg.listInstalled(kind))
214 if uie is not None]
215 elif which in (AEConstants.UIE_ALL_ASSOCIATED,
216 AEConstants.UIE_TIER_ASSOCIATED):
217 names = self._getClassNames(kind, which)
218 if names is None:
219 return None
220 return [uie.getName() for uie in (reg.loadOne(name) for name in names)
221 if uie is not None]
222
224 '''
225 Internal method for getting descriptions of all installed or associated
226 L{UIElement}s for the given kind.
227
228 @param kind: Kind of L{UIElement} to fetch metadata for, one of
229 L{UIRegistrar.ALL_KINDS}
230 @type kind: string
231 @param which: Which names to get, one of the UIE_ constants in
232 L{AEConstants}
233 @type which: integer
234 @return: All descriptions
235 @rtype: list of string
236 '''
237 reg = UIRegistrar
238 if which == AEConstants.UIE_INSTALLED:
239 return [uie.getDescription() for uie in (reg.loadOne(name) for name in
240 reg.listInstalled(kind))
241 if uie is not None]
242 elif which in (AEConstants.UIE_ALL_ASSOCIATED,
243 AEConstants.UIE_TIER_ASSOCIATED):
244 names = self._getClassNames(kind, which)
245 if names is None:
246 return None
247 return [uie.getDescription() for uie in (reg.loadOne(name)
248 for name in names)
249 if uie is not None]
250
270
289
307
326
328 '''
329 Gets the programmatic class names of all L{AEOutput} and L{AEInput} devices
330 currently loaded in, installed in, or associated with the active profile
331 depending on the which flag.
332
333 The default value is used if which is invalid.
334
335 @param which: Which names to get, one of the UIE_ constants in
336 L{AEConstants}
337 @type which: integer
338 @return: Names of all L{AEOutput} and L{AEInput} classes
339 @rtype: list of string
340 '''
341 if which != AEConstants.UIE_LOADED:
342 return self._getClassNames(UIRegistrar.DEVICE, which)
343 else:
344 return [dev.getClassName() for dev in self.device_man.getDevices()]
345
347 '''
348 Gets the human readable names of all L{AEOutput} and L{AEInput} devices
349 currently loaded in, installed in, or associated with the active profile
350 depending on the which flag.
351
352 The default value is used if which is invalid.
353
354 @param which: Which names to get, one of the UIE_ constants in
355 L{AEConstants}
356 @type which: integer
357 @return: Names of all L{AEOutput} and L{AEInput} devices
358 @rtype: list of string
359 '''
360 if which != AEConstants.UIE_LOADED:
361 return self._getNames(UIRegistrar.DEVICE, which)
362 else:
363 return [dev.getName() for dev in self.device_man.getDevices()]
364
366 '''
367 Gets the descriptions of all L{AEOutput} and L{AEInput} devices
368 currently loaded in, installed in, or associated with the active profile
369 depending on the which flag.
370
371 The default value is used if which is invalid.
372
373 @param which: Which names to get, one of the UIE_ constants in
374 L{AEConstants}
375 @type which: integer
376 @return: Names of all L{AEOutput} and L{AEInput} devices
377 @rtype: list of string
378 '''
379 if which != AEConstants.UIE_LOADED:
380 return self._getDescriptions(UIRegistrar.DEVICE, which)
381 else:
382 return [dev.getDescription() for dev in self.device_man.getDevices()]
383
385 '''
386 Gets the programmatic class names of all L{AEMonitor}s currently loaded in,
387 installed in, or associated with the active profile depending on the which
388 flag.
389
390 The default value is used if which is invalid.
391
392 @param which: Which names to get, one of the UIE_ constants in
393 L{AEConstants}
394 @type which: integer
395 @return: Names of all L{AEMonitor} classes
396 @rtype: list of string
397 '''
398 if which != AEConstants.UIE_LOADED:
399 return self._getClassNames(UIRegistrar.MONITOR, which)
400 else:
401 return [mon.getClassName() for mon in
402 self._getUIEInstances(UIRegistrar.MONITOR, which)]
403
405 '''
406 Gets the human readable names of all L{AEMonitor}s currently loaded in,
407 installed in, or associated with the active profile depending on the which
408 flag.
409
410 The default value is used if which is invalid.
411
412 @param which: Which names to get, one of the UIE_ constants in
413 L{AEConstants}
414 @type which: integer
415 @return: Names of all L{AEMonitor}s
416 @rtype: list of string
417 '''
418 if which != AEConstants.UIE_LOADED:
419 return self._getNames(UIRegistrar.MONITOR, which)
420 else:
421 return [mon.getName() for mon in
422 self._getUIEInstances(UIRegistrar.MONITOR, which)]
423
425 '''
426 Gets the human readable descriptions of all L{AEMonitor}s currently loaded
427 in, installed in, or associated with the active profile depending on the
428 which flag.
429
430 The default value is used if which is invalid.
431
432 @param which: Which names to get, one of the UIE_ constants in
433 L{AEConstants}
434 @type which: integer
435 @return: Descriptions of all L{AEMonitor}s
436 @rtype: list of string
437 '''
438 if which != AEConstants.UIE_LOADED:
439 return self._getDescriptions(UIRegistrar.MONITOR, which)
440 else:
441 return [mon.getDescription() for mon in
442 self._getUIEInstances(UIRegistrar.MONITOR, which)]
443
445 '''
446 Gets the programmatic class names of all L{AEChooser}s installed in or
447 associated with the active profile depending on the which flag.
448
449 The default value is used if which is invalid.
450
451 @note: Getting loaded chooser names is not currently supported.
452 @param which: Which names to get, one of the UIE_ constants in
453 L{AEConstants}
454 @type which: integer
455 @return: Names of all L{AEChooser} classes
456 @rtype: list of string
457 '''
458 if which != AEConstants.UIE_LOADED:
459 return self._getClassNames(UIRegistrar.CHOOSER, which)
460
462 '''
463 Gets the human readable names of all L{AEChooser}s installed in or
464 associated with the active profile depending on the which flag.
465
466 The default value is used if which is invalid.
467
468 @note: Getting loaded chooser names is not currently supported.
469 @param which: Which names to get, one of the UIE_ constants in
470 L{AEConstants}
471 @type which: integer
472 @return: Names of all L{AEChooser}s
473 @rtype: list of string
474 '''
475 if which != AEConstants.UIE_LOADED:
476 return self._getNames(UIRegistrar.CHOOSER, which)
477
479 '''
480 Gets the descriptions of all L{AEChooser}s installed in or associated with
481 the active profile depending on the which flag.
482
483 The default value is used if which is invalid.
484
485 @note: Getting loaded chooser names is not currently supported.
486 @param which: Which names to get, one of the UIE_ constants in
487 L{AEConstants}
488 @type which: integer
489 @return: Descriptions of all L{AEChooser}s
490 @rtype: list of string
491 '''
492 if which != AEConstants.UIE_LOADED:
493 return self._getDescriptions(UIRegistrar.CHOOSER, which)
494
496 '''
497 Gets the programmatic class names of all L{Perk}s in this L{Tier}, all
498 installed L{Perk}s, L{Perk}s associated with this L{Tier}, or all L{Perk}s
499 associated with this profile depending on the which flag.
500
501 The default value is used if which is invalid.
502
503 @param which: Which names to get, one of the UIE_ constants in
504 L{AEConstants}
505 @type which: integer
506 @return: Names of all L{Perk} classes
507 @rtype: list of string
508 '''
509 if which != AEConstants.UIE_LOADED:
510 return self._getClassNames(UIRegistrar.PERK, which)
511 else:
512 return [perk.getClassName() for perk in self.tier.getPerks()]
513
515 '''
516 Gets the human readable names of all L{Perk}s in this L{Tier}, all
517 installed L{Perk}s, L{Perk}s associated with this L{Tier}, or all L{Perk}s
518 associated with this profile depending on the which flag.
519
520 The default value is used if which is invalid.
521
522 @param which: Which names to get, one of the UIE_ constants in
523 L{AEConstants}
524 @type which: integer
525 @return: Names of all L{Perk}s
526 @rtype: list of string
527 '''
528 if which != AEConstants.UIE_LOADED:
529 return self._getNames(UIRegistrar.PERK, which)
530 else:
531 return [perk.getName() for perk in self.tier.getPerks()]
532
534 '''
535 Gets the human readable descriptions of all L{Perk}s in this L{Tier}, all
536 installed L{Perk}s, L{Perk}s associated with this L{Tier}, or all L{Perk}s
537 associated with this profile depending on the which flag.
538
539 The default value is used if which is invalid.
540
541 @param which: Which names to get, one of the UIE_ constants in
542 L{AEConstants}
543 @type which: integer
544 @return: Descriptions of all L{Perk}s
545 @rtype: list of string
546 '''
547 if which != AEConstants.UIE_LOADED:
548 return self._getDescriptions(UIRegistrar.PERK, which)
549 else:
550 return [perk.getDescription() for perk in self.tier.getPerks()]
551
553 '''
554 Universal task registration method. Uses known interfaces to try to
555 register the given L{Task} as an event task, an input task, a timer task,
556 etc. All information for configuring the L{Task} is contained in the
557 task itself.
558
559 @param task: Task to register
560 @type task: L{Task.Base.Task}
561 @raise NotImplementedError: When the L{Task} does not properly implement
562 the interfaces it should
563 '''
564 count = 0
565 try:
566
567 self.perk.registerEventTask(task, *task.getEventLayers())
568 count += 1
569 except (AttributeError, NotImplementedError):
570 pass
571 try:
572
573 self.perk.registerTimerTask(task, task.getTimerInterval())
574 count += 1
575 except AttributeError:
576 pass
577 try:
578
579 self.perk.registerNamedTask(task, task.getIdentity())
580 count += 1
581 except (AttributeError, ValueError):
582 pass
583 if count == 0:
584
585 raise NotImplementedError
586
588 '''
589 Universal task unregistration method. Uses known interfaces to try to
590 unregister the given L{Task} as an event task, an input task, a timer task,
591 etc. All information for configuring the L{Task} is contained in the
592 task itself.
593
594 @param task: Task to unregister
595 @type task: L{Task.Base.Task}
596 @raise NotImplementedError: When the L{Task} does not properly implement
597 the interfaces it should
598 '''
599 count = 0
600 perk = self.perk
601 try:
602
603 perk.unregisterEventTask(task, *task.getEventLayers())
604 count += 1
605 except AttributeError:
606 pass
607 try:
608
609
610 task.getTimerInterval
611 perk.unregisterTimerTask(task)
612 count += 1
613 except AttributeError:
614 pass
615 try:
616
617 perk.unregisterNamedTask(task.getIdentity())
618 count += 1
619 except (AttributeError, ValueError, KeyError):
620 pass
621 if not count:
622
623 raise NotImplementedError
624
626 '''
627 Chains the L{Task} with the given name to the target L{Task}. If link is
628 CHAIN_BEFORE, the linked L{Task} will execute before the target. If link is
629 CHAIN_AFTER, the linked L{Task} will execute after. If link is
630 CHAIN_AROUND, the linked L{Task} will execute in lieu of the target, but
631 can execute the target manually using L{doTask}.
632
633 @param target: Name of the L{Task} to link to
634 @type target: string
635 @param link: One of the CHAIN constants in L{AEConstants.Tools}
636 @type link: integer
637 @param name: Name of the L{Task} to link
638 @type name: string
639 '''
640 self.perk.linkTaskToChain(name, link, target)
641
643 '''
644 Unchains the L{Task} with the given name to the target L{Task}. The link
645 parameter has the same meaning as in L{chainTask}. If link is set to None,
646 one reference to the named L{Task} is removed from the before, after, and
647 around chains.
648
649 @note: The target L{Task} must be registered at the time of invocation.
650 @param target: Name of the L{Task} to unlink from
651 @type target: string
652 @param link One of the CHAIN constants in L{AEConstants.Tools} or None
653 @type link: integer
654 @param name: Name of the L{Task} to unlink
655 @type name: string
656 @raise ValueError: When the named L{Task} is not unlinked at least once
657 @raise KeyError: When the target L{Task} does not have a chain segement in
658 this L{Perk} for the given link type
659 '''
660 self.perk.unlinkTaskFromChain(name, link, target)
661
663 '''
664 Gets the L{Task} with the given name if it is registered anywhere in the
665 current L{Tier}. If no L{Task} is registered under the given name, returns
666 None.
667
668 Calls L{Tier.Tier.getNamedTask} to search across all L{Perk}s in the owning
669 L{Tier}.
670
671 @param name: Name of the L{Task} to locate
672 @type name: string
673 @return: L{Task} with the given name or None
674 @rtype: L{Task.Base.Task}
675 '''
676 return self.tier.getNamedTask(name)
677
679 '''
680 Gets all registered L{Task}s registered to handle the given L{AEEvent} type
681 on the given layer from the current L{Tier}.
682
683 Calls L{Tier.Tier.getEventTasks} to search across all L{Perk}s in the
684 owning L{Tier}.
685
686 @param event_type: Desired type of L{AEEvent}
687 @type event_type: L{AEEvent} class
688 @param task_layer: Layer on which the desired L{Task}s are registered
689 @type task_layer: integer
690 @return: List of all L{Task}s that handle the given event type and on
691 the given layer in the L{Tier} which owns this L{Perk}
692 @rtype: list of L{Task.Base.Task}
693 '''
694 return self.tier.getEventTasks(event_type, task_layer)
695
697 '''
698 Gets the L{Task} with the given name if it is registered B{in this L{Perk}
699 only}. If no L{Task} is registered under the given name in this L{Perk},
700 returns None.
701
702 @param name: Name of the L{Task} to locate
703 @type name: string
704 @return: L{Task} with the given name or None
705 @rtype: L{Task.Base.Task}
706 @see: L{getTierNamedTask}
707 '''
708 return self.perk.getNamedTask(name)
709
711 '''
712 Get all registered L{Task}s registered to handle the given L{AEEvent} type
713 B{in this L{Perk} only}.
714
715 @param event_type: Desired type of L{AEEvent}
716 @type event_type: L{AEEvent} class
717 @param task_layer: Layer on which the desired L{Task}s are registered
718 @type task_layer: integer
719 @return: List of all L{Task}s that handle the given event type on the given
720 layer in this L{Perk}
721 @rtype: list of L{Task.Base.Task}
722 @see: L{getTierEventTasks}
723 '''
724 return self.perk.getEventTasks(event_type, task_layer)
725
727 '''
728 Gets the default L{AEState} associated with an L{AEOutput} or L{AEInput}
729 device currently loaded in the L{DeviceManager}.
730
731 @param device_name: Name of the device
732 @type device_name: string
733 @return: Loaded state for the device
734 @rtype: L{AEState}
735 '''
736 try:
737 dev = self.getOutputDevice(device_name)
738 except InvalidDeviceError:
739 return None
740 return dev.getDefaultStyle()
741
743 '''
744 Gets the L{AEState} associated with a L{Perk}. If the state was previously
745 persisted to disk, it is loaded from disk. If not, a new state object
746 is created for the named Perk and immediately persisted in the user's
747 profile.
748
749 @param perk_name: Name of the L{Perk}
750 @type perk_name: string
751 @return: Loaded state for the L{Perk}
752 @rtype: L{AEState}
753 '''
754 if not reload:
755 perk = self.getPerkByName(perk_name)
756 return perk.getState()
757
758
759 perk = UIRegistrar.loadOne(perk_name)
760 if perk is None:
761
762 return None
763
764 state = perk.getState()
765
766 try:
767 return self.sett_man.loadState(perk_name, state)
768 except KeyError:
769 pass
770
771 self.sett_man.saveState(perk_name, state)
772 return state
773
775 '''
776 Loads and shows all L{AEMonitor}s associated with this profile.
777
778 @return: Was at least one monitor loaded?
779 @rtype: boolean
780 '''
781 loaded = False
782 reg = UIRegistrar
783 mons = reg.loadAssociated(UIRegistrar.MONITOR, self.acc_eng.getProfile())
784 emons = self.event_man.getMonitors()
785 imons, omons = self.device_man.getMonitors()
786 tmons = self.tier_man.getMonitors()
787 if not len(emons):
788 self.event_man.addMonitors(*mons)
789 loaded = True
790 if not len(tmons):
791 self.tier_man.addMonitors(*mons)
792 loaded = True
793 if not (len(imons) + len(omons)):
794 self.device_man.addMonitors(*mons)
795 loaded = True
796 return loaded
797
799 '''
800 Hides and unloads all L{AEMonitor}s associated with this profile.
801
802 @return: Was at least one monitor unloaded?
803 @rtype: boolean
804 '''
805 unloaded = False
806 emons = self.event_man.getMonitors()
807 imons, omons = self.device_man.getMonitors()
808 tmons = self.tier_man.getMonitors()
809 for mon in (emons, imons, omons, tmons):
810 if len(mon):
811 mon.clear()
812 unloaded = True
813 return unloaded
814
816 '''
817 Loads and shows one L{AEMonitor}.
818
819 @param name: Class name of the L{AEMonitor}
820 @type name: string
821 '''
822 mon = UIRegistrar.loadOne(name)
823 self.event_man.addMonitors(mon)
824 self.tier_man.addMonitors(mon)
825 self.device_man.addMonitors(mon)
826
828 '''
829 Hides and unloads one L{AEMonitor}.
830
831 @param name: Class name of the L{AEMonitor}
832 @type name: string
833 '''
834 emons = self.event_man.getMonitors()
835 tmons = self.tier_man.getMonitors()
836 imons, omons = self.device_man.getMonitors()
837 for mons in (emons, tmons, imons, omons):
838 mons.removeByClassName(name)
839
841 '''
842 Loads an L{AEChooser} dialog with the given name from disk. Passes the
843 keyword arguments to the init method of the chooser. This method should
844 typically only be invoked by a L{Task.ChooserTask} subclass.
845
846 @param name: UIE name of the chooser
847 @type name: string
848 @param kwargs: Keyword arguments to initialize the chooser
849 @type kwargs: dictionary
850 @return: Reference to the chooser if it was created. If it already existed,
851 None is returned instead.
852 @rtype: L{AEChooser}
853 '''
854 reg = UIRegistrar
855 chooser = reg.loadOne(name)
856 if chooser is None:
857 return
858 try:
859
860 chooser(self.event_man, self.tier.getIdentity())
861 except ValueError, ex:
862
863 ex.args[0].activate(**kwargs)
864 return None
865 else:
866
867 chooser.init(**kwargs)
868
869 self.perk.registerChooserTask(chooser, self)
870 return chooser
871
873 '''
874 Unloads the given L{AEChooser} dialog. This method should typically only be
875 invoked by a L{Task.ChooserTask} subclass.
876
877 @param chooser: The chooser to unload
878 @type chooser: L{AEChooser}
879 '''
880
881 self.perk.unregisterChooserTask(chooser)
882
883 - def doTask(self, task_name, chain=True, propagate=True, layer=None,**kwargs):
884 '''
885 Immediately executes a L{Task} registered under the given name in this
886 L{Tier}. Keyword arguments for L{Task} execution may be provided. The
887 L{task_por} of this L{Task} is always provided to the L{Task} being
888 executed and this L{Task}'s L{task_por} is updated with the value of the
889 pointer after the other L{Task} has finished execution.
890
891 The chain parameter dictates whether only the named L{Task} is executed
892 (False), or if all other L{Task}s chained to it are as well (True). The
893 propagate parameter determines whether the execute or update method is
894 called on the L{Task}. This param is not typically specified by a L{Task}
895 or L{Perk}. It is used internally by L{Task.CyclicInputTask} to handle the
896 propagation flag in Task chains.
897
898 @param task_name: Name of the L{Task} to execute
899 @type task_name: string
900 @param chain: Execute all L{Task}s chained to the one named or just the
901 one named?
902 @type chain: boolean
903 @param propagate: Should chained L{Task}s be executed (True) or updated
904 (False)?
905 @type propagate: boolean
906 @param layer: Event layer on which the L{Task} will execute. Defaults to
907 the same layer as the caller if None.
908 @type layer: integer
909 @param kwargs: Arbitrary keyword arguments to pass to the L{Task}, some of
910 which may be required, others which may be optional, and others which
911 may be completely ignored
912 @type kwargs: dictionary
913 '''
914
915 if layer is None: layer = self.layer
916
917 task = self.tier.getNamedTask(task_name)
918 if task is not None:
919 perk = task.getPerk()
920 self.tier.manageChain(self.task_por, task_name, task, perk, layer,
921 kwargs, propagate, chain)
922
923 self.task_por = self.tier.getPointer()
924
925 - def blockNTasks(self, n, task_type, condition=lambda **x: True):
926 '''
927 Blocks L{Task}s of the given type from executing in response to the next
928 n events. This is a convenience shortcut to avoid registering one-shot
929 L{Task}s in L{Perk}s to do exactly the same thing.
930
931 @param n: Number of events to block
932 @type n: integer
933 @param task_type: Kind of L{Task} to block
934 @type task_type: L{Task} class
935 @param condition: Condition statement to check if the event is actually
936 one to be consumed. The callable is called with the keyword arguments
937 passed to the L{Task} execute method.
938 @type condition: callable
939 '''
940
941 class consumer(task_type):
942 def init(self):
943 self.count = n
944 def execute(self, **kwargs):
945 if not condition(**kwargs):
946 return
947 self.count -= 1
948 if self.count == 0:
949 self.unregisterTask(self)
950 return False
951
952 self.registerTask(consumer(None))
953
954 - def associatePerk(self, name, tier=None, all_tiers=False, index=None):
955 '''
956 Associates a L{Perk} with the active profile.
957
958 @param name: Name of the UIE to associate
959 @type name: string
960 @param tier: Name of the L{Tier} with which the L{Perk} will be associated.
961 Defaults to the name of the L{Tier} specified by the L{Perk} itself.
962 @type tier: string
963 @param all_tiers: Should the L{Perk} be loaded on every L{Tier}? Defaults
964 to the value specified by the L{Perk} itself.
965 @type all_tiers: boolean
966 @param index: Load order index of the L{Perk}. Lower means sooner to load
967 but also later to handle events (i.e. bottom of the L{Perk} stack).
968 @type index: integer
969 '''
970 UIRegistrar.associate(name, [self.getProfileName()], tier, all_tiers,index)
971
973 '''
974 Disassociates a L{Perk} from the active profile.
975
976 @param name: Name of the UIE to disassociate
977 @type name: string
978 @param tier: Name of the L{Tier} from which the L{Perk} will be
979 disassociated. Defaults to the name of the L{Tier} specified by the
980 L{Perk} itself.
981 @type tier: string
982 @param all_tiers: Should the L{Perk} be removed from the list of Perks to
983 load for every L{Tier}? Defaults to the value specified by the L{Perk}
984 itself.
985 '''
986 UIRegistrar.disassociate(name, [self.getProfileName()], tier, all_tiers)
987
989 '''
990 Associates a L{AEMonitor} with the active profile. Loads it immediately.
991
992 @param name: Name of the UIE to associate
993 @type name: string
994 '''
995 UIRegistrar.associate(name, [self.getProfileName()])
996 self.loadMonitor(name)
997
999 '''
1000 Associates a L{AEMonitor} with the active profile. Unloads it immediately.
1001
1002 @param name: Name of the UIE to associate
1003 @type name: string
1004 '''
1005 self.unloadMonitor(name)
1006 UIRegistrar.disassociate(name, [self.getProfileName()])
1007
1009 '''
1010 Associates a L{AEOutput} or L{AEInput} device with the active profile.
1011 Does not load it immediately. See L{refreshDevices} for that functionality.
1012
1013 @param name: Name of the UIE to associate
1014 @type name: string
1015 @param index: Load order index of the device where lower means sooner, None
1016 means last.
1017 @type index: integer
1018 '''
1019 UIRegistrar.associate(name, [self.getProfileName()], index=index)
1020
1022 '''
1023 Disassociates a L{AEOutput} or L{AEInput} device from the active profile.
1024 Does not unload it immediately. See L{refreshDevices} for that
1025 functionality.
1026
1027 @param name: Name of the UIE to associate
1028 @type name: string
1029 '''
1030 UIRegistrar.disassociate(name, [self.getProfileName()])
1031
1033 '''
1034 Unloads all existing devices then immediately loads all devices associated
1035 with the active profile.
1036 '''
1037 self.device_man.unloadDevices()
1038 self.device_man.loadDevices()
1039
1041 '''
1042 Stores the given value under the given name. The data will be available via
1043 L{getTempVal} to all L{Task}s executing or updating in response to the
1044 current L{AEEvent}. This includes cascading L{Task.EventTask}s, chained
1045 L{Task.InputTask}s with names, etc. Once the event has been handled by all
1046 L{Task}s, all stored information is discarded automatically.
1047
1048 The name must be an immutable object. The value can be an arbitrary object.
1049 Only the value from the most recent call with a given name is stored.
1050
1051 @param name: Name to associate with the value
1052 @type name: immutable
1053 @param value: Any value to store
1054 @type value: object
1055 '''
1056 self.tier.setTempVal(name, value)
1057
1059 '''
1060 Gets the value previously stored under the given name using L{setTempVal}.
1061 See that method for details.
1062
1063 If no value has been stored under the given name, None is returned.
1064
1065 @param name: Name of the stored data
1066 @type name: immutable
1067 @return: Value stored under the given name or None
1068 @rtype: object
1069 '''
1070 try:
1071 return self.tier.getTempVal(name)
1072 except KeyError:
1073 return None
1074
1076 '''
1077 Adds new constants to L{AEConstants} such that they are visible to other
1078 L{Perk}s. If any of the named constants do not exist, an exception will
1079 be raised. If any of the named constants are already registered, they will
1080 be silently ignored by L{AEConstants.register}.
1081
1082 @param scope: Scope in which the constants are defined (e.g. globals())
1083 @type scope: dictionary
1084 @param names: Names of constants to register
1085 @type names: list of string
1086 @raise KeyError: When one of the named constants does not exist in the
1087 scope
1088 '''
1089 AEConstants.register(dict(((name, scope[name]) for name in names)))
1090
1092 '''
1093 Gets the L{Perk} with the given name.
1094
1095 If no perk is registered under the given name, KeyError is raised.
1096
1097 @param name: Name of the perk
1098 @type name: string
1099 @return: Perk with the given name
1100 @rtype: object
1101 @raise KeyError: When the perk with the given name is not found
1102 '''
1103 for perk in self.tier.getPerks():
1104 if perk.getClassName() == name:
1105 return perk
1106 raise KeyError
1107
1109 '''
1110 Gets the L{Perk} instance variable with the given name.
1111
1112 If no perk is registered under the given name a KeyError is raised
1113 if the perk does not contain var_name an AttributeError is raised.
1114
1115 @param perk_name: Name of the perk
1116 @type perk_name: immutable
1117 @param var_name: Name of the instance variable
1118 @type var_name: immutable
1119 @return: perk variable with the given name
1120 @rtype: object
1121 @raise KeyError: When the perk or variable with it's given name
1122 is not found
1123 @raise AttributeError: When attribute is not found
1124 is not found
1125 '''
1126 perk = self.getPerkByName(perk_name)
1127 return getattr(perk, var_name)
1128
1129 - def setPerkVar(self, perk_name, var_name, value):
1130 '''
1131 Sets the L{Perk} instance variable with the given name to value.
1132
1133 If no perk is registered under the given name a KeyError is raised
1134 if the perk does not contain var_name an AttributeError is raised.
1135
1136 @param perk_name: Name of the perk
1137 @type perk_name: immutable
1138 @param var_name: Name of the instance variable
1139 @type var_name: immutable
1140 @param value: value to set instance variable
1141 @type value: immutable
1142 @return: perk variable with the given name
1143 @rtype: object
1144 @raise KeyError: When the perk or variable with it's given name
1145 @raise AttributeError: When attribute is not found
1146 '''
1147 perk = self.getPerkByName(perk_name)
1148 setattr(perk, var_name, value)
1149
1151 '''
1152 Gets the L{Perk} L{Setting} state variable with the given name.
1153
1154 If no perk is registered under the given name or L{setting_name} is not
1155 found, KeyError is raised.
1156
1157 @param perk_name: Name of the perk
1158 @type perk_name: immutable
1159 @param setting_name: Name of the perk
1160 @type setting_name: immutable
1161 @return: L{Setting} object for given perk.
1162 @rtype: object
1163 @raise KeyError: When the perk is not found
1164 '''
1165 if perk_name is None:
1166 perk_name = self.perk.getClassName()
1167 state = self.getPerkState(perk_name, reload=False)
1168 return state.getSettingObj(setting_name)
1169
1171 '''
1172 Gets the value of the L{Perk} L{Setting} state variable with the given
1173 name.
1174
1175 If no perk is registered under the given name or if L{setting_name} is not
1176 found, KeyError is raised.
1177
1178 @param perk_name: Name of the perk
1179 @type perk_name: immutable
1180 @param setting_name: Name of the perk
1181 @type setting_name: immutable
1182 @return: value contained in L{AEState} attribute with given name
1183 @rtype: object
1184 @raise KeyError: When the perk is not found
1185 '''
1186 if perk_name is None:
1187 perk_name = self.perk.getClassName()
1188 state = self.getPerkState(perk_name, reload=False)
1189 return state.getSettingVal(setting_name)
1190
1192 '''
1193 Sets the value of the L{Perk} L{Setting} state variable with the given
1194 name.
1195
1196 If no perk is registered under the given name or if L{setting_name} is not
1197 found, KeyError is raised.
1198
1199 @param perk_name: Name of the perk
1200 @type perk_name: immutable
1201 @param setting_name: Name of the perk
1202 @type setting_name: immutable
1203 @param value: value contained in L{AEState} attribute with given name
1204 @param value: object
1205 @raise KeyError: When the L{Perk} is not found
1206 '''
1207 if perk_name is None:
1208 perk_name = self.perk.getClassName()
1209 state = self.getPerkState(perk_name, reload=False)
1210 state.setSettingVal(setting_name, value)
1211
1212 - def getHistory(self):
1213 '''
1214 Gets the zipped contents of L{getTaskHistory} and L{getPerkHistory}. This
1215 method does not involve extra processing because the history is already
1216 zipped in the L{Tier}. In fact, the other methods require the extra work
1217 of unzipping.
1218
1219 The history is ordered from the first L{Task} to respond to an event to
1220 the most recent L{Task} to respond, including the current L{Task}.
1221
1222 @return: List of L{Task} identities and L{Perk} class names
1223 @rtype: list of 2-tuple of string
1224 '''
1225 return self.tier.getHistory()
1226
1227 - def getTaskHistory(self):
1228 '''
1229 Gets the identities of all L{Task}s that have executed in response to the
1230 event currently being processed. This includes all chained L{Task}s and all
1231 L{Task}s executed using L{doTask} flattened into a linear history.
1232
1233 If any L{Task} that executed did not have an identity, None is substituted
1234 in its place.
1235
1236 The history is ordered from the first L{Task} to respond to an event to
1237 the most recent L{Task} to respond, including the current L{Task}.
1238
1239 @return: Identities of the L{Task}s
1240 @rtype: list of string
1241 '''
1242 h = self.tier.getHistory()
1243 return [names[0] for names in h]
1244
1245 - def getPerkHistory(self):
1246 '''
1247 Gets the class names of all L{Perk}s that have executed in response to the
1248 event currently being processed. The contents of the list returned by this
1249 method have a one-to-one pairing with the list contents from
1250 L{getTaskHistory}.
1251
1252 The history is ordered from the first L{Perk} to respond to an event to
1253 the most recent L{Perk} to respond, including the current L{Perk}.
1254
1255 @return: Class names of the L{Perk}s
1256 @rtype: list of string
1257 '''
1258 h = self.tier.getHistory()
1259 return [names[1] for names in h]
1260
1262 '''
1263 Gets the identity of the L{Task} which this one is executing before, after,
1264 or around according to a previous chaining. If this L{Task} is not
1265 executing as part of a chain, returns None.
1266
1267 @return: Identity of the L{Task} or None
1268 @rtype: string
1269 '''
1270 try:
1271 return self.tier.getAnchor()[0]
1272 except TypeError:
1273 return None
1274
1276 '''
1277 Gets the class name of the L{Perk} owning the L{Task} that would be
1278 returned by L{getAnchorTaskId}.
1279
1280 @see: L{getAnchorTaskId}
1281 @return: Class name of the L{Perk} or None
1282 @rtype: string
1283 '''
1284 try:
1285 return self.tier.getAnchor()[1]
1286 except TypeError:
1287 return None
1288
1290 '''
1291 Gets the names of all L{Task}s currently registered in the named L{Perk}.
1292 If no name is given, this L{Perk} is used. If the named L{Perk} is not
1293 found, an exception is raised.
1294
1295 @param perk_name: Name of the L{Perk} to query or None to mean this one
1296 @type perk_name: string
1297 @return: List of all registered L{Task} names
1298 @rtype: list of string
1299 @raise KeyError: When the named L{Perk} is not loaded
1300 '''
1301 if perk_name is None:
1302 return self.perk.getTaskNames()
1303 else:
1304 for perk in self.tier.getPerks():
1305 if perk.getClassName() == perk_name:
1306 return perk.getTaskNames()
1307 raise KeyError(perk_name)
1308
1310 '''
1311 Gets the names of all L{Task}s currently registered in this L{Tier}.
1312
1313 @return: List of all registered L{Task} names
1314 @rtype: list of string
1315 '''
1316 names = []
1317 for perk in self.tier.getPerks():
1318 names.extend(perk.getTaskNames())
1319 return names
1320