The first edition of the code can be found in this 1.0 version.
To summarize the problem :
- I have an endpoint in flask where the work logic change according to the query
- I am trying to implement an extension mechanism where the right class is loaded
- The first version did not provide caching of the imported class
Based on the answer from @netme, this is a code update where I lazy load the right handler class and cache it :
./run.py:
from flask import Flask, abort
import handler
app = Flask(__name__)
handler_collection = handler.HandlerCollection()
@app.route('/')
def api_endpoint():
try:
endpoint = "simple" # Custom logic to choose the right handler
handler_instance = handler_collection.getInstance(endpoint)
except handler.UnknownEndpoint as e:
abort(404)
print(handler_instance, handler_instance.name)
# Handler processing. Not yet implemented
return "Hello World"
if __name__ == "__main__":
app.run(host='0.0.0.0', port=8080, debug=True)
./handler.py:
# -*- coding: utf-8 -*-
import importlib
import handlers
class UnknownEndpoint(Exception):
pass
class HandlerCollection:
_endpoints_classes = {}
def addClass(self, endpoint_class):
self._endpoints_classes[endpoint_class.name] = endpoint_class
def getClass(self, endpoint_name):
if (endpoint_name in self._endpoints_classes):
return self._endpoints_classes.get(endpoint_name)
try:
# Try to import endpoint handler from a module in handlers package
endpoint_module = importlib.import_module(
'.{}'.format(str(endpoint_name)),
'handlers')
endpoint_module.register(self)
except ImportError as e:
raise UnknownEndpoint('Unknown endpoint \'{}\''.format(endpoint_name)) from e
return self._endpoints_classes.get(endpoint_name)
def getInstance(self, endpoint_name):
endpoint_class = self.getClass(endpoint_name)
return endpoint_class()
./handlers/simple.py:
# -*- coding: utf-8 -*-
class SimpleWebhookHandler:
name = "simple"
def register(handler_collection):
handler_collection.addClass(SimpleWebhookHandler)
Each handler needs to provide a register function which allows to have different handler class name and each handler class needs to provide a class attribute name.
Can you give me your opinion on this piece of code ? Is it "pythonic" ?