Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

without CommandManager #76

Open
miron opened this issue Mar 14, 2023 · 0 comments
Open

without CommandManager #76

miron opened this issue Mar 14, 2023 · 0 comments

Comments

@miron
Copy link
Owner

miron commented Mar 14, 2023

Solution without using CommandManager, maybe better and more maintanable when do_* commands are registered in the ActionManager instead of the respective classes. greet i.e. could still call another class

def precmd(self, line):
    # Add some methods based on condition
    if some_condition:
        setattr(self, 'do_bye', self.bye)
        setattr(self, 'do_greet', self.greet)
    return line

def postcmd(self, stop, line):
    # Remove some methods based on condition
    if not some_condition:
        delattr(self, 'do_bye')
        delattr(self, 'do_greet')
    return stop

def bye(self, arg):
    # Do something here
    pass

def greet(self, arg):
    # Do something here
    pass

Another Idea:

import types
import cmd

class MyCmd(cmd.Cmd):
    pass

def add_do_methods(obj):
    if some_condition:
        def do_bye(self, arg):
            # Do something here
            pass

        def do_greet(self, arg):
            # Do something here
            pass

        do_methods = {'do_bye': do_bye, 'do_greet': do_greet}

        new_class_dict = dict(obj.__class__.__dict__)
        new_class_dict.update(do_methods)
        new_class = types.new_class(obj.__class__.__name__, (obj.__class__,), {}, lambda ns: ns.update(new_class_dict))

        obj.__class__ = new_class

def remove_do_methods(obj):
    if not some_condition:
        new_class = types.new_class(obj.__class__.__name__, (obj.__class__,), {})
        new_class_dict = dict(new_class.__dict__)

        for method_name in ['do_bye', 'do_greet']:
            if method_name in new_class_dict:
                del new_class_dict[method_name]

        new_class = types.new_class(obj.__class__.__name__, (obj.__class__,), {}, lambda ns: ns.update(new_class_dict))
        obj.__class__ = new_class

# Create an instance of MyCmd
my_cmd = MyCmd()

# Add the do_* methods
add_do_methods(my_cmd)

# Call the methods
my_cmd.do_bye('arg')
my_cmd.do_greet('arg')

# Remove the do_* methods
remove_do_methods(my_cmd)

In this example, the add_do_methods() function adds the do_bye() and do_greet() methods to the class of the specified object if the some_condition is true. It does this by creating a new dictionary that includes the existing class dictionary as well as the new methods, and then creating a new class that derives from the existing class with the updated dictionary. It then sets the class of the specified object to the new class.

The remove_do_methods() function does the opposite, removing the do_bye() and do_greet() methods from the class of the specified object if the some_condition is false. It does this by creating a new dictionary that includes the existing class dictionary with the methods removed, and then creating a new class that derives from the existing class with the updated dictionary. It then sets the class of the specified object to the new class.

By using dynamic class creation and setting the class of the object to the new class, you can add and remove methods from an existing class at runtime.

Originally posted by @miron in #10 (comment)

@miron miron changed the title Solution without using CommandManager, maybe better and more maintanable when do_* commands are registered in the ActionManager instead of the respective classes. greet i.e. could still call another class without CommandManager Mar 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant