pythongeneratorgenshi

Genshi and Python Generators (yield)


How do I create/call a python generator in Genshi? Is that even possible?

For example, (and no i'm not looking for an alternate solution to this problem, of which there are many, including enumerate on the for each, etc):

 <?python
  """ a bunch of other code ... """
  def bg_color_gen():
    """ Alternate background color every call """
    while 1:
      yield "#FFFFFF"
      yield "#EBEBEB"
  ?>

And then calling this function:

  <fo:block background-color="${bg_color_gen()}">First entry</fo:block>
  <fo:block background-color="${bg_color_gen()}">Second entry</fo:block>
  <fo:block background-color="${bg_color_gen()}">Third entry</fo:block>

This has nothing to do with my < fo:block >, which you could replace with < div >. It is not an FO question but a Genshi question. I'm guessing Genshi doesn't recognize the 'yield' and runs 'while 1' ad-infinitum?

Also, I do realize I could use a global to keep track of a counter, and then call

 counter++
 if counter%yieldCount==0: return "#FFFFFFF"
 elif counter%yieldCount==1: return "#EBEBEB"

But this is not a generator and gets ugly very quickly!

Clarification: Another way to ask this question: how would you code

def fib():
    a,b = 0,1
    while True:
        yield a
        b = a+b
        yield b
        a = a+b

Which would then be called in the sentence "The first number is $fib(), the second is $fib(), the third is $fib(), and so on."

================================================

Updated full solution based on accepted answer:

<?python
def fib_generator():
    a,b = 0,1
    while True:
        yield a
        b = a+b
        yield b
        a = a+b
fib = fib_generator()
?>


The first number is ${next(fib)}, 
the second is ${next(fib)},
the third is ${next(fib)}, and so on.

Solution

  • Without knowing the structure of your content, I would suggest the following:

    <fo:block py:for="i, entry in entries"
              background-color="${'#FFFFFF' if i % 2 else '#EBEBEB'}">
      ${entry}
    </fo:block>
    

    However if you truly want to use a generator then you could just evaluate using Python's native next()

    <py:with vars="color=bg_color_gen();">
      <fo:block background-color="${next(color)}">
    </py:with>