Create your own manager

Managers will help you expand your framework rapidly across all your different projects. If you have read the latest tutorial you already know that commands are hooks of the CommandManager class. class. So what is exactly is a hook and a manager?

We will describe that here in a simple manner. You can find more information in the manager reference doc.

Managers & Hooks

Managers

Managers help you define a way to search and register hooks (class or function) linked to a specific registry config like a ProjectConfig.

During the first tutorials you have encountered and worked with different registry config without noticing it. The ProjectConfig being one. Each registry, have hooks that are registered to every config. When you create a new command, automatically, when Socon start, we know that the project artemis has a launch command that is linked to the CommandManager.

Hooks

Hooks are nothing less than a class that is linked to a manager to do anything you want. As an example BaseCommand and ProjectCommand inherit from Hook and define how a command works. Both of these class are linked to the CommandManager that define the way we find these commands and the way we print the helper when you type python manage.py help.

Create a Manager

As it is always better to learn with a good example, let’s create a manager that help you register all your spacecraft for your projects. Well of course in each project you could just create a simple json that you load using your ProjectConfig path etc.. but where is the fun in that? And wouldn’t it be better to have a class for each spacecraft with different functionalities and different attributes that you can register automatically? I knew it. Let’s do it.

Define the manager

First thing first, we need to create the manager. For that in any project or in the common space you can create a managers.py file. It’s in that file that you will define all your managers. At the start, Socon will scan this file if it exists and register all the managers that have been defined.

We are going to create our manager in the common space. For that create the file managers.py in tutorial:

tutorial/
    tutorial/
        __init__.py
        settings.py
        managers.py
    ...

In the managers.py:

from socon.core.manager import BaseManager


class SpaceCraftManager(BaseManager):
    name = 'spacecraft'
    lookup_module = 'spacecraft'

That simple? Yes, by default Socon just needs two attributes:

  • name: The name of the manager.

  • lookup_module: The name of the module to look for the hooks.

Right now, there is nothing much. Socon will register your manager but we don’t know yet what to do with it. To give it a purpose we will create a Hook class that we will link to this manager. Then all of our hooks will inherit from this one.

Let’s create the hook. We have specified in the manager that we should look in the spacecraft module to find the hooks. So let’s create a file spacecraft.py at the same place than the managers.py.

In spacecraft.py:

from socon.core.manager import Hook


class SpaceCraft(Hook, abstract=True):
    manager = 'spacecraft'

    # attribute of the spacecraft
    name = None
    speed = None
    size = None

    def __str__(self) -> str:
        return "name: {}, speed: {}, size {}".format(
            self.name, self.speed, self.size
        )

In this class we have defined two important things:

  • abstract: This mean that this hook won’t be registered. In most case we won’t need to register the main hook class. This is because it can be an abstract base class and we don’t want to see it as a manager.

  • manager: The name of the manager that this hook and all its subclass will be linked to. This is really important. If you forget that and you register your hooks, this will throw you an error. Every class that inherit from Hook must define the manager attribute.

Note

We could have register this hook in the managers.py module. It would have worked. This is something that you have to decide for your framework.

Now what? We need to create our aircraft in each of our projects. For that let’s copy the spacecraft.py file in both apollo and artemis project. We will make a slight change in both of them.

Apollo project - spacecraft.py:

from tutorial.spacecraft import SpaceCraft


class SaturnIb(SpaceCraft):
    name = 'Saturn IB'
    speed = 10000
    size = 25

Artemis project - spacecraft.py:

from tutorial.spacecraft import SpaceCraft


class Orion(SpaceCraft):
    name = 'Orion'
    speed = 20000
    size = 10

To access these class we need to call our manager and tell him to look for every hooks in spacecraft.py in the common space and in every projects. For that we will modify the build.py command in the common space.

from socon.core.management.base import Config, ProjectCommand
from socon.core.registry.base import ProjectConfig
from socon.core.manager.base import managers


class BuildCommand(ProjectCommand):
    name = 'build'

    def handle(self, config: Config, project_config: ProjectConfig):
        manager = managers.get_manager('spacecraft')
        manager.find_all()
        spacecrafts = manager.get_hooks(project_config)
        for spacecraft in spacecrafts:
            print(f"Building {spacecraft()}")

This get’s a bit more complicated but no worries we will explain everything. First off all, we will need to import socon.core.manager.managers object to get access to all the managers. It’s that object that keeps a record of all managers Socon or the user have declared. This object is an instance of the ManagerRegistry class.

  • get_manager(): To access this manager we will use the get_manager() method by specifying the name of the manager we are looking for. This will return our manager and give us access to methods that will help us get all of our SpaceCraft class.

  • find_all(): Socon allows you to search only in the project config you want but also everywhere in your framework. For the tutorial we will search everywhere.

  • get_hooks(): Get all the hooks for the project config given. This means that when you start the build command, if the project you give contain a spacecraft, we will get it and print it later on.

We then iterate and instantiate our spacecrafts. This will then allow us to print the string representation of our class.

You can now start the build command:

$ python manage.py build --project artemis

This will get you the following output:

Building name: Orion, speed: 20000, size 10

Congratulations! You have built your first Manager and Hooks. As you can see it is pretty easy and give you endless possibility for your framework.

Note

You can add multiple spacecraft in your spacecraft.py. They will all be registered and accessible using your manager. Give it a try!