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

Source Code for Module Peach.Generators.block

  1   
  2  ''' 
  3  Contains implementation of a Block generator and BlockSize generator. 
  4   
  5  @author: Michael Eddington 
  6  @version: $Id: Peach.Generators.block-pysrc.html 1138 2008-08-16 19:39:03Z meddingt $ 
  7  ''' 
  8   
  9  # 
 10  # Copyright (c) 2005-2007 Michael Eddington 
 11  # Copyright (c) 2004-2005 IOActive Inc. 
 12  # 
 13  # Permission is hereby granted, free of charge, to any person obtaining a copy  
 14  # of this software and associated documentation files (the "Software"), to deal 
 15  # in the Software without restriction, including without limitation the rights  
 16  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell  
 17  # copies of the Software, and to permit persons to whom the Software is  
 18  # furnished to do so, subject to the following conditions: 
 19  # 
 20  # The above copyright notice and this permission notice shall be included in     
 21  # all copies or substantial portions of the Software. 
 22  # 
 23  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
 24  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
 25  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
 26  # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
 27  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 28  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
 29  # SOFTWARE. 
 30  # 
 31   
 32  # Authors: 
 33  #   Michael Eddington (mike@phed.org) 
 34   
 35  # $Id: Peach.Generators.block-pysrc.html 1138 2008-08-16 19:39:03Z meddingt $ 
 36   
 37  import sys 
 38  from Peach import generator, group 
 39  from Peach.Generators.repeater          import * 
 40  from Peach.Generators.incrementor import Incrementor 
 41  import random 
 42  #, static 
 43   
 44  #__all__ = ["Block", "BlockSize", "Block2"] 
 45   
46 -class Block(generator.Generator):
47 ''' 48 Block is a set of Generators in a specific order who's values are combined 49 into a block of data. The L{BlockSize} generator can be used to output 50 the size of the block or other generators. 51 52 Example: 53 54 >>> gen = Block([ 55 ... Static('Hello'), 56 ... Static(' '), 57 ... Static('World') 58 ... ]) 59 >>> print gen.getValue() 60 Hello World 61 62 @note: This type of block will not call .next() on the generators it 63 contains. See L{Block2} or L{Block3} for that. 64 65 @note: Do not use with L{DictionaryList} generator. Will cause 66 infinitlooping since the .next() is never called on sub generators. 67 68 @see: L{MultiBlock}, L{Block2}, L{Block3}, L{BlockSize}, L{MultiBlockCount} 69 ''' 70
71 - def __init__(self, generators = None):
72 ''' 73 @type generators: List 74 @param generators: List of generators 75 @type alignment: Integer 76 @param alignment: How to align block. Just like with a struct. 77 ''' 78 79 generator.Generator.__init__(self) 80 81 self._inGetValue = 0 82 self._inRawValue = 1 83 self._generators = None 84 85 if generators == None: 86 self._generators = [] 87 else: 88 self._generators = generators
89
90 - def next(self):
91 ''' 92 Note: We arn't going to next on any of the sub 93 generators. This is left to the group or whatever todo. 94 ''' 95 pass
96
97 - def reset(self):
98 ''' 99 Even though we don't propogate .next calls we should 100 reset things. 101 ''' 102 for g in self._generators: 103 g.reset()
104
105 - def getValue(self):
106 self._inGetValue = 1 107 ret = '' 108 109 for i in range(len(self._generators)): 110 try: 111 ret += str(self._generators[i].getValue()) 112 except TypeError, e: 113 print "\nPeach.block.Block: Caught type error, here is identification information" 114 print e 115 print "self._generators[i].getName(): %s" % self._generators[i].getName() 116 if self._generators[i].identity() != None: 117 print "self._generators[i].identity: (%s) =====" % self._generators[i] 118 for p in self._generators[i].identity(): 119 print p 120 print "===============" 121 else: 122 print "self._generators[i].identity: None!" 123 124 raise e 125 126 if self._transformer != None: 127 return self._transformer.encode(ret) 128 129 self._inGetValue = 0 130 return ret
131
132 - def getRawValue(self):
133 self._inRawValue = 1 134 ret = '' 135 136 for i in range(len(self._generators)): 137 ret += self._generators[i].getRawValue() 138 139 self._inRawValue = 0 140 return ret
141
142 - def getSize(self):
143 ''' 144 Size of generator after all transformations 145 146 @rtype: number 147 @return: size of data generated 148 ''' 149 return len(str(self.getValue()))
150
151 - def append(self, generator):
152 ''' 153 Append a generator to end of list. 154 155 @type generator: Generator 156 @param generator: Generator to append 157 ''' 158 self._generators.append(generator)
159
160 - def insert(self, pos, generator):
161 ''' 162 Insert generator into list 163 164 @type generator: Generator 165 @param generator: Generator to insert 166 ''' 167 self._generators.insert(pos, generator)
168
169 - def remove(self, generator):
170 ''' 171 Remove a generator from list 172 173 @type generator: Generator 174 @param generator: Generator to remove 175 ''' 176 self._generators.remove(generator)
177
178 - def clear(self):
179 ''' 180 Clear list of generators. 181 ''' 182 self._generators = []
183
184 - def setGenerators(self, generators):
185 ''' 186 Set array of generators. 187 188 @type generators: list 189 @param generators: list of Generator objects 190 ''' 191 self._generators = generators
192 193 # Container emulation methods ############################ 194
195 - def __len__(self):
196 return self._generators.__len__()
197 - def __getitem__(self, key):
198 return self._generators.__getitem__(key)
199 - def __setitem__(self, key, value):
200 return self._generators.__setitem(key, value)
201 - def __delitem__(self, key):
202 return self._generators.__delitem__(key)
203 - def __iter__(self):
204 return self._generators.__iter__()
205 - def __contains__(self, item):
206 return self._generators.__contains__(item)
207 208 209
210 -class MultiBlockCount(generator.Generator):
211 ''' 212 Generates the number of occurances of a MultiBlock generator. 213 214 Example: 215 216 >>> block = MultiBlock([ Static('12345') ], 0, 100, Static(1)) 217 >>> blockCount = MultiBlockCount( block ) 218 >>> print blockCount.getValue() 219 1 220 221 @see: L{MultiBlock} 222 ''' 223
224 - def __init__(self, block, defaultOccurs = 1):
225 ''' 226 @type block: MultiBlock 227 @param block: MultiBlock to get count of 228 @type defaultSize: number 229 @param defaultSize: To avoid recursion this is our occurs (optional) 230 ''' 231 generator.Generator.__init__(self) 232 self.setBlock(block) 233 self._defaultOccurs = defaultOccurs 234 self._insideSelf = False 235 self._inGetRawValue = False
236
237 - def getValue(self):
238 ''' 239 Return data, passed through a transformer if set. 240 ''' 241 out = self.getRawValue() 242 if self._transformer != None and self._inGetRawValue == 0: 243 out = self._transformer.encode(out) 244 245 return out
246
247 - def getRawValue(self):
248 ''' 249 Returns size of block as string. 250 251 @rtype: string 252 @return: size of specified Block 253 ''' 254 255 if self._inGetRawValue or self._block == None: 256 return str(self._defaultOccurs) 257 258 # Call getValue to make sure MultiBlock 259 # has set occurs to correct value. 260 self._inGetRawValue = True 261 self._block.getValue() 262 self._inGetRawValue = False 263 264 return self._block.occurs
265
266 - def getBlock(self):
267 ''' 268 Get block object we act on. 269 270 @rtype: Block 271 @return: current Block 272 ''' 273 return self._block
274
275 - def setBlock(self, block):
276 ''' 277 Set block we act on. 278 279 @type block: Block 280 @param block: Block to set. 281 ''' 282 self._block = block 283 return self
284
285 -class Block2(Block):
286 ''' 287 Specialized type of L{Block} that will call next() on each generator. 288 289 Use this type of block with L{GeneratorList}s. 290 291 Example: 292 293 >>> gen = GeneratorList(None, [ 294 ... Block2([ 295 ... Static('Hello'), 296 ... Static(' '), 297 ... Repeater(None, Static('World'), 1, 2) 298 ... ]) 299 ... ]) 300 >>> print gen.getValue() 301 Hello World 302 >>> gen.next() 303 >>> print gen.getValue() 304 Hello WorldWorld 305 306 @see: L{Block}, L{Block3}, L{BlockSize} 307 ''' 308
309 - def next(self):
310 exit = 0 311 for i in self._generators: 312 try: 313 i.next() 314 exit = 2 315 except: 316 if exit < 2: 317 exit = 1 318 if exit == 1: 319 raise generator.GeneratorCompleted("Block2")
320
321 - def reset(self):
322 for i in self._generators: 323 try: 324 i.reset() 325 except AttributeError: 326 raise Exception("Block2: Attribute Error! %s" % i)
327 328
329 -class Block3(Block):
330 ''' 331 A Block that takes a group to perform .next() on. The BlockSize generator 332 can be used to output the block size someplace. 333 334 This is a specialized version of Block. This version will 335 call next() the provided Group. This was added to make complex 336 sub-blocks work properly. 337 ''' 338
339 - def __init__(self, group, generators):
340 ''' 341 @type group: Group 342 @param group: Group to perform .next() on 343 @type generators: List 344 @param generators: List of generators 345 ''' 346 347 generator.Generator.__init__(self) 348 349 self._nextGroup = group 350 self._generators = generators
351
352 - def next(self):
353 try: 354 self._nextGroup.next() 355 except group.GroupCompleted: 356 raise generator.GeneratorCompleted("Block3")
357
358 - def reset(self):
359 self._nextGroup.reset() 360 361 for i in self._generators: 362 try: 363 i.reset() 364 except AttributeError: 365 raise Exception("Block3: Attribute Error! %s" % i)
366 367
368 -class BlockSize(generator.Generator):
369 ''' 370 Will generate size of Block or another Generator. BlockSize can 371 can detect recursive calls and provides an optional defaultSize 372 that can be set for such cases. 373 374 Example: 375 376 >>> block = Block([ Static('12345') ]) 377 >>> blockSize = BlockSize( block ) 378 >>> print blockSize.getValue() 379 5 380 381 ''' 382 383 _inGetRawValue = 0 384
385 - def __init__(self, block, defaultSize = 1):
386 ''' 387 @type block: Block 388 @param block: Block to get size of 389 @type defaultSize: number 390 @param defaultSize: To avoid recursion this is how big we are 391 (optional) 392 ''' 393 generator.Generator.__init__(self) 394 self._block = None 395 self.setBlock(block) 396 self._defaultSize = defaultSize 397 self._insideSelf = False
398
399 - def getValue(self):
400 ''' 401 Return data, passed through a transformer if set. 402 ''' 403 out = self.getRawValue() 404 #print "block.BlockSize::getValue(): out = %s" % out 405 if self._transformer != None and self._inGetRawValue == 0: 406 out = self._transformer.encode(out) 407 408 #print "block.BlockSize::getValue(): out = %s" % out 409 return out
410
411 - def getRawValue(self):
412 ''' 413 Returns size of block as string. 414 415 @rtype: string 416 @return: size of specified Block 417 ''' 418 419 if self._inGetRawValue == 1: 420 # Avoid recursion and return a string 421 # that is defaultSize in length 422 return str(self._defaultSize) 423 424 self._inGetRawValue = 1 425 out = str(len(str(self._block.getValue()))) 426 self._inGetRawValue = 0 427 return out
428
429 - def getBlock(self):
430 ''' 431 Get block object we act on. 432 433 @rtype: Block 434 @return: current Block 435 ''' 436 return self._block
437
438 - def setBlock(self, block):
439 ''' 440 Set block we act on. 441 442 @type block: Block 443 @param block: Block to set. 444 ''' 445 self._block = block 446 return self
447 448 449 import random
450 -class BlockRandomizer(generator.SimpleGenerator):
451 ''' 452 This block takes a number of sub-blocks or generators 453 that it will include or not include in variouse combinations 454 and orders. 455 ''' 456
457 - def __init__(self, group, okGenerators, notOkGenerators, limit = 1024, seed = 10312335):
458 ''' 459 @type group: Group 460 @param group: Group to perform .next() on 461 @type okGenerators: Array of Generator objects 462 @param okGenerators: The expected data blocks to mix and match 463 @type notOkGenerators: Array of Generator objects 464 @param notOkGenerators: The unexpected data blocks to mix and match 465 @type limit: Number 466 @param limit: [optional] Limit the number of possible test variations. Defaults to 1024. 467 @type seed: Number 468 @param seed: [optional] A random number generator is used and can be seeded. Defaults to 10312335. 469 ''' 470 471 generator.SimpleGenerator.__init__(self, group) 472 473 self._generators = okGenerators 474 self._okGenerators = okGenerators 475 self._notOkGenerators = notOkGenerators 476 self._limit = limit 477 self._seed = seed 478 self._count = 0 479 self._testSet = 1 480 481 random.seed(self._seed)
482 483
484 - def _resetGenerators(self):
485 # Reset all the completed generators 486 for gen in self._generators: 487 try: 488 gen.reset() 489 except: 490 pass
491
492 - def next(self):
493 494 if self._limit > -1 and self._count >= self._limit: 495 raise generator.GeneratorCompleted("BlockRandomizer hit its max!") 496 497 done = True 498 for gen in self._generators: 499 try: 500 gen.next() 501 done = False 502 except: 503 pass 504 505 if done: 506 self._count += 1 507 self.nextTest()
508
509 - def copyArray(self, array):
510 newArray = [] 511 512 for a in array: 513 newArray.append(a) 514 515 return newArray
516
517 - def inArray(self, array, item):
518 for i in array: 519 if i == item: 520 return True 521 522 return False
523
524 - def nextTest(self):
525 526 test = random.randint(1, 4) 527 notOk = random.randint(0, 1) 528 529 genOk = self.copyArray(self._okGenerators) 530 genNotOk = self.copyArray(self._notOkGenerators) 531 532 if test == 1: 533 random.shuffle(genOk) 534 self._generators = genOk 535 536 elif test == 2: 537 sample = random.sample(genOk, random.randint(1, len(genOk))) 538 gens = [] 539 540 for g in genOk: 541 542 if self.inArray(sample, g): 543 for i in range(random.randint(1, 20)): 544 g.reset() 545 gens.append(g) 546 547 else: 548 gens.append(g) 549 550 self._generators = gens 551 552 elif test == 3: 553 sample1 = random.sample(genOk, random.randint(1, len(genOk)/2)) 554 sample2 = random.sample(genNotOk, random.randint(1, len(genNotOk)/2)) 555 556 gens = [] 557 for g in sample1: 558 gens.append(g) 559 for g in sample2: 560 gens.append(g) 561 562 random.shuffle(gens) 563 564 self._generators = gens 565 566 elif test == 4: 567 self._generators = random.sample(genOk, random.randint(1, len(genOk)/2)) 568 569 # Reset all our generators 570 self._resetGenerators()
571
572 - def reset(self):
573 self._generators = self._okGenerators
574
575 - def getValue(self):
576 self._inGetValue = 1 577 ret = '' 578 579 for i in range(len(self._generators)): 580 try: 581 ret += str(self._generators[i].getValue()) 582 except TypeError, e: 583 print "\nPeach.block.Block: Caught type error, here is identification information" 584 print e 585 print "self._generators[i].getName(): %s" % self._generators[i].getName() 586 if self._generators[i].identity() != None: 587 print "self._generators[i].identity: (%s) =====" % self._generators[i] 588 for p in self._generators[i].identity(): 589 print p 590 print "===============" 591 else: 592 print "self._generators[i].identity: None!" 593 594 raise e 595 596 if self._transformer != None: 597 return self._transformer.encode(ret) 598 599 self._inGetValue = 0 600 return ret
601
602 - def getRawValue(self):
603 self._inRawValue = 1 604 ret = '' 605 606 for i in range(len(self._generators)): 607 ret += self._generators[i].getRawValue() 608 609 self._inRawValue = 0 610 return ret
611
612 - def getSize(self):
613 ''' 614 Size of generator after all transformations 615 616 @rtype: number 617 @return: size of data generated 618 ''' 619 return len(self.getValue())
620 621 622 from Peach.Generators.dictionary import List 623
624 -class MultiBlock(generator.Generator):
625 ''' 626 Specialized type of L{Block} that will duplicate itself a certain/random number of times. 627 628 @see: L{Block}, L{MultiBlockCount} 629 ''' 630 631 _seed = 1192315309984 632
633 - def __init__(self, group, generators, minOccurs = 1, maxOccurs = 1, genOccurs = None):
634 ''' 635 @type generators: List 636 @param generators: List of Generator objects 637 @type minOccurs: Number 638 @param minOccurs: Minimum number of times this block can occur, defaults to 1 639 @type maxOccurs: Number 640 @param maxOccurs: Maximum number of times this block can occur, defaults to 1 641 @type genOccurs: Generator 642 @param genOccurs: [Optional] Generator that produces number of occurances 643 ''' 644 generator.Generator.__init__(self) 645 self.setGroup(group) 646 647 self._block = Block(generators) 648 self.minOccurs = minOccurs 649 self.maxOccurs = maxOccurs 650 651 if self.minOccurs == 0: 652 self.defaultOccurs = 1 653 else: 654 self.defaultOccurs = self.minOccurs 655 656 # setup a generator to produce our occurs values 657 # or accept a generator for this 658 if genOccurs == None: 659 660 if self.maxOccurs - self.minOccurs < 255: 661 # Produce all occurs 662 self.genOccurs = Incrementor(None, self.minOccurs, 1, None, self.maxOccurs) 663 664 else: 665 # Produce a random sampling of numbers 666 step = (self.maxOccurs - self.minOccurs) / 255 667 self.genOccurs = List(None, range(self.minOccurs, self.maxOccurs, step)) 668 self.genOccurs.getList().insert(0, self.defaultOccurs) 669 self.genOccurs.getList().append(self.maxOccurs) 670 671 if self.minOccurs > 0: 672 self.genOccurs.getList().append(self.minOccurs-1) 673 674 self.genOccurs.getList().append(self.maxOccurs+1) 675 676 else: 677 self.genOccurs = genOccurs 678 679 # Setup our first occurs 680 self.occurs = int(self.genOccurs.getValue())
681
682 - def setGenOccurs(self, genOccurs):
683 self.genOccurs = genOccurs 684 self.occurs = int(self.genOccurs.getValue())
685
686 - def next(self):
687 self.genOccurs.next() 688 self.occurs = int(self.genOccurs.getValue())
689
690 - def reset(self):
691 self.genOccurs.reset() 692 self.occurs = int(self.genOccurs.getValue())
693
694 - def getRawValue(self):
695 return self._block.getRawValue() * self.occurs
696
697 - def getSize(self):
698 ''' 699 Size of generator after all transformations 700 701 @rtype: number 702 @return: size of data generated 703 ''' 704 return len(self.getValue())
705
706 - def append(self, generator):
707 ''' 708 Append a generator to end of list. 709 710 @type generator: Generator 711 @param generator: Generator to append 712 ''' 713 self._block.append(generator)
714
715 - def insert(self, pos, generator):
716 ''' 717 Insert generator into list 718 719 @type generator: Generator 720 @param generator: Generator to insert 721 ''' 722 self._block.insert(pos, generator)
723
724 - def remove(self, generator):
725 ''' 726 Remove a generator from list 727 728 @type generator: Generator 729 @param generator: Generator to remove 730 ''' 731 self._block.remove(generator)
732
733 - def clear(self):
734 ''' 735 Clear list of generators. 736 ''' 737 self._block.clear()
738
739 - def setGenerators(self, generators):
740 ''' 741 Set array of generators. 742 743 @type generators: list 744 @param generators: list of Generator objects 745 ''' 746 self._block.setGenerators(generators)
747 748 # Container emulation methods ############################ 749
750 - def __len__(self):
751 return self._block.__len__()
752 - def __getitem__(self, key):
753 return self._block.__getitem__(key)
754 - def __setitem__(self, key, value):
755 return self._block.__setitem(key, value)
756 - def __delitem__(self, key):
757 return self._block.__delitem__(key)
758 - def __iter__(self):
759 return self._block.__iter__()
760 - def __contains__(self, item):
761 return self._block.__contains__(item)
762 763 764 # end 765