Skip to content

re-ws.pl

ReverseEngineering WorkStation

  • Home
  • Tutorials
  • Random
  • About

Plugin architecture demo for Python projects

Posted on November 17, 2024 - November 17, 2024 by Kamil (aka. v3l0c1r4pt0r)

I started work on this concept many months ago. However I never had enough free time to get this to complete stage. Today finally I prepared the demo will all crucial features embedded. So, first, let me explain the concept. Generally the idea is to have a command that will be easily extensible with new features. The best way to achieve that is by having a kind of plugin architecture, where there is main program – in this case just an interface in fact as it does not provide any useful features on its own. And there are a lot of plugins that somehow registers to main program.

Crucial thing here is to have it done automatically, so all the user has to do is to install the plugin. Another important feature is to provide bash completion for this program, so that plugin developer can focus on interface itself, not the way of integrating it with bash and still get quite good completion. Of course in more complicated cases developer still has to do some development, but let’s ignore that here as this is not so important.

To achieve all the above I created two demo projects. One is called menu and it implements interface for plugins, do all the necessary jobs, so that plugins can live like almost independent applications, only called by menu. The other is demo plugin that uses all this magic to appear as command in menu just after its installation.

So from user perspective there are two main steps:

  1. Install menu and all plugins he needs with pip
  2. Enable bash completion as is usually done with argcomplete

I described the usage in README of menu already, so will not repeat that here.

Results

With this kind of architecture, what you can achieve is, with only few lines of code, interface that outputs something like this:

$ m --help
usage: m [-h] {demo} ...

Menu

positional arguments:
  {demo}
    demo      Show a demo on how plugin can have its own command

options:
  -h, --help  show this help message and exit
$ m demo --help
usage: m demo [-h] [-d]

options:
  -h, --help         show this help message and exit
  -d, --demonstrate  Demonstrate use of argument

And this is split into two Python modules and easily can be extended to new ones.

Internals

Now to the most interesting part, so the internals. Internally there are three interesting features here. First is how main menu finds its plugins. This can be seen in __main__.py and looks like that:

29     plugin_list = []
30     for p in pkgutil.iter_modules():
31       if p.name.startswith(PLUGIN_PACKAGE_PREFIX):
32         plugin_list.append(p.name)

Second interesting feature is usage of argcomplete, as it makes completion almost effortless. And this is as simple as:

54     argcomplete.autocomplete(parser)
55     args = parser.parse_args(argv)
56     return args.func(args)

And the last one is having logger that colors terminal output depending on level of log to print. This one is a bit longer as it consists of 3 parts. First is formatter class:

class ColoringFormatter(logging.Formatter):

  fmt = '{start}%(levelname)s/%(name)s [%(asctime)s]: %(message)s{stop}'
  FORMATS = {
    logging.FATAL: fmt.format(start=Format(Style.BOLD, Color.RED),
        stop=Format(Style.OFF)),
    logging.ERROR: fmt.format(start=Format(color=Color.LIGHT_RED),
        stop=Format(Style.OFF)),
    logging.WARNING: fmt.format(start=Format(color=Color.LIGHT_YELLOW),
        stop=Format(Style.OFF)),
    logging.DEBUG: fmt.format(start=Format(color=Color.DARK_GREY),
        stop=Format(Style.OFF)),
    logging.NOTSET: fmt.format(start='', stop=''),
  }

  def format(self, record):
    if record.levelno in self.FORMATS:
      fmt = self.FORMATS[record.levelno]
    else:
      fmt = self.FORMATS[logging.NOTSET]
    formatter = logging.Formatter(fmt)
    return formatter.format(record)

Second is format class that moves some escape code creation magic outside (color and style are ordinary Enums):

class Format:

  def __init__(self, style=None, color=None):
    self.style = style
    self.color = color

  def __str__(self):
    stack = []
    if self.color is not None:
      stack.append(str(self.color.value))
    if self.style is not None:
      stack.append(str(self.style.value))
    seq_list = ';'.join(stack)
    return f'\033[{seq_list}m'

And third is, where finally logger is assembled together:

    # create main logger
    self.main_logger = logging.getLogger(appname)
    self.main_logger.setLevel(logging.DEBUG)

    # create console handler
    handler = logging.StreamHandler()
    handler.setLevel(logging.DEBUG)

    # set console handler's formatter to coloring
    handler.setFormatter(ColoringFormatter())
    self.main_logger.addHandler(handler)

Idea for colored logger obviously comes from StackOverflow. And basically this is it. The rest is in my opinion boring stuff that always has to be done.

Posted in NewsTagged hacking, Linux, programming, Python

Post navigation

Authorizing adb connections from Android command line (and making other service calls from cli)
Running graphical apps inside Docker containers

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Tags

Android assembly busybox C CAN can-hacking cc-factory cmake compiler docker Dreamspark electronics English gcc hacking hardware JavaCard JCOP kernel KiCAD library Linux PC PCB pinout PKI polski programming Python radio Raspberry Pi Reverse Engineering RTL-SDR SDC SDM SDR smart card software tor tty UART UEFi Windows X.509 Xperia Pro

Recent Posts

  • PHP build for use bundled in Android applications
  • Running graphical apps inside Docker containers
  • Plugin architecture demo for Python projects
  • Authorizing adb connections from Android command line (and making other service calls from cli)
  • How to recover torrent from rtorrent meta files

Recent Comments

  • pomi on Playing with GF-07 GPS device
  • pomi on Playing with GF-07 GPS device
  • Hamdy Abumgata on Playing with GF-07 GPS device
  • Mousum Gogoi on Playing with GF-07 GPS device
  • Eason on Sniffing USB traffic with DSLogic logic analyzer into pcap file

Categories

  • News
  • Random
  • Reversing LKV373A
  • Setting up new v3 Hidden Service with ultimate security
  • Tutorials
  • Uncategorized
  • Understanding JCOP

Links

  • Me @ github
  • LKV373A Wiki
  • DevTomek

Archives

  • December 2024
  • November 2024
  • May 2024
  • July 2023
  • October 2022
  • August 2022
  • July 2021
  • June 2021
  • May 2021
  • December 2020
  • November 2020
  • October 2020
  • August 2020
  • December 2019
  • November 2019
  • October 2019
  • August 2019
  • July 2019
  • February 2019
  • November 2018
  • October 2018
  • June 2018
  • May 2018
  • March 2018
  • February 2018
  • January 2018
  • December 2017
  • November 2017
  • September 2017

Meta

  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org
Proudly powered by WordPress | Theme: micro, developed by DevriX.