Package Peach :: Package Generators :: Module dictionary
[hide private]

Source Code for Module Peach.Generators.dictionary

   1   
   2  ''' 
   3  Contains generators that use a set of data (dictionaries) such as files, lists, 
   4  etc. 
   5   
   6  @author: Michael Eddington 
   7  @version: $Id: Peach.Generators.dictionary-pysrc.html 1138 2008-08-16 19:39:03Z meddingt $ 
   8  ''' 
   9   
  10  # 
  11  # Copyright (c) 2005-2007 Michael Eddington 
  12  # Copyright (c) 2004-2005 IOActive Inc. 
  13  # 
  14  # Permission is hereby granted, free of charge, to any person obtaining a copy  
  15  # of this software and associated documentation files (the "Software"), to deal 
  16  # in the Software without restriction, including without limitation the rights  
  17  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell  
  18  # copies of the Software, and to permit persons to whom the Software is  
  19  # furnished to do so, subject to the following conditions: 
  20  # 
  21  # The above copyright notice and this permission notice shall be included in     
  22  # all copies or substantial portions of the Software. 
  23  # 
  24  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
  25  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
  26  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
  27  # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
  28  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
  29  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
  30  # SOFTWARE. 
  31  # 
  32   
  33  # Authors: 
  34  #   Michael Eddington (mike@phed.org) 
  35   
  36  # $Id: Peach.Generators.dictionary-pysrc.html 1138 2008-08-16 19:39:03Z meddingt $ 
  37   
  38  import types, static, sys, struct 
  39  sys.path.append("c:/projects/peach") 
  40  from Peach import generator, group 
  41  from Peach.group import GroupSequence 
  42  from Peach.generator import * 
  43  from Peach.Generators.block import Block3 
  44  from Peach.Generators.static import * 
  45   
  46  #__all__ = ['Dictionary', 'GeneratorList', 'GeneratorList2', 'List', 'BinaryList'] 
  47   
