import json

import tornado.ioloop
import tornado.web
import lmod

from notebook.utils import url_path_join
from notebook.base.handlers import IPythonHandler

from jinja2 import Template

modules_template = """
<html><body><form method="POST">
{% for loc, modules in moduleavail.items() %}
  <h2>{{ loc }}</h2>
  <table>
      <tr>
      {% for module in modules %}
      <td><input type="checkbox" name="module" value="{{ module }}" {% if module in modulelist %} checked {% endif %}> {{ module }} </td>
      {% if loop.index % 4 == 0 %}
            </tr><tr>
      {% endif %}
      {% endfor %}
      </tr>
  </table>
{% endfor %}
<input type="submit">
</form></body></html>
"""

class LmodActionHandler(IPythonHandler):
    @tornado.web.authenticated
    def get(self, action):
        if action == 'avail':
            self.finish(json.dumps(lmod.module_avail()))
        elif action == 'list':
            self.finish(json.dumps(lmod.module_list()))

    @tornado.web.authenticated
    def post(self, action):
        if action in ('load', 'unload'):
            module = self.get_argument('module', default=None)
            if module:
                lmod.module(action, module)
                self.finish(json.dumps('SUCCESS'))

class LmodHandler(IPythonHandler):
    template = Template(modules_template)

    def initialize(self):
        self.module_list = module_list()

    @tornado.web.authenticated
    def get(self):
        self.write(self.template.render(moduleavail=module_avail(),
                                        modulelist=self.module_list))

    @tornado.web.authenticated
    def post(self):
        checked_modules = self.request.arguments['module']
        new_modulelist = set(map(bytes.decode, checked_modules))

        to_load = new_modulelist - self.module_list
        to_unload = self.module_list - new_modulelist

        lmod.module('load', " ".join(to_load))
        lmod.module('unload', " ".join(to_unload))

        self.module_list = set(lmod.module_list())
        self.write(self.template.render(moduleavail=module_avail(),
                                        modulelist=self.module_list))


#-----------------------------------------------------------------------------
# URL to handler mappings
#-----------------------------------------------------------------------------
_lmod_action_regex = r"(?P<action>load|unload|avail|list)"

default_handlers = [
    (r"/lmod", LmodHandler),
    (r"/lmod/%s" % (_lmod_action_regex), LmodActionHandler),
]

def load_jupyter_server_extension(nbapp):
    """
    Called when the extension is loaded.

    Args:
        nb_server_app (NotebookWebApplication): handle to the Notebook webserver instance.
    """
    nbapp.log.info("Loading lmod extension")
    web_app = nbapp.web_app
    host_pattern = '.*$'
    for handler in default_handlers:
        route_pattern = url_path_join(web_app.settings['base_url'], handler[0])
        web_app.add_handlers(host_pattern, [(route_pattern, handler[1])])

    # Load javascript extension
    nbapp.config_manager.update('tree', {"load_extensions": {"lmod": True}})

if __name__ == "__main__":
    app = tornado.web.Application([ (r"/", LmodHandler), ])
    app.listen(12345)
    tornado.ioloop.IOLoop.current().start()

@@ -156,532 +156,8 @@
 er%0A%0A
-from jinja2 import Template%0A%0Amodules_template = %22%22%22%0A%3Chtml%3E%3Cbody%3E%3Cform method=%22POST%22%3E%0A%7B%25 for loc, modules in moduleavail.items() %25%7D%0A  %3Ch2%3E%7B%7B loc %7D%7D%3C/h2%3E%0A  %3Ctable%3E%0A      %3Ctr%3E%0A      %7B%25 for module in modules %25%7D%0A      %3Ctd%3E%3Cinput type=%22checkbox%22 name=%22module%22 value=%22%7B%7B module %7D%7D%22 %7B%25 if module in modulelist %25%7D checked %7B%25 endif %25%7D%3E %7B%7B module %7D%7D %3C/td%3E%0A      %7B%25 if loop.index %25 4 == 0 %25%7D%0A            %3C/tr%3E%3Ctr%3E%0A      %7B%25 endif %25%7D%0A      %7B%25 endfor %25%7D%0A      %3C/tr%3E%0A  %3C/table%3E%0A%7B%25 endfor %25%7D%0A%3Cinput type=%22submit%22%3E%0A%3C/form%3E%3C/body%3E%3C/html%3E%0A%22%22%22%0A%0A
 clas
@@ -712,916 +712,8 @@
 ))%0A%0A
-class LmodHandler(IPythonHandler):%0A    template = Template(modules_template)%0A%0A    def initialize(self):%0A        self.module_list = module_list()%0A%0A    @tornado.web.authenticated%0A    def get(self):%0A        self.write(self.template.render(moduleavail=module_avail(),%0A                                        modulelist=self.module_list))%0A%0A    @tornado.web.authenticated%0A    def post(self):%0A        checked_modules = self.request.arguments%5B'module'%5D%0A        new_modulelist = set(map(bytes.decode, checked_modules))%0A%0A        to_load = new_modulelist - self.module_list%0A        to_unload = self.module_list - new_modulelist%0A%0A        lmod.module('load', %22 %22.join(to_load))%0A        lmod.module('unload', %22 %22.join(to_unload))%0A%0A        self.module_list = set(lmod.module_list())%0A        self.write(self.template.render(moduleavail=module_avail(),%0A                                        modulelist=self.module_list))%0A%0A%0A
 #---
@@ -977,37 +977,8 @@
 = %5B%0A
-    (r%22/lmod%22, LmodHandler),%0A
     
@@ -1665,16 +1665,16 @@
 ain__%22:%0A
-
     app 
@@ -1712,16 +1712,22 @@
 /%22, Lmod
+Action
 Handler)

Remove LmodHandler keeping only LmodActionHandler