[PATCH] merge3 fails with python2.3
John A Meinel
john at arbash-meinel.com
Wed Jul 6 02:10:17 BST 2005
Martin Pool wrote:
>On 5 Jul 2005, John A Meinel <john at arbash-meinel.com> wrote:
>
>
>
>>I found the bug. It turns out that the way iterables work with python2.3
>>is different than with python2.4
>>It seems that doing:
>>
>>aiter = iter(SequenceMatcher(None, self.base, self.a).get_matching_blocks())
>>
>>In python2.4 these evaluate to False when they run out of entries, so:
>>
>>while aiter:
>> aiter.next()
>>
>>Will loop properly. But in python2.3, they do not evaluate to False,
>>instead raising a StopIteration exception. So it basically becomes:
>>
>>while True:
>> aiter.next() # This raises a StopIteration exception, which won't be
>>caught by the while
>>
>>
>
>It needs to also guard the .next() that gets the first value.
>
>Rather than have a big try block I think i'll just change them to
>regular C-like indexed loops. (Catching an exception that could come
>from anywhere inside makes me uncomfortable.)
>
>
>
>>Is there a reason to do "while aiter and biter:"? I assume because you
>>only want to call 'next()' on one of them, not both like 'zip()' would do.
>>
>>
>
>That's right, we want to progress through both until one is finished,
>but only one of them steps forward on each loop. Maybe there's a
>better way?
>
>I'm not sure if the extensive use of generators in here is really
>sensible. They are a very nice way to separate out code that might be
>entwined in other languages. I wonder how much they cost compared to
>building a list? I suppose a bit more.
>
>
>
I think use generators wherever you can, but since you *already* have a
list, just use it. Is it possible for get_matching_blocks to return and
empty list? [] Which means that you could use something like:
alst = SequenceMatcher(None, self.base, self.a).get_matching_blocks()
blst = SequenceMatcher(None, self.base, self.b).get_matching_blocks()
if alst:
abase, amatch, alen = alst.pop(0)
if blst:
bbase, bmatch, blen = blst.pop(0)
while alst and blst:
...
if (abase + alen) < (bbase + blen):
abase, amatch, alen = alst.pop(0)
else:
bbase, bmatch, blen = blst.pop(0)
Then you don't need to keep a counter, because an empty list
automatically is counted as False.
You could also just use 2 stop iterations traps:
try:
abase, amatch, alen = aiter.next()
bbase, bmatch, blen = biter.next()
except StopIteration:
aiter = False
biter = False
while aiter and biter:
...
try:
if (abase + alen) < (bbase + blen):
abase, amatch, alen = aiter.next()
else:
bbase, bmatch, blen = biter.next()
except StopIteration:
break
That way you don't have a giant try/catch block.
I think the internal iteration is great. It makes everything lazy and
easy to work with at the top level. Just don't go around creating iter()
objects that you don't need, since their implementation changed between
2.3 and 2.4
John
=:->
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 253 bytes
Desc: OpenPGP digital signature
Url : https://lists.ubuntu.com/archives/bazaar/attachments/20050705/d9299ac0/attachment.pgp
More information about the bazaar
mailing list