Skip to content

Rewrite turtle's undo handling to fix various issues #158563

Description

@StanFromIreland

There are currently three bugs in turtle's undo handling.

  1. 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.

  2. 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.

  3. 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.

  4. 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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

stdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or error

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions