There are currently three bugs in turtle's undo handling.
-
stamp() fails when the undo buffer is disabled
import turtle
t = turtle.Turtle()
t.setundobuffer(None)
t.stamp() # AttributeError: 'NoneType' object has no attribute 'push'
clearstamp(), clear() and reset() fail the same way if a stamp exists when the buffer is disabled.
-
teleport() is not recorded in the undo buffer
import turtle
t = turtle.Turtle()
t.forward(50)
t.teleport(0, 100)
t.undo()
print(t.pos()) # (0.00,100.00), expected (50.00,0.00)
t.undo()
t.undo() # also prints "undogoto: HALLO-DA-STIMMT-WAS-NICHT!" ...?
Only the pen changes made by teleport() are undone, never the move itself, so undoing earlier moves starts from the wrong position.
-
An exception in write(), circle() or dot() corrupts later undo steps
import turtle
t = turtle.Turtle()
try:
t.write("hi", align="middle") # KeyError
except KeyError:
pass
t.forward(10)
t.forward(10)
t.undo()
print(t.pos()) # (0.00,0.00), expected (10.00,0.00)
These methods set undobuffer.cumulate = True and only reset it on success, so after an error every later action is merged into a single undo step.
-
https://github.com/python/cpython/pull/158564/changes#r4159905046 This has to be addressed separately, as a fix can't be backported, since it would alter the number of entries in the buffer.
I propose adding a private context manager that circle(), dot(), write() and teleport() can use to group their actions into one undo step, so an exception can no longer leave the undo buffer merging every later action, and for teleport() to records its move so a single undo() reverts it. Also we need to guard stamp(), clearstamp(), clear() and reset() against a disabled undo buffer.
Linked PRs
There are currently three bugs in
turtle's undo handling.stamp()fails when the undo buffer is disabledclearstamp(),clear()andreset()fail the same way if a stamp exists when the buffer is disabled.teleport()is not recorded in the undo bufferOnly the pen changes made by
teleport()are undone, never the move itself, so undoing earlier moves starts from the wrong position.An exception in
write(),circle()ordot()corrupts later undo stepsThese methods set
undobuffer.cumulate = Trueand only reset it on success, so after an error every later action is merged into a single undo step.https://github.com/python/cpython/pull/158564/changes#r4159905046 This has to be addressed separately, as a fix can't be backported, since it would alter the number of entries in the buffer.
I propose adding a private context manager that
circle(),dot(),write()andteleport()can use to group their actions into one undo step, so an exception can no longer leave the undo buffer merging every later action, and forteleport()to records its move so a singleundo()reverts it. Also we need to guardstamp(),clearstamp(),clear()andreset()against a disabled undo buffer.Linked PRs
turtle's undo handling #158564turtle's undo handling (GH-158564) #158609turtle's undo handling (GH-158564) #158610