DEV Community

Dimitar
Dimitar

Posted on

1

Creating a Plugin Architecture in Python

There are some use-cases where a plugin architecture is needed, I call this "code" plugins but it is quite possible that there is already a word for that. The idea is to 'load' functions or classes that are dynamically created so that you can have the reference to the instances at runtime. I've created 2 solutions for that matter one that is using the __subclasses__ dunder method and one using a decorator.

Solution 1

Repository: https://github.com/syrull/plugin-arch-python/tree/main/Solution-1

SOLUTION-1
│   configuration.py
│   main.py
│   README.md
│   setup.py
│
└───actions
        action_example1.py
        action_example2.py
        __init__.py
Enter fullscreen mode Exit fullscreen mode

Loading the __subclasses__ of the BaseAction class and creating a 'pluggable' classes. The actions can be specified in the configuration.py file in the ACTIONS const. This method is inspired by django's INSTALLED_APPS method.

The call method is a placeholder for the "actions".

To Register an action

  • New python file in actions/ folder
  • Create a class with an appropriate name (ex. ClickAction)
  • Extend the class with BaseAction
  • Add an entry to ACTIONS const located in configuration.py file with the approriate path to the module

After that the function will be available at the register in the main.py file.

$ python main.py
[<class 'actions.action_example1.Example1Action'>, <class 'actions.action_example2.Example2Action'>]
Enter fullscreen mode Exit fullscreen mode

Benchmarks

Measure-Command { python .\main.py }

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 24
Ticks             : 240745
TotalDays         : 2.78640046296296E-07
TotalHours        : 6.68736111111111E-06
TotalMinutes      : 0.000401241666666667
TotalSeconds      : 0.0240745
TotalMilliseconds : 24.0745
Enter fullscreen mode Exit fullscreen mode

Solution 2

Repository: https://github.com/syrull/plugin-arch-python/tree/main/Solution-2

SOLUTION-2
│   main.py
│   README.md
│   register.py
│
└───actions
        action_example1.py
        action_example2.py
        __init__.py
Enter fullscreen mode Exit fullscreen mode

The benefits of this solution are that we have a control over the decorator and we can pass some custom *args, **kwargs to the decorated functions.

To Register an action

  • New python file in actions/ folder
  • Create function with an appropriate name (ex. action_onclick)
  • Decorate the function with register_action decorator
  • Export the function in the __all__ method in actions/__init__.py file

After that the function will be available at the register in the main.py file.

$ python main.py
[<function action_example1 at 0x000001CC3F88D310>, <function action_example2 at 0x000001CC3F88D3A0>]
Enter fullscreen mode Exit fullscreen mode

Benchmarks

Measure-Command { python .\main.py }

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 22
Ticks             : 227803
TotalDays         : 2.6366087962963E-07
TotalHours        : 6.32786111111111E-06
TotalMinutes      : 0.000379671666666667
TotalSeconds      : 0.0227803
TotalMilliseconds : 22.7803
Enter fullscreen mode Exit fullscreen mode

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay