1
2 '''
3 Default included Group implementations.
4
5 @author: Michael Eddington
6 @version: $Id: Peach.group-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, traceback
38 from Peach import generator
39
40
41
43 '''
44 Groups allow for performing a C{next()} call on a specific set of
45 Generators allowing for more complex Fuzzing setups. This default group
46 object will iterate an infinit amount of times.
47
48 Group objects implement the iterator protocol.
49 '''
50
51 _name = None
52 _generators = []
53 _identity = ""
54
56 '''
57 Create a new Group object.
58
59 @type name: string
60 @param name: Name of Group object. Not currently used.
61 '''
62 self._name = name
63 self._generators = []
64
65
66
67 self._identity = traceback.format_stack()
68
70 '''
71 Get current name of Group. Not currently used.
72
73 @rtype: string
74 @return: name of Group
75 '''
76 return self._name
78 '''
79 Set name of Group. Not currently used.
80
81 @type name: string
82 @param name: Name of Group
83 '''
84 self._name = name
85
87 '''
88 Add Generator to Group. This should almost never be called
89 directly. Generators will call this when you set there Group.
90 However, you can do some crazy stuff by adding a Generator into
91 multiple Groups so they iterate themselves in strange ways.
92
93 @type gen: Generator
94 @param gen: Generator to add
95 '''
96 self._generators.append(gen)
97
99 '''
100 Add Generators to Group. This should almost never be called
101 directly. Generators will call this when you set there Group.
102 However, you can do some crazy stuff by adding a Generator into
103 multiple Groups so they iterate themselves in strange ways.
104
105 @type gens: Array of Generators
106 @param gens: Generatorsto add
107 '''
108 for g in gens:
109 self._generators.append(g)
110
112 '''
113 Remove Generator from Group.
114
115 @type gen: Generator
116 @param gen: Generator to remove
117 '''
118 self._generators.remove(gen)
119
121 '''
122 Returns list of all generators in Group. This is a reference
123 to our internal list so any changes will also affect the Group.
124
125 @rtype: Array
126 @return: Returns Array of strings
127 '''
128 return self._generators
129
132
134 '''
135 Iterate all Generators to next value.
136
137 From Python docs on next():
138
139 I{The intention of the protocol is that once an iterator's next() method
140 raises StopIteration, it will continue to do so on subsequent calls.
141 Implementations that do not obey this property are deemed broken. (This
142 constraint was added in Python 2.3; in Python 2.2, various iterators are
143 broken according to this rule.)}
144
145 For Groups, please use the GroupCompleted exception instead of
146 StopIteration (its a subclass).
147 '''
148
149
150
151
152 if len(self._generators) < 1:
153 print "Identity of Group: ", self._identity
154 raise Exception("Error: Group does not contain any generators. This is probably not a good thing.")
155
156 done = 1
157
158 for i in range(len(self._generators)):
159 try:
160 self._generators[i].next()
161 done = 0
162 except generator.GeneratorCompleted:
163 pass
164
165 if done == 1:
166 raise GroupCompleted()
167
169 '''
170 Resets all Generators to there initial state.
171 '''
172 for i in self._generators:
173 i.reset()
174
175
177 '''
178 Raised when group has completed all iterations. This exception is a
179 sub class of StopIteration.
180 '''
181 pass
182
183
185 '''
186 A sequence of groups. Each group will be iterated until they are
187 completed in sequence.
188
189 This is also a container type and can be used as such to gain
190 access to the contained groups.
191
192 HINT: If groups param is an integer it will create an array of
193 Group() objects of that length that can be accessed using
194 the array specifier groupSequence[x].
195 '''
196
197 - def __init__(self, groups = None, name = None):
198 '''
199 Create a GroupSequence object.
200
201 @type groups: list
202 @param groups: Optional list of Groups to use
203 '''
204
205 self._slackerCount = 0
206
207 if name is None:
208 self._name = ""
209 else:
210 self._name = name
211
212 self._generators = []
213
214
215 if str(type(groups)) == "<type 'int'>":
216 self._groups = []
217 for i in range(groups):
218 self._groups.append(Group())
219
220 elif groups != None:
221 self._groups = groups
222
223 else:
224 self._groups = []
225 self._position = 0
226 self._count = 1
227
229 '''
230 This is a function for slackers that allows access to the next group
231 without having to specify an index.
232
233 @rtype: Group
234 @return: Returns the next Group in the list
235 '''
236 if self._slackerCount >= len(self._groups):
237 raise Exception("GroupSequence: getNextGroup() ran past end of array.")
238 self._slackerCount += 1
239 return self._groups[self._slackerCount -1]
240
242 '''
243 Will add a new Group to sequence of groups and then return that group.
244
245 @type newGroup: Group
246 @param newGroup: [optional] Group to append, or if not given add Group()
247 @rtype: Group
248 @return: Returns appended Group
249 '''
250 if newGroup == None:
251 newGroup = Group()
252
253 self._groups.append(newGroup)
254 return newGroup
255
256 - def append(self, group = None):
257 '''
258 Append a Group.
259
260 @type group: Group
261 @param group: Group to append
262 @rtype: Group
263 @return: Returns appended Group
264 '''
265 return self.addNewGroup(group)
266
268 '''
269 Remove a Group.
270
271 @type group: Group
272 @param group: Group to remove
273 '''
274 self._groups.remove(group)
275
290
295
296
297
298
304 return self._groups.__setitem(key, value)
311
312 import inspect, pyclbr, random
313
315 '''
316 This group will take a GroupSequence and perform random mutations
317 on how generators are incremented. This group understands that a
318 GroupSequence can have other GroupSequences in it.
319 '''
320
329
335
337
338 print "len: %d" % len(self.groups)
339 for group in self.groups:
340 group.reset()
341
343 '''Pick some groups to play with
344 '''
345
346
347
348
349
350
351 type = random.randint(0, 1)
352
353 if type == 0:
354
355 groupsDo = []
356 picks = random.sample(xrange(self.count), random.randint(0, self.count-1))
357 for pick in picks:
358 groupsDo.append(self.groups[pick])
359
360 self.currentGroup = GroupSequence(groupsDo, "GroupForever")
361
362 elif type == 1:
363
364 groupEach = groupFor = self.groups[ random.randint(0, self.count-1) ]
365 groupsDo = []
366
367 picks = random.sample(xrange(self.count), random.randint(0, self.count-1))
368 for pick in picks:
369 groupsDo.append(self.groups[pick])
370
371 try:
372 groupsDo.remove(groupEach)
373 except:
374 pass
375
376 groupDo = GroupSequence(groupsDo, "GroupForever")
377
378 self.currentGroup = GroupForeachDo(groupEach, groupDo)
379
380 else:
381 raise Exception("GroupForever._pickStuff(): Should not be here!!")
382
383 self.isCompleted = False
384
386
387 if hasattr(groupSequence, 'next') and hasattr(groupSequence, '__iter__'):
388 groups = []
389
390 for group in groupSequence:
391 if group == None:
392 continue
393
394 groups.append(group)
395
396 if hasattr(group, 'next') and hasattr(group, '__iter__'):
397 for g in self._findAllGroups(group):
398 if g == None:
399 continue
400
401 groups.append(g)
402
403 return groups
404
405 if hasattr(groupSequence, "getForeachGroup"):
406 return [group.getForeachGroup(), group.getDoGroup()]
407
408 return []
409
417
421
422
424 '''
425 Group object with a fixed number of iterations.
426 '''
427
428 _max = 0
429 _current = 0
430
432 '''
433 Create GroupFixed object.
434
435 @type maxIterations: number
436 @param maxIterations: Maximum number of iterations.
437 '''
438 self._max = maxIterations
439 Group.__init__(self)
440
442 '''
443 Get the maximum iterations to perform.
444
445 @rtype: number
446 @return the maximum iterations
447 '''
448 return self._max
450 '''
451 Set the maximum iterations to perform.
452
453 @type maxIterations: number
454 @param maxIterations: Maximum number of iterations.
455 '''
456 self._max = maxIterations
457
467
468
470 '''
471 Foreach iteration of group A do group B
472 '''
473
474
475
476
477 - def __init__(self, groupA, groupB, verbose = True, name = ""):
478 '''
479 Foreach interation of group A do group B
480
481 @type groupA: Group
482 @param groupA: The for each of group
483 @type groupB: Group
484 @param groupB: The Do group
485 @type verbose: Boolean
486 @param verbose: [optional] Control printing of group completed message, enabled by default.
487 '''
488 self._generators = []
489 self._groupA = groupA
490 self._groupB = groupB
491 self._count = 1
492 self._name = name
493 self._verbose = verbose
494 self._isCompleted = False
495
497
498 if self._isCompleted:
499 raise GroupCompleted("We are done")
500
501 try:
502 self._groupB.next()
503 self._count += 1
504 except GroupCompleted:
505 if self._verbose:
506 print "%s: GroupForeachDo.GroupCompleted -- [%d]" % (self._name, self._count)
507
508 self._count = 1
509 self._groupB.reset()
510
511 try:
512 self._groupA.next()
513 except GroupCompleted:
514 self._isCompleted = True
515
517 self._groupA.reset()
518 self._groupB.reset()
519 self._count = 1
520 self._isCompleted = False
521
523 '''
524 Returns the For each group
525 '''
526 return self._groupA
527
529 '''
530 Returns the Do group
531 '''
532 return self._groupB
533
534
535
536
537