Building Pluggable Python Applications

How Pluggy works

Building a pluggable application

requests  # This is needed for the plugins
pluggy
# main.pyclass App:
def display_jokes(self, amount: int) -> None:
results = [[]]
jokes = [joke for plugin in results for joke in plugin]
for joke in jokes:
print(joke)
if __name__ == "__main__":
app = App()
app.display_jokes(2)
# hookspec.pyfrom typing import Any, Callable, List, TypeVar, castimport pluggy  # type: ignoreF = TypeVar("F", bound=Callable[..., Any])
hookspec = cast(Callable[[F], F], pluggy.HookspecMarker("python_plugin_example"))
class PluginExampleHookSpec:
"""
Python Plugin Example Hook Specification
"""
@hookspec
def retrieve_joke(self, amount: int) -> List[str]:
"""
Fired when retrieving jokes
Args:
amount: How many jokes should be returned
Returns:
A string containing a joke
"""
# hookimpl.pyfrom typing import Any, Callable, TypeVar, castimport pluggy  # type: ignoreF = TypeVar("F", bound=Callable[..., Any])hookimpl = cast(Callable[[F], F], pluggy.HookimplMarker("python_plugin_example"))
# main.pyimport pluggy  # type: ignorefrom python_plugin_example.hookspec import PluginExampleHookSpecclass App:
def __init__(self) -> None:
self.pm: pluggy.PluginManager = pluggy.PluginManager("python_plugin_example")
self.pm.add_hookspecs(PluginExampleHookSpec)
def display_jokes(self, amount: int) -> None:
results = self.pm.hook.retrieve_joke(amount=amount)
jokes = [joke for plugin in results for joke in plugin]
for joke in jokes:
print(joke)
if __name__ == "__main__":
app = App()
app.display_jokes(2)
# plugins/icanhazdadjokes.pyfrom typing import Listimport requestsfrom python_plugin_example.hookimpl import hookimplDAD_JOKE_API_ENDPOINT = "<https://icanhazdadjoke.com/>"class ICanHazDadJokePlugin:
@hookimpl
def retrieve_joke(self, amount: int) -> List[str]:
headers = {
"Accept": "application/json",
}
values = []
for i in range(amount):
response = requests.get(DAD_JOKE_API_ENDPOINT, headers=headers)
values.append(response.json().get("joke", ""))
jokes = [f"👨 Dad joke: {value}" for value in values]
return jokes
# plugins/chucknorris.pyfrom typing import Listimport requestsfrom python_plugin_example.hookimpl import hookimplCHUCK_NORRIS_API_ENDPOINT = "<https://api.chucknorris.io/jokes/random>"class ChuckNorrisPlugin:
@hookimpl
def retrieve_joke(self, amount: int) -> List[str]:
values = []
for i in range(amount):
response = requests.get(CHUCK_NORRIS_API_ENDPOINT)
values.append(response.json().get("value", ""))
jokes = [f"🤠 Chuck Norris: {value}" for value in values]
return jokes
# main.pyimport pluggy  # type: ignorefrom python_plugin_example.hookspec import PluginExampleHookSpec
from python_plugin_example.plugins.chucknorris import ChuckNorrisPlugin
from python_plugin_example.plugins.icanhazdadjoke import ICanHazDadJokePlugin
class App:
def __init__(self) -> None:
self.pm: pluggy.PluginManager = pluggy.PluginManager("plugin_example")
self.pm.add_hookspecs(PluginExampleHookSpec)
self.pm.register(ChuckNorrisPlugin())
self.pm.register(ICanHazDadJokePlugin())
def display_jokes(self, amount: int) -> None:
results = self.pm.hook.retrieve_joke(amount=amount)
jokes = [joke for plugin in results for joke in plugin]
for joke in jokes:
print(joke)
if __name__ == "__main__":
app = App()
app.display_jokes(2)
> python main.py
👨 Dad joke: Geology rocks, but Geography is where it’s at!
👨 Dad joke: My pet mouse ‘Elvis’ died last night. He was caught in a trap..
🤠 Chuck Norris: Chuck Norris only applies his car brakes for people with red hair & beards.
🤠 Chuck Norris: Chuck Norris does not need a toothbrush when he brushes his teeth

--

--

--

Anders is a Finnish IT company, whose mission is sustainable software development with the greatest colleagues of all time.

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Boosting speed and power for your eCommerce website with a dedicated server — Geek Crunch Hosting

Gesture Space

Revest Protocol Launches on Polygon

FlutterForce — #Week 113

Imgix Review — Image Processing as a Service Reviewed

Go, the Tricky Parts

.Net Core Web API 3.1 CRUD Operations With Redis and SQL Server on Azure Cloud

Virtual Internship Program Experience (LGMVIP’21) at LetsGrowMore

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Anders Innovations

Anders Innovations

Anders is a Finnish IT company, whose mission is sustainable software development with the greatest colleagues of all time.

More from Medium

Web Scraping ebay with selenium and export data to csv

Installing Pycharm (advanced IDE for working on coding projects)-Community Version

Don’t Buy Alexa Create Your Own Using Python -less than 50 Lines of Code

Alexa from Amazon

Alexa Skills with Python : The visual dimension