miron / NeonCore

Terminal based Cyberpunk Tabletop RPG with Nostr as database and openAI API compatible commands
3 stars 1 forks source link

without CommandManager #76

Open miron opened 1 year ago

miron commented 1 year ago

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 https://github.com/miron/NeonCore/issues/10#issuecomment-1436111938