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
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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
43
44
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
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
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
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
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
141
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
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
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
179 '''
180 Clear list of generators.
181 '''
182 self._generators = []
183
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
194
207
208
209
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
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
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
259
260 self._inGetRawValue = True
261 self._block.getValue()
262 self._inGetRawValue = False
263
264 return self._block.occurs
265
267 '''
268 Get block object we act on.
269
270 @rtype: Block
271 @return: current Block
272 '''
273 return self._block
274
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
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
320
322 for i in self._generators:
323 try:
324 i.reset()
325 except AttributeError:
326 raise Exception("Block2: Attribute Error! %s" % i)
327
328
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
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
357
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
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
400 '''
401 Return data, passed through a transformer if set.
402 '''
403 out = self.getRawValue()
404
405 if self._transformer != None and self._inGetRawValue == 0:
406 out = self._transformer.encode(out)
407
408
409 return out
410
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
421
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
430 '''
431 Get block object we act on.
432
433 @rtype: Block
434 @return: current Block
435 '''
436 return self._block
437
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
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
485
486 for gen in self._generators:
487 try:
488 gen.reset()
489 except:
490 pass
491
508
510 newArray = []
511
512 for a in array:
513 newArray.append(a)
514
515 return newArray
516
518 for i in array:
519 if i == item:
520 return True
521
522 return False
523
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
570 self._resetGenerators()
571
574
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
611
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
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
657
658 if genOccurs == None:
659
660 if self.maxOccurs - self.minOccurs < 255:
661
662 self.genOccurs = Incrementor(None, self.minOccurs, 1, None, self.maxOccurs)
663
664 else:
665
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
680 self.occurs = int(self.genOccurs.getValue())
681
683 self.genOccurs = genOccurs
684 self.occurs = int(self.genOccurs.getValue())
685
687 self.genOccurs.next()
688 self.occurs = int(self.genOccurs.getValue())
689
691 self.genOccurs.reset()
692 self.occurs = int(self.genOccurs.getValue())
693
696
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
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
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
734 '''
735 Clear list of generators.
736 '''
737 self._block.clear()
738
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
749
755 return self._block.__setitem(key, value)
762
763
764
765