On Oct 5, 1:46 pm, Jason Baker <jason.ba...@ttu.edu> wrote: > Grammar nazi alert: > > "To stop this generator, you need to call it's .stop() method. The > wrapper could do this"
It's a sketch - rather than a proposal for immediate merge - hence the request for feedback. Pedantry at this stage does not fall into the category of helpful feedback. (It makes people, me included, think twice about posting a sketch something for feedback on the concepts) > Moving on to subjects with a little bit more substance, suppose I have > a generator function Foo that I wrap using one of these decorators. > What exactly will happen if I call Foo? Like all decorators, Foo then no longer binds to the original version of Foo. In this case, rather than returning a generator, it returns a component. I suspected this: Pipeline( follow('/var/log/system.log'), grep(None, ".*pants.*"), printer(None) ).run() would be relatively obvious. After all, Pipeline links and activates components, not generators, therefore the decorated generator functions return components that use the generator functions for their logic, rather than the generator functions directly. In this case, the 2 decorators are used to use the logic embodied by the generator to control a component. This opens up a variety of possibilities. > This isn't entirely clear to me by tracing the sourcecode. This is why I split into two portions, at least when I reposted. Specifically, one part shows a working illustration of how this would be used: http://code.google.com/p/kamaelia/source/browse/trunk/Sketches/MPS/AxonDecorators/example.py ... and I noted that the names "blockingProducer" & "TransformerGenComponent" are non ideal - but then it is inside / Sketches... The other was an initial implementation - which is primarily proof of concept that this can even be done - which can be found here: http://code.google.com/p/kamaelia/source/browse/trunk/Sketches/MPS/AxonDecorators/decorators.py blockingProducer is a fairly traditional/simple decorator. For anyone who've written lots of decorators, there's a handful of issues with that bare approach (cf the Michele Simionato's decorator module for more details), but it's fine as a basic proof of concept. The decorator TransformerGenComponent is slightly odd in that it returns a class rather than a function which reuses/configures a function. This is primarily because that was the more obvious approach at the time. I'll be refactoring it to match the blocking producer format. Out of these two files though, the most important one is not the implementation, but the idea & API as used in the example file: http://code.google.com/p/kamaelia/source/browse/trunk/Sketches/MPS/AxonDecorators/example.py For example, in an earlier thread, I posted this syntax/decorator illustration: @GeneratorComponent(Inboxes = ["inbox", "control"], Outboxes = ["outbox", "signal"]) def Tracer(self): while 1: for msg in self.Inbox("inbox"): print self.tag, str(msg) self.send(msg, "outbox") self.pause() yield 1 However, this looked like one step too far towards voodoo for Steve & IIRC John agreed. In retrospect, I agree, though it could be a convenient shortcut. Furthermore a suggested alternative syntax like this: # Becomes a subsumed generator by one in the wrapper that handles control and # moving yielded values to the outbox. Looks like a standard simple generator. @GeneratorPipelineComponent def Tracer(inbox): for msg in inbox: print "> ", str(msg) yield msg Has some unresolvable problems without massively complicating GeneratorPipelineComponent, or without reformulating that example like this: @TransformerGenComponent def Tracer(inbox): while 1: for msg in inbox(): print "> ", str(msg) yield msg yield My question was fundamentally this: does the following code look clear enough to follow /roughly/ what's going on at a glance, or is it too unclear. @blockingProducer def follow(fname): f = file(fname) f.seek(0,2) # go to the end while True: l = f.readline() if not l: # no data time.sleep(.1) else: yield l @TransformerGenComponent def grep(lines, pattern): regex = re.compile(pattern) while 1: for l in lines(): if regex.search(l): yield l yield @TransformerGenComponent def printer(lines): while 1: for line in lines(): sys.stdout.write(line) sys.stdout.flush() yield Pipeline( follow('/var/log/system.log'), grep(None, ".*pants.*"), printer(None) ).run() If the above is clear & readable - ie you read this as it follows a system file, greps for a pattern and prints it, that's good. If it isn't the implementation is irrelevant. If it is clear, the goalposts change to making the implementation nicer, maintainable and ideally unsurprising. I've had positive comments elsewhere, so my impression based on those is that this *may* be a nice idea. *ho hum* Michael. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "kamaelia" group. To post to this group, send email to kamaelia@googlegroups.com To unsubscribe from this group, send email to kamaelia+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/kamaelia?hl=en -~----------~----~----~----~------~----~------~--~---