[py-dev] py.log and multiple keywords

Grig Gheorghiu grig at gheorghiu.net
Fri Jun 17 19:00:21 CEST 2005


--- Grig Gheorghiu <grig at gheorghiu.net> wrote:

> Holger and others interested in this topic,
> 
> I was thinking that in many situations it would be helpful to be able
> to specify multiple keywords that would each point to a different
> consumer and that would be all 'kick in' on a call to the producer.
> Basically, I'd want this test to pass:
> 
>     def test_multiple_keywords(self):
>         log = py.log.Producer('console logfile db')
>         py.log.setconsumer('console', py.log.STDOUT)
>         logfile = tempdir.join('mylogfile.out')
>         py.log.setconsumer('logfile', open(str(logfile), 'w',
> buffering=1))
>         dbfile = tempdir.join('mydbfile.out')
>         py.log.setconsumer('db', open(str(dbfile), 'w', buffering=1))
>         
>         res, out, err = callcapture(log, "hello")
>         assert out.strip() == "[console:logfile:db] hello" 
> 
>         assert logfile.readlines() == ['[console:logfile:db]
> hello\n']
>         assert dbfile.readlines() == ['[console:logfile:db] hello\n']
> 
> Right now the last 2 assert statements fail, because _getconsumer
> returns as soon as it finds a match for the first keyword, so only
> the
> 'console' consumer gets a chance to consume the message.
> 
> I'm thinking that the _getconsumer function could be a generator that
> yields a message-processing function for each keyword it finds in its
> registry. What do you think?
> 
> Grig

Here's how I modified __call__ and _getconsumer in producer.py in order
to achieve the goal stated above. Of course, the old semantics doesn't
apply at this point, but all the current tests still pass.

    def __call__(self, *args):
        for func in self._getconsumer(self.keywords):
            if func is not None: 
                func(self.Message(self.keywords, args))
   
    def _getconsumer(self, keywords):
        found_consumer = False
        for keyword in keywords:
            consumer = self.keywords2consumer.get((keyword,))
            if consumer:
                found_consumer = True
            yield consumer
        if not found_consumer:
            yield self.keywords2consumer.get('default',
default_consumer)

Now this test passes (on Unix, because on Windows there's a problem
with opening files in buffering mode):

    def test_multiple_keywords(self):
        log = py.log.Producer('console logfile db email')
        py.log.setconsumer('console', py.log.STDOUT)
        logfile = tempdir.join('mylogfile.out')
        py.log.setconsumer('logfile', open(str(logfile), 'w',
buffering=1))
        dbfile = tempdir.join('mydbfile.out')
        py.log.setconsumer('db', open(str(dbfile), 'w', buffering=1))

        res, out, err = callcapture(log, "hello")
        assert out.strip() == "[console:logfile:db:email] hello" 
        assert logfile.readlines() == ['[console:logfile:db:email]
hello\n']
        assert dbfile.readlines() == ['[console:logfile:db:email] hello\n']


More information about the py-dev mailing list