gahjelle / pyplugs

Decorator based plugin architecture for Python
https://pypi.org/project/pyplugs/
MIT License
67 stars 4 forks source link

Import multiple functions from the same plugin #34

Closed AndresLaverdeMarin closed 2 years ago

AndresLaverdeMarin commented 2 years ago

Hello,

I'm trying to use a plugin architecture to develop a mathematical model for different vehicle characteristics, and I want to import more than one function for the same python file, i.e. I have multiple python files each one with multiple function and I need to import from the different file all functions:

plugins/
     __init__.py
    characteristics_1.py
    characteristics_2.py
    characteristics_3.py

And I want to import the functions that I have inside of characteristics file, I have registered whole functions that are inside of characteristics and the init file is:

import pyplugs

# All function names are going to be stored under names
names = pyplugs.names_factory(__package__)

# When read function is called, it will call a function received as parameter
read = pyplugs.call_factory(__package__)

This is possible using pyplugs? Or I need to implement some changes inside the pyplugs to do it?

Thanks in advance for your answer.

gahjelle commented 2 years ago

Hi @AndresLaverdeMarin

I'm glad you're giving pyplugs a spin. Yes, you can use multiple functions from each file. In terms of language, a plugin refers to one file (or module) and as you've seen it defaults to using the first registered function inside each file.

However, you can use func to refer to named, registered functions inside a file. Here are a couple of examples:

Assume you have the following file that contains several functions that you want to run as a kind of pipeline implementing a model, calling each of the functions in order:

model.py

import pyplugs

@pyplugs.register
def read(dataset, config):
    # Code to read data based on config and store raw data in dataset

@pyplugs.register
def clean(dataset, config):
    # Code to clean the data in dataset based on config

@pyplugs.register
def analyze(dataset, config):
    # Code to analyze the data in dataset based on config

You can then use code similar to the following to call each function:

import pyplugs

def run_pipeline(pipeline, config):
    stages = pyplugs.funcs(__package__, pipeline)
    dataset = {}
    for stage in stages:
        dataset = pyplugs.call(__package__, plugin=pipeline, func=stage, dataset=dataset, config=config)

In your simpler case, I think you only need to call a particular registered function? In this case, you can add that function name to the func parameter in call(). You could for instance create wrapper functions like these:

import pyplugs

# All function names inside a file are stored in funcs
funcs = pyplugs.funcs_factory(__package__)

# Call functions inside plugins in this package
call = pyplugs.call_factory(__package__)

def read(plugin, path):
    """The call to read() is dispatched to the correct plugin"""
    return call(plugin=plugin, func="read", path=path)

If you want to use the plugin named characteristics_1, you can then do something like this:

# List all functions inside characteristics_1
print(funcs("characteristics_1"))

# Call the read() function inside characteristics_1
read("characteristics_1", path="/data/stuff.csv")

I hope this helps you out!

AndresLaverdeMarin commented 2 years ago

Hello @gahjelle ,

Thanks for your detailed explanation, yes for my case the second example is enough to solve the problem, but the first example give some ideas about other use of the pyplugs inside the code.