Page 1 of 1

Extensions support

Posted: Tue May 17, 2016 8:33 pm
by BackRaw
Hi,

I'm currently looking for a way to implement a dynamic Extensions system into my plugin. I've come up with this folder structure thus far:

Code: Select all

./plugins/myplugin/myplugin.py
./plugins/myplugin/extensions/__init__.py
./plugins/myplugin/extensions/ext1.py
./plugins/myplugin/extensions/ext2.py


Syntax: Select all

# ./plugins/myplugin/myplugin.py

from myplugin.extensions import ext1
from myplugin.extensions import ext2


This is all good, however, what if I don't know the extension's name? Like when somebody else wrote an extension and put it into the extensions folder.
The bad way works, but that's now what I'm looking for:

Code: Select all

from myplugin.extensions import *



I want to be able to do something like this:

Syntax: Select all

# ./plugins/myplugin/extensions/__init__.py

class Extension(object):

# some code that identifies this object as a plugin Extension


extensions = list() # extension manager that holds Extension objects


Syntax: Select all

# ./plugins/myplugin/extensions/ext1.py

from myplugin.extensions import Extension
from myplugin.extensions import extensions

class Ext1(Extension):

# some code

extensions.append(Ext1())


so I can have some control over those extensions like loading and unloading by server command:

Syntax: Select all

# ./plugins/myplugin/myplugin.py

from myplugin.extensions import extensions

# dome something with the extension manager

In my mind, this can work. However, ext1.py and ext2.py will never get loaded into memory because nothing imports them.
What can I do about this?

My goal is to expose certain listeners from the main plugin which the extensions can listen on and do something about them.

Thank you very much!

Re: Extensions support

Posted: Tue May 17, 2016 8:52 pm
by Ayuto
What you are looking for are sub-plugins and we have an API for that (not sure if the examples in that post are still working).
viewtopic.php?f=5&t=458

This will allow you to load/unload/reload sub-plugins. If you are just looking for something that loads all sub-plugins when your main plugin gets loaded, you can probably stick with an easier implementation. E.g. you could just iterate over all *.py files in your sub-plugin directory and import them using importlib.

Re: Extensions support

Posted: Tue May 17, 2016 9:14 pm
by iPlayer
You can add this to the end of your extensions/__init__.py:

Code: Select all

import os

def parse_modules(dir_):
    modules = []
    for name in os.listdir(dir_):
        if not name.endswith('.py'):
            continue

        if name.startswith('__') and name.endswith('__.py'):
            continue

        if os.path.isfile(os.path.join(dir_, name)):
            modules.append(os.path.splitext(name)[0])

    return modules

__all__ = parse_modules(os.path.dirname(__file__))

from . import *


Or just go with importlib, as Ayuto suggested.

Re: Extensions support

Posted: Tue May 17, 2016 9:38 pm
by satoon101
I would highly recommend using path.Path over os. We include path.py in our site-packages.

Re: Extensions support

Posted: Tue May 17, 2016 9:52 pm
by BackRaw
Thank you all. I totally forgot about the "plugins" package. I'll look into it. :D