48 -class Flags(Generator):
49 ''' 50 DEPRICATED -- Use Flags2, it works better. This class is still around 51 for backwards compatability. 52 '''
53 - def __init__(self, group = None, flagSpecs = None, flagGenerators = None, 54 flagBase = 0):
55 ''' 56 @type group: Group 57 @param group: Group to assign this generator to 58 @type flagSpecs: Array of integers 59 @param flagSpecs: Array of bit offset for corresponding flag 60 @type flagGenerators: Array of Generators 61 @param flagGenerators: Generators in this array produce flag values 62 @type flagBase: Number 63 @param flagBase: [optional] Base of flag (defaults to 0x0) 64 ''' 65 Generator.__init__(self) 66 self.setGroup(group) 67 68 if flagSpecs == None: 69 flagSpecs = [] 70 if flagGenerators == None: 71 flagGenerators = [] 72 73 if len(flagSpecs) != len(flagGenerators): 74 raise Exception("Count of flagSpecs does not match flagGenerators") 75 76 self._flagSpecs = flagSpecs 77 self._flagGenerators = flagGenerators 78 self._flagBase = flagBase 79 self.flag = 0x00000000000000000000 80 81 self._calcFlag()
82
83 - def next(self):
84 85 # Are we done? Only done if everyone is done 86 87 stop = True 88 for i in range(len(self._flagSpecs)): 89 try: 90 self._flagGenerators[i].next() 91 stop = False 92 except GeneratorCompleted: 93 pass 94 95 if stop == True: 96 raise GeneratorCompleted("Flags is done sir!") 97 98 # Otherwise figure out next flag varianet 99 self._calcFlag
100
101 - def _calcFlag(self):
102 self._flag = self._flagBase 103 for i in range(len(self._flagSpecs)): 104 self._flag |= int(self._flagGenerators[i].getValue()) << int(self._flagSpecs[i])
105
106 - def getRawValue(self):
107 return self._flag
108 109
110 -class Flags2(SimpleGenerator):
111 ''' 112 Define the layout of flags and provide a generator for each. Each flag 113 has a position, length, and generator. The Flag itself also has a total 114 length and byte order (litte or big). If values generated for each field in 115 the flag are masked such as they always fit and do not affect other fields 116 in the flag. 117 118 Example: 119 120 >>> gen = Flags2(None, 8, [ [0, 1, Bit()], [4, 1, Bit()], [6, 2, List(None, [0, 1, 2])] ]) 121 >>> print gen.getValue() 122 0 123 >>> gen.next() 124 >>> print gen.getValue() 125 81 126 >>> gen.next() 127 >>> print gen.getValue() 128 145 129 >>> gen.next() 130 >>> print gen.getValue() 131 209 132 133 ''' 134
135 - def __init__(self, group, length, flags, isLittleEndian = True):
136 ''' 137 @type group: Group 138 @param group: Group for this Generator 139 @type length: Integer 140 @type length: Length of flag field, must be 8, 16, 32, or 64. 141 @type flags: Array of Arrays 142 @param flags: Each sub-array must contain a position (zero based), 143 length (in bits), and a generator. 144 ''' 145 SimpleGenerator.__init__(self, group) 146 147 if length % 2 != 0: 148 raise Exception("Invalid length argument. Length must be multiple of 2!") 149 150 for flag in flags: 151 if flag[0] > length: 152 raise Exception("Flag position larger then length") 153 if (flag[0] + flag[1]) > length: 154 raise Exception("Flag position + flag length larger then length") 155 156 self.length = length 157 self.flags = flags
158 159 # flags needs to contain position and length 160
161 - def next(self):
162 done = True 163 164 for flag in self.flags: 165 try: 166 flag[2].next() 167 done = False 168 except GeneratorCompleted: 169 pass 170 171 if done: 172 raise GeneratorCompleted("Flags are done")
173
174 - def getRawValue(self):
175 ret = 0 176 177 for flag in self.flags: 178 mask = 0x00 << self.length - (flag[0] + flag[1]) 179 180 cnt = flag[0] + flag[1] - 1 181 for i in range(flag[1]): 182 #print "<< %d" % cnt 183 mask |= 1 << cnt 184 cnt -= 1 185 186 #print "Mask:",repr(mask) 187 flagValue = flag[2].getValue() 188 if flagValue == None or flagValue == 'None': 189 flagValue = 0 190 191 ret |= mask & (int(flagValue) << flag[0]) 192 193 return ret
194 195
196 -class Dictionary(generator.Generator):
197 ''' 198 Iterates through a collection of values stored in a file. 199 Possible uses could be to brute force passwords or try a set of 200 known bad values. 201 ''' 202 203 _fileName = None 204 _fd = None 205 _currentValue = None 206
207 - def __init__(self, group, fileName):
208 ''' 209 @type group: Group 210 @param group: Group this Generator belongs to 211 @type fileName: string 212 @param fileName: Name of file use 213 ''' 214 Generator.__init__(self) 215 self._fileName = fileName 216 self.setGroup(group)
217
218 - def getFilename(self):
219 ''' 220 Get name of file. 221 222 @rtype: string 223 @return: name of file 224 ''' 225 return self._fileName
226
227 - def setFilename(self, filename):
228 ''' 229 Set filename. 230 231 @type filename: string 232 @param filename: Filename to use 233 ''' 234 self._fileName = filename
235
236 - def next(self):
237 if self._fd == None: 238 self._fd = open(self._fileName, 'rb') 239 if self._fd == None: 240 raise Exception('Unable to open', self._fileName) 241 242 oldValue = self._currentValue 243 self._currentValue = self._fd.readline() 244 if self._currentValue == None or len(self._currentValue) == 0: 245 self._currentValue = oldValue 246 raise generator.GeneratorCompleted("Dictionary completed for file [%s]" % self._fileName) 247 248 self._currentValue = self._currentValue.rstrip("\r\n")
249
250 - def getRawValue(self):
251 if self._fd == None: 252 self._fd = open(self._fileName, 'rb') 253 if self._fd == None: 254 raise Exception('Unable to open', self._fileName) 255 256 if self._currentValue == None: 257 self._currentValue = self._fd.readline() 258 self._currentValue = self._currentValue.rstrip("\r\n") 259 260 return self._currentValue
261
262 - def reset(self):
263 self._fd = None 264 self._currentValue = None
265
266 - def unittest():
267 g = group.Group() 268 dict = Dictionary(g, 'samples/dict.txt') 269 270 try: 271 while g.next(): 272 print dict.getValue() 273 except group.GroupCompleted: 274 pass 275 276 g.reset() 277 278 try: 279 while g.next(): 280 print dict.getValue() 281 except group.GroupCompleted: 282 pass
283 unittest = staticmethod(unittest)
284 285
286 -class List(generator.Generator):
287 ''' 288 Iterates through a specified list of values. When the end of the list is 289 reached a generator.GeneratorCompleted exceoption is raised. Last item 290 will be returned until reset is called. 291 292 Example: 293 294 >>> list = List(None, ['1', '2', '3']) 295 >>> list.getValue() 296 1 297 >>> list.next() 298 >>> list.getValue() 299 2 300 >>> list.next() 301 >>> list.getValue() 302 3 303 304 ''' 305 306 _list = None 307 _curPos = 0 308
309 - def __init__(self, group, list = None):
310 ''' 311 @type group: Group 312 @param group: Group this Generator belongs to 313 @type list: list 314 @param list: List of values to iterate through 315 ''' 316 Generator.__init__(self) 317 self.setGroup(group) 318 self._list = list 319 self._curPos = 0 320 321 if self._list == None: 322 self._list = []
323
324 - def reset(self):
325 self._curPos = 0
326
327 - def next(self):
328 self._curPos += 1 329 if self._curPos >= len(self._list): 330 self._curPos -= 1 331 raise generator.GeneratorCompleted("List")
332
333 - def getRawValue(self):
334 return str(self._list[self._curPos])
335
336 - def getList(self):
337 ''' 338 Get current list of values. 339 340 @rtype: list 341 @return: Current list of values 342 ''' 343 return self._list
344
345 - def setList(self, list):
346 ''' 347 Set list of values. 348 349 @type list: list 350 @param list: List of values 351 ''' 352 self._list = list 353 354 if self._list == None: 355 self._list = []
356
357 - def unittest():
358 g = group.Group() 359 list = List(g, ['A', 'B', 'C', 'D']) 360 361 if list.getValue() != 'A': 362 raise Exception("List unittest failed 1") 363 g.next() 364 if list.getValue() != 'B': 365 raise Exception("List unittest failed 2") 366 g.next() 367 if list.getValue() != 'C': 368 raise Exception("List unittest failed 3") 369 g.next() 370 if list.getValue() != 'D': 371 raise Exception("List unittest failed 4") 372 373 try: 374 g.next() 375 raise Exception("List unittest failed 5") 376 except group.GroupCompleted: 377 pass 378 379 try: 380 g.next() 381 raise Exception("List unittest failed 5") 382 except group.GroupCompleted: 383 pass 384 385 if list.getValue() != 'D': 386 raise Exception("List unittest failed 6") 387 388 list = List(g, [1, 2, 3, 4, 5]) 389 390 try: 391 while g.next(): 392 print list.getValue() 393 except group.GroupCompleted: 394 pass
395 unittest = staticmethod(unittest)
396 397
398 -class BinaryList(List):
399 ''' 400 Iterates through a specified list of binary values. When the end 401 of the list is reached a generator.GeneratorCompleted exceoption 402 is raised. 403 ''' 404 405 _packString = 'b' 406
407 - def __init__(self, group, list = None, packString = None):
408 ''' 409 @type group: Group 410 @param group: Group this Generator belongs to 411 @type list: list 412 @param list: List of values to iterate through 413 @type packString: string 414 @param packString: Defaults to 'b' 415 ''' 416 Generator.__init__(self) 417 List.__init__(self, group, list) 418 self._packString = packString
419
420 - def getRawValue(self):
421 out = self._list[self._curPos] 422 if self._packString != None: 423 return struct.pack(self._packString, out) 424 425 return out
426
427 - def unittest():
428 g = group.Group() 429 list = BinaryList(g, [0, 1, 2, 3], '>B') 430 431 try: 432 while g.next(): 433 print list.getValue() 434 except group.GroupCompleted: 435 pass
436 unittest = staticmethod(unittest)
437 438
439 -class _ArrayList(generator.Generator):
440 '''Internal helper class''' 441
442 - def __init__(self, listOfLists):
443 self._listOfLists = listOfLists 444 self._pos = 0 445 self._block 446 self._block = Block(self._listOfLists[self._pos])
447
448 - def getRawValue(self):
449 return self._block
450
451 - def next(self):
452 if (self._pos + 1) >= len(self._listOfLists): 453 raise generator.GeneratorCompleted("ArrayList") 454 455 self._pos += 1 456 self._block = Block(self._listOfLists[self._pos])
457
458 - def reset(self):
459 self._pos = 0
460 461 import random 462
463 -class GeneratorChoice(generator.Generator):
464 ''' 465 Will choose from a list of Generators. See use cases below for 466 further description of operation: 467 468 Case 1 - minOccurs and maxOccurs are 1. In this case a single 469 generator is selected N times. 470 Case 2 - minOccurs is 1 and maxOccurs is 100. In this case 471 N sets of random items are chosen. 472 Case 3 - minOccurs is 0 and maxOccurs is 1. You will always 473 get 1 case were 0 items are chosen and 1 case of 474 other items chosen 475 476 Currently N == 10. 477 478 ''' 479
480 - def __init__(self, group, minOccurs, maxOccurs, groups, list, n = 10, name = None):
481 ''' 482 @type group: Group 483 @param group: Group this Generator belongs to 484 @type list: list 485 @param list: List of Generators to choose frome 486 @type name: string 487 @type name: Name of generator 488 ''' 489 490 generator.Generator.__init__(self) 491 492 self.n = n 493 self.minOccurs = minOccurs 494 self.maxOccurs = maxOccurs 495 self._curPos = 0 496 self.setName(name) 497 498 if group != None: 499 self.setGroup(group) 500 501 self._groups = groups 502 self._list = list 503 504 if self._list == None or self._groups == None: 505 raise Exception("groups and list cannot be None.") 506 507 if len(self._list) != len(self._groups): 508 raise Exception("groups and list must have same number of items!") 509 510 if len(self._list) < self.maxOccurs: 511 self.maxOccurs = len(self._list) 512 513 # handle case 1 - minOccurs == 1 and maxOccurs == 1 514 if self.minOccurs == 1 and self.maxOccurs == 1: 515 516 theGroups = [] 517 theItems = [] 518 519 # select a single generator 520 if len(self._list) <= self.n: 521 sample = xrange(len(self._list)) 522 else: 523 sample = random.sample(xrange(len(self._list)), self.n) 524 525 for n in sample: 526 theGroups.append(self._groups[n]) 527 theItems.append(self._list[n]) 528 529 self.generator = GeneratorList2(None, theGroups, theItems) 530 531 # handle case 3 -- minOccurs == 0, maxOccurs == 1 532 elif self.minOccurs == 0 and self.maxOccurs == 1: 533 theGroups = [] 534 theItems = [] 535 536 if self.maxOccurs - self.minOccurs <= self.n: 537 sample = xrange(self.maxOccurs - self.minOccurs) 538 539 else: 540 sample = random.sample(xrange(len(self._list)), self.n) 541 542 for n in sample: 543 theGroups.append(self._groups[n]) 544 theItems.append(self._list[n]) 545 546 self.generator = GeneratorList(None, [ 547 Static(''), 548 GeneratorList2(None, theGroups, theItems) 549 ]) 550 551 # handle case 2 - minOccurs == 1, maxOccurs == 100 552 else: 553 554 theGeneratorLists = [] 555 sample = None 556 557 if self.maxOccurs - self.minOccurs <= self.n: 558 sample = xrange(self.maxOccurs - self.minOccurs) 559 560 else: 561 sample = random.sample(xrange(self.minOccurs, self.maxOccurs), self.n) 562 563 for n in sample: 564 565 theGroups = [] 566 theItems = [] 567 568 subSample = random.sample(xrange(len(self._list)), n) 569 subSample.sort() 570 571 # remove dups 572 old = -1 573 newSample = [] 574 for x in subSample: 575 if x != old: 576 old = x 577 newSample.append(x) 578 579 subSample = newSample 580 for x in subSample: 581 theGroups.append(self._groups[x]) 582 theItems.append(self._list[x]) 583 584 theGeneratorLists.append(Block3(GroupSequence(theGroups), theItems)) 585 586 self.generator = GeneratorList(None, theGeneratorLists)
587
588 - def next(self):
589 self.generator.next()
590
591 - def reset(self):
592 self.generator.reset()
593
594 - def getRawValue(self):
595 return self.generator.getValue()
596 597 598
599 -class GeneratorList(generator.Generator):
600 ''' 601 Iterates through a specified list of generators. When the end of the list is 602 reached a generator.GeneratorCompleted exceoption is raised. 603 604 NOTE: Generators are incremented by this object so DON'T SET A GROUP ON THEM! 605 606 NOTE: We only increment to next generator in list when the GeneratorCompleted 607 exception has been thrown from current generator. This allows one todo kewl 608 things like have 2 static generators, then a dictionary, then a repeater. 609 610 Example: 611 612 >>> gen = GeneratorList(None, [ 613 ... Static('1'), 614 ... Static('2'), 615 ... Static('3') 616 ... ]) 617 >>> print gen.getValue() 618 1 619 >>> gen.next() 620 >>> print gen.getValue() 621 2 622 >>> gen.next() 623 >>> print gen.getValue() 624 3 625 >>> try: 626 ... gen.next() # Will raise GeneraterCompleted exception 627 ... except: 628 ... pass 629 >>> print gen.getValue() # notice we get last value again. 630 3 631 632 Example: 633 634 >>> gen = GeneratorList(None, [ 635 ... Repeater(None, Static('Peach'), 1, 2), 636 ... Static('Hello World') 637 ... ]) 638 >>> print gen.getValue() 639 Peach 640 >>> gen.next() 641 >>> print gen.getValue() 642 PeachPeach 643 >>> gen.next() 644 >>> print gen.getValue() 645 Hello World 646 >>> try: 647 ... gen.next() # Will raise GeneraterCompleted exception 648 ... except: 649 ... pass 650 >>> print gen.getValue() # notice we get last value again. 651 Hello World 652 653 Bad Example, group set on Generator in list: 654 655 >>> group = Group() 656 >>> gen = GeneratorList(group, [ 657 ... Repeater(group, Static('Peach'), 1, 2), 658 ... Static('Hello World') 659 ... ]) 660 >>> print gen.getValue() 661 Peach 662 >>> group.next() 663 >>> print gen.getValue() 664 Hello World 665 >>> try: 666 ... gen.next() # Will raise GeneraterCompleted exception 667 ... except: 668 ... pass 669 >>> print gen.getValue() # notice we get last value again. 670 Hello World 671 672 ''' 673
674 - def __init__(self, group, list, name = None):
675 ''' 676 @type group: Group 677 @param group: Group this Generator belongs to 678 @type list: list 679 @param list: List of Generators to iterate through 680 @type name: string 681 @type name: Name of generator 682 ''' 683 684 Generator.__init__(self) 685 686 self._curPos = 0 687 688 self.setName(name) 689 690 if group != None: 691 self.setGroup(group) 692 693 self._list = list 694 695 if self._list == None: 696 self._list = []
697
698 - def next(self):
699 try: 700 self._list[self._curPos].next() 701 except generator.GeneratorCompleted: 702 #print "Peach.dictionary.GeneratorList2.next(): caught GeneratorCompleted" 703 self._curPos += 1 704 705 if self._curPos >= len(self._list): 706 self._curPos -= 1 707 #print "Peach.dictionary.GeneratorList2.next(): throwing complete exceptions" 708 raise generator.GeneratorCompleted("Peach.dictionary.GeneratorList")
709
710 - def reset(self):
711 self._curPos = 0 712 713 for i in self._list: 714 i.reset()
715
716 - def getRawValue(self):
717 # Use .getValue to make sure we 718 # pick up any transformers 719 value = self._list[self._curPos].getValue() 720 if value is None: 721 print "Peach.dictionary.GeneratorList.getRawValue(): getValue() was None" 722 print "Peach.dictionary.GeneratorList.getRawValue(): Name is %s" % self._list[self._curPos].getName() 723 print "Peach.dictionary.GeneratorList.getRawValue(): Type is %s" % self._list[self._curPos] 724 725 return value
726
727 - def getList(self):
728 ''' 729 Get list of Generators. 730 731 @rtype: list 732 @return: list of Generators 733 ''' 734 return self._list
735
736 - def setList(self, list):
737 ''' 738 Set list of Generators. 739 740 @type list: list 741 @param list: List of Generators 742 ''' 743 self._list = list 744 745 if self._list == None: 746 self._list = []
747
748 - def unittest():
749 g = group.Group() 750 list = GeneratorList(g, [static.Static('A'), static.Static('B'), static.Static('C')]) 751 752 try: 753 while g.next(): 754 print list.getValue() 755 except group.GroupCompleted: 756 pass
757 unittest = staticmethod(unittest)
758 759
760 -class GeneratorList2(GeneratorList):
761 ''' 762 Iterates through a specified list of generators (different group control). 763 When the end of the list is reached a generator.GeneratorCompleted exceoption 764 is raised. 765 766 This generator differs from GeneratorList by allowing one group to 767 drive the rounds, but associating different sub groups to each generator. 768 When the master group is incremented the group for the current generator is 769 also incremented. This allows more complex control of how generators 770 create data. 771 772 NOTE: We only increment to next generator in list when the GeneratorCompleted 773 exception has been thrown from current generator. This allows one todo kewl 774 things like have 2 static generators, then a dictionary, then a repeater. 775 776 Example: 777 778 >>> groupA = Group() 779 >>> groupBA = Group() 780 >>> groupBB = Group() 781 >>> groupB = GroupForeachDo(groupBA, groupBB) 782 >>> 783 >>> gen = GeneratorList2(None, [groupA, groupB], [ 784 ... Repeater(groupA, Static('A'), 1, 1, 3), 785 ... Block([ 786 ... List(groupBA, [':', '\\', '/']), 787 ... Repeater(groupBB, Static('B'), 1, 1, 3) 788 ... ]) 789 ... ]) 790 >>> 791 >>> print gen.getValue() 792 A 793 >>> gen.next() 794 >>> gen.getValue() 795 AA 796 >>> gen.next() 797 >>> gen.getValue() 798 AAA 799 >>> gen.next() 800 >>> gen.getValue() 801 :B 802 >>> gen.next() 803 >>> gen.getValue() 804 :BB 805 >>> gen.next() 806 >>> gen.getValue() 807 :BBB 808 >>> gen.next() 809 >>> gen.getValue() 810 \B 811 >>> gen.next() 812 >>> gen.getValue() 813 \BB 814 >>> gen.next() 815 >>> gen.getValue() 816 \BBB 817 >>> gen.next() 818 >>> gen.getValue() 819 /B 820 >>> gen.next() 821 >>> gen.getValue() 822 /BB 823 >>> gen.next() 824 >>> gen.getValue() 825 /BBB 826 827 @see: L{GeneratorList} 828 ''' 829 830 #_groupList = None 831
832 - def __init__(self, group, groupList = None, list = None, name = None):
833 ''' 834 @type group: Group 835 @param group: Group this Generator belongs to 836 @type groupList: list 837 @param groupList: List of Groups to use on generators 838 @type list: list 839 @param list: List of Generators to iterate through 840 @type name: String 841 @param name: [optional] Name for this Generator. Used for debugging. 842 ''' 843 Generator.__init__(self) 844 self.setGroup(group) 845 self.generators = self._list = list 846 self.groups = self._groupList = groupList 847 self.setName(name) 848 self._curPos = 0 849 850 if self._list == None: 851 self._list = [] 852 if self._groupList == None: 853 self._groupList = [] 854 855 self.reset()
856
857 - def next(self):
858 try: 859 self._groupList[self._curPos].next() 860 #print "GeneratorList2.next(): ..." 861 except group.GroupCompleted: 862 #print "GeneratorList2.next(): Next pos [%d]" % self._curPos 863 #print "GeneratorList2.next(): %d items in our list" % len(self._list) 864 self._curPos += 1 865 if self._curPos < len(self._list): 866 self._groupList[self._curPos].reset() 867 #except: 868 # print "GeneratorList2.next(): Caught some other exception" 869 870 if self._curPos >= len(self._list): 871 self._curPos -= 1 872 #print "%s: GeneratorList2.next() Completed" % name 873 raise generator.GeneratorCompleted("Peach.dictionary.GeneratorList2")
874
875 - def setGroups(self, list):
876 ''' 877 Set list of Groups. 878 879 @type list: list 880 @param list: List of Groups 881 ''' 882 self._groupList = list 883 884 if self._groupList == None: 885 self._groupList = []
886
887 - def reset(self):
888 self._curPos = 0 889 890 for i in self._list: 891 i.reset() 892 893 for i in self._groupList: 894 i.reset()
895
896 - def unittest():
897 g = group.Group() 898 list = GeneratorList2(g, [static.Static('A'), static.Static('B'), static.Static('C')]) 899 900 try: 901 while g.next(): 902 print list.getValue() 903 except group.GroupCompleted: 904 pass
905 unittest = staticmethod(unittest)
906 907
908 -class GeneratorListGroupMaster(GeneratorList2):
909 ''' 910 Provides a mechanism to create in effect a group of GeneratorList2's that 911 will progress and increment together drivin by the master of the group. This 912 Generator is the Group Master generator and controls the slaves of the 913 group. 914 915 This generator comes in handy when you have two bits of data that are 916 logically linked but in separate places. An example would be a length of 917 data being generated. Both values are parameters and generated separaetly