How to undo a python script

Select polygonal edges, run:

def run():
    listEdges = pm.ls(sl = 1, flatten=True)
    pm.polyDuplicateEdge(listEdges, splitType=0, offset=0.1)

run()

Then run:

pm.undo()

And get the error: # Error: line 1: RuntimeError: file C:\pmcmds.py line 133: Undo is temporarily unavailable. Try exiting the current tool.

While if you press CTR + Z in a viewport it will undo properly. What I am doing wrong?

I need to undo my script cos I wish to make it interactive, so the user can adjust parameters with a HUD slider (offset for example). Each time user release slider I undo the previous execution and run again with a new value.

Does pm.polyDuplicateEdge put you in a tool context? Because it sounds like something is, given the error message when running pm.undo.

Well… I activate the select tool, select edges, run script. The select tool remains after running script.
If I execute a script with undo, it will undo.

def run():
    listEdges = pm.ls(sl = 1, flatten=True)
    pm.polyDuplicateEdge(listEdges, splitType=0, offset=0.1)

run()
pm.undo()

But its not working step by step.

But may be my idea of interactivity implementation is wrong? Are there other options to achieve same functionality?

Im unable to recreate the issue you’re having, but you might try using the UndoChunk context manager as described in Practical Programming with Python:

class UndoChunk(object):
    # an undo context manager
    def  __enter__(self):
        pm.undoInfo(openChunk=True)
    def __exit__(self, *_):
        pm.undoInfo(closeChunk=True)

with UndoChunk():
    run()

The chunk context manager is a great way to roll a bunch of operations into a single chunk, so that it can be treated as a single operation. But I don’t think that is what you’re asking for here right?

Also, when running your code above, I get no issues.
Might be worth double checking your undo settings, something might be wonky there.

Thanks, R.White!
The same solution I found posted here by Robert. That does not work as well.

Also, when running your code above, I get no issues.

You select an edge, run the first part of the code, then run pm.undo() and it rolls back???
Cos for me it’s working only if I run all (with pm.undo) at once…

By undo settings you mean if its turned on or not? I checked, it is.

I’m curious. Is this something that needs to be handled with pymel? I can’t seem to have any problems using Maya’s standard python interpreter and the undo queue.

In this particular case, pm.undo is really no different than cmds.undo, the pymel one has a better docstring, but is probably a tiny bit slower due to being a wrapper around cmds.undo.
Where pymel really differs, is when any function returns a node, as pymel returns a class representing that node instead of just a string. undo doesn’t return a node, it just executes an action, so no appreciable difference.

Thanks. Well. It’s just that I’ve heard about it before, that you need to enclose your code to be able to undo it, but I guess I’ve never understood why since any of my scripts “undos” fine.
So I wondered if this was something particularly for Pymel, but is it really a Python thing?

Nope, its a Maya thing.
If you want to be able to undo a whole chunk of code at once, you’d build something like @WeatherMan’s example up above.

Otherwise you’re just calling the undo command, same as when you hit Z.

Otherwise you’re off in the deep end of creating a custom tool using the API and having to implement doIt, undoIt, and redoIt. Which then the regular undo / redo commands take advantage of.

1 Like

For me the problem still exists. I check on another computer — its works fine… I delete prefs, no difference. Settings/preferences > Undo: turned ON

Have no Idea what to check next to find the reason why my Maya does not want to do it!

I get that “Try exiting the current tool.” error sometimes when I accidentally drag a node in the outliner, and the operation seems to get stuck until I change to a manipulator and back again.

I’m wondering if you have any installed plugin or tool which is causing that sort of context switch.

I can select an edge, run your code, and run pm.undo() without issue.

(Also, in default Maya hotkeys, you only have to hit z to undo. Ctrl is optional.)

How can I find if I have any plugin which causing context switch?

No idea. That’s just the fuzziest clue I could think of. I see that error about once a week, but almost always from dragging things with my Wacom in the outliner.