LumaPictures / pymel

Python in Maya Done Right
Other
478 stars 130 forks source link

First call of pm.menu('test', exists=True) results in a ui.Menu(res) call, where res = cmds.menu('test', exists=True) #471

Open chelloiaco opened 10 months ago

chelloiaco commented 10 months ago

Related to issue pymel Maya 2024 #467

The first call of pm.menu containing an "exists" arg is inconsistent with Maya's cmds. It executes the creation of a ui.Menu using the result of the cmds query as the name arg.

On a fresh Maya, the following behavior is noted when checking for a non-existent "test" menu : pymel (first call - unexpected behavior) :

import pymel.core as pm
pm.menu("test", ex=True)
# Result: ui.Menu('AttributeEditor|MainAttributeEditorLayout|formLayout1|AEmenuBarLayout|False') #

pymel (second call - expected behavior) :

pm.menu("another_test", ex=True)
# Result: False #

The issue happens when on windows.py:1856, the if not kwargs.get('query', kwargs.get('q', False)) passes and allows the execution of _factories.maybeConvert(res, uitypes.Menu) where, in this test, res = False. Note here that we lost the original kwarg ex=True on this call, since we're only using res.

This then eventually calls PyUI.__new__ on uitypes.py:407 with the following args:

name=False <class 'bool'>, # NOT the default None
create=False <class 'bool'>, # default
kwargs={} # default

Which, in turn, passes the uitypes.PyUI._isBeingCreated check on uitypes.py:475, since name=False which, as far as Python cares, is True when not name (uitypes.py:482). This eventually culminates into a cmds.menu(False), which sadly is allowed (yes, using a bool) and creates a menu with the name "False", like so:

cmds.menu(False)
# Result: 'AttributeEditor|MainAttributeEditorLayout|formLayout1|AEmenuBarLayout|False' # 

Subsequent calls probably get caught in a try except in the cmds wrappers, since it will try to create the "False" menu again, which then prevents the menu function's cmds call at line windows.py:476 from returning properly and doesn't create additional ones.

GoodAsNew commented 2 months ago

I think this is related. I have this issue that a condition passes even tho the value is False when first time executing. If i just do if False and True:, then it works as expected. But when I check if the value returned by pm.window(name, exists = True), it passes the condition. This happens only with PyMel. I recently installed Maya 2024 and latest PyMel. I don't remember what the PyMel version is that worked previously.

If I use condition if windowExists: it passes the condition even tho it shouldn't. But if i use if windowExists == True: It works as expected. if windowExists and True: also passes the condition with False value. If I do just if False and True: it works as expected and wont pass the condition.

Test code:

import pymel.core as pm

def test1():
    windowNam = "window123" #non existing window
    windowExists = pm.window(windowNam, exists = True) #Checks if the window exists. should always be false, because the window is never made.
    if windowExists: #This condition passes even though the value is False.
        print(windowExists) #Prints False, even though it shouldn't even pass the condition.
        pm.deleteUI(windowNam) #Tries to delete the window but since it doesn't exist, it throws an error.
test1()
False   #<-- prints False
Error: deleteUI: Object 'window123' not found.
Traceback (most recent call last):
File "", line 9, in 
File "", line 8, in test1
File "C:\Users\(user)\AppData\Roaming\Python\Python310\site-packages\pymel\internal\pmcmds.py", line 217, in deleteUI_wrapped
res = new_cmd(*new_args, **new_kwargs)
RuntimeError: deleteUI: Object 'window123' not found.`