vendredi 27 novembre 2020

Python — Init class reflectively

I am creating a commands system in Python. I have module vkcommands that has a class that processes commands from chat (this is a chat-bot), and inside it, I also have class VKCommand with attributes like name, usage, min_rank, etc. Then I have module vkcmds with submodules that implement these commands:

...
vkcommands.py
vkcmds
    |- __init__.py  # empty
    |- add_group.py
    |- another_cmd.py
    |- ...

Implementations of commands (e.g. add_group) look like this:

import ranks
import vkcommands
from vkcommands import VKCommand


class AddGroup(VKCommand):
    def __init__(self, kristy):
        VKCommand.__init__(self, kristy,
                           label='create',
                           # ... (other attributes)
                           min_rank=ranks.Rank.USER)

    def execute(self, chat, peer, sender, args=None, attachments=None):
        # implementation (called from vkcommands.py)

When a user sends a message in the chat, the command manager analyzes it and looks through the registered commands list to see if this is an ordinary message or a bot command. Currently I register all commands in the commands list manually like this:

class VKCommandsManager:
    def __init__(self, kristy):
        from vkcmds import (
            add_group,
            next_class
        )

        self.kristy = kristy
        self.commands = (
            add_group.AddGroup(kristy),
            next_class.NextClass(kristy)
        )

Now I would like all commands to be registered automatically using reflections instead. In Java, I'd iterate over all classes in my commands package, reflectively getConstructor of each, call it to retrieve the VKCommand object, and add it to the commands list.

How can I do so in Python? Again, what I need is to:

  1. iterate over all submodules in module (folder) vkcmds/;
  2. for each submodule, check if there is some class X that extends VKCommand inside;
  3. if (2) is true, then call the constructor of that class with one argument (it is guaranteed that the constructor for all commands only has one argument of a known type (my bot's main class));
  4. add the object (? extends VKCommand) constructed in (3) to the commands list that I can iterate over later.




Aucun commentaire:

Enregistrer un commentaire