saleguas/context_menu

Flexibility of the target function's signature?

Opened this issue · 0 comments

Hello,
I just discovered your library and I already find it very very practical. I have a program which can already load files through a pop-up (PyQt5's QFileDialog) and would like to add the option to load them via context menu too.

My question is: can the function's signature be more flexible?
As of now, it seems that only f(filenames, params) and f(filenames=None, params=None) are supported. f(**kwargs) would be very handy as we could still recover the filenames and params while allowing extra parameters, and f(self, ...) would be amazing too for when your target function is actually a method.

I have prepared test cases for you.
The code below will add four context menu actions for files. Only actions 1 and 2 actually work, while 3 and 4 (the kwargs and class variants) don't. Uncomment the code in the context manager and run the code again to remove those context menu actions.

Thank you in advance!

from contextlib import contextmanager

@contextmanager
def add_context_menu_action(action_name, function):
    """Add a context menu action only for the duration of the encompassed scope.

       args:
       -----
       :action_name: (str) the label of the action button.
       :function: the function to call on action button click. Because of the
                  context-menu library requirements, this function must have
                  a `function(filenames, params)` signature. No *args or **kwargs.

       See also:
       -----
       https://github.com/saleguas/context_menu
       https://pypi.org/project/context-menu/"""

    # Creates a direct context menu entry.
    kwargs = dict(name=action_name, type="FILES")
    fc = menus.FastCommand(**kwargs, python=function)
    fc.compile()
#    yield
#    try:
#        menus.removeMenu(**kwargs)
#    except FileNotFoundError: # Prevents an error if the function could not be located.
#        pass



def _TEST1(filenames, params):

    with open("ZE_TEST 1.txt", "w") as file:
        file.write(f"filenames: {filenames}\n")
        file.write(f"params: {params}\n")
        file.write("*"*15)



def _TEST2(filenames=None, params=None):

    with open("ZE_TEST 2.txt", "w") as file:
        file.write(f"filenames: {filenames}\n")
        file.write(f"params: {params}\n")
        file.write("*"*15)



def _TEST3(**kwargs):

    filenames, params = (kwargs[key] for key in ("filenames", "params"))
    with open("ZE_TEST 3.txt", "w") as file:
        file.write(f"filenames: {filenames}\n")
        file.write(f"params: {params}\n")
        file.write("*"*15)



class MethodTester:

    def __init__(self):
        pass

    def _TEST4(self, filenames, params):
        with open("ZE_TEST 4.txt", "w") as file:
            file.write(f"filenames: {filenames}\n")
            file.write(f"params: {params}\n")
            file.write("*"*15)



if __name__ == "__main__":

    x = MethodTester()
    for n in (1, 2, 3, 4):
        name = f"ZE_TEST FastCommand {n}"
        function = {1: _TEST1,
                    2: _TEST2,
                    3: _TEST3,
                    4: x._TEST4}[n]
        with add_context_menu_action(name, function):
            pass