MP Plugs documentation index

Universal Python Framework.

What is this package for?

MP Plugs can be used to create modular applications with setup + loop structure common in microcomputer and GUI programming.

Links

Get the latest version

Latest release can be found here. This documentation was last updated for version v0.4.

Meta

Documentation maintenance

This documentation is maintained in a docs folder. If you find an error or a lacking topic please open an issue or a PR.

External resources
License

Both the package and this documentation are released under MIT license.

Authors

Installation

Installation from PIP


pip install mpplugs
    

Manual installation


git clone https://github.com/Jakub21/mpplugs.git
python setup.py install
    

Quick introduction to MP Plugs

MP Plugs can be used to create modular programs. Here's how to do it.

How MP Plugs programs work

MP Plugs enforces coding practices that might be considered unorthodox, beware

Hello world program

First, create main program file program.py. This code runs in main process. Other processes use this one to communicate with each other.


import mpplugs as plg # Import mp plugs

if __name__ == '__main__':
  prog = plg.Program('MyBasicProgram') # Create program
  prog.updateSettings({ # Method for changing program settings
    'Compiler.pluginDirectories': ['./demoPlugins'], # Add plugins to your program
  })
  prog.preload() # Prepare plugins
  prog.run() # Create plugin instances in separate processes, exec init and start loop
    

This code creates program instance, then tells compiler where to look for plugins. The preload method compiles plugins into single-file form. Those files are deleted once your program stops.

Note that run method is blocking the main process.

Main process is only used to coordinate tasks and will not execute any of your code. For that you need plugins. Plugin consists of 3 mandatory files: Config.py and Scope.py and a file that has the same name as your plugin. Those must be placed in a directory that is also named after your plugin. For the program to load the plugin its parent directory must be added in program's settings.

In our example, after adding plugin named FirstDemo the file structure would look like this:

project/ |- demoPlugins/ | |- FirstDemo/ | | |- Config.py | | |- FirstDemo.py (main plugin file) | | |- Scope.py (definitions file) |- program.py

In FirstDemo.py there must be a class that, again, has name of the plugin. Also it must inherit from package's Plugin class that is made available in this file during startup. We also need init and update methods that were mentioned on the very start of this guide. Generally empty plugin would look like this:


class FirstDemo(Plugin):
  def init(self):
    super().init()

  def update(self):
    super().update()

    

Note the super methods calls. Those are required for the program to run correctly.

Next required file is Config.py This file must contain a class named Config but it can be left empty. When program starts contents of this class are copied to cnf property of the plugin. Using this class to store configurable variables is recommended because they can be modified from main program script.


class Config:
  pass
    

Last required file is Scope.py but it can be left empty. This file is where you can define variables accessible in whole plugin process or import packages. In more complex plugins it matters that you do this in this file.

You can now check if your newly created program runs but at this point it would only print some initialization logs.

Using built-in Logger

MP Plugs has logger that includes information on where in program the log was emitted and a timestamp. The logs are colored depending on their importance. To emit a log use one of the built-in methods.


Debug(plugin, *message) # magenta timestamp, gray origin + message
Info(plugin, *message) # magenta timestamp, white origin + message
Note(plugin, *message) # cyan timestamp + origin, white message
Warn(plugin, *message) # all yellow
Error(plugin, *message) # all red
    

Colors can be changed or turned off in program settings. This logger will be used later in the guide.

Events system

For this section we will need two plugins. Create plugin SecondDemo by repeating steps from the previous section.

To communicate between processes events system must be used. Every event triggers its handlers in all plugins of the program.

 # FirstDemo.py
class FirstDemo(Plugin):
  def init(self):
    super().init()
    self.addEventHandler('Dummy', self.onDummy) # Add handler

  def update(self):
    super().update()

  def onDummy(self, event):
    Note(self, f'FirstDemo received Dummy (apples = {event.apples})')
    
 # SecondDemo.py
class SecondDemo(Plugin):
  def init(self):
    super().init()
    self.apples = 4

  def update(self):
    super().update()
    if not(self.__mpplugs__.tick % 60):
      Debug(self, f'Emitting Dummy (apples = {self.apples})')
      Event(self, 'Dummy', apples=self.apples)
      self.apples = (self.apples + 3) % 13
    

See Plugin class API for more on __mpplugs__ property, it will not be discussed in this guide. It only was used to limit rate at which events are fired.

You could add handler for events with Dummy ID and it would get called as well. You can see that any keyword argument passed to the event constructor will be added as its property. This has limitation of only allowing picklable objects.

Summary

This package has more features that were not described here, this is what you need to get started. For more please refer to the API sections. You can request that this guide is extended by opening an issue. You can also extend it yourself and open a pull request.

Program

Compiler

Executor

Plugin