Module tensorboardY.server

Source code
from tornado import web, ioloop
import os
import simplejson as json

from .tools import check_type
from .widgets import Widget
from .output import decode


class NoCacheStaticFileHandler(web.StaticFileHandler):

    def set_extra_headers(self, path):
        self.set_header('Cache-Control',
                        'no-store, no-cache, must-revalidate, max-age=0')


class MainHandler(web.RequestHandler):

    def initialize(self, forward, inputs, title, github_url):
        self.forward = forward
        self.inputs = inputs
        self.title = title
        self.github_url = github_url

    def get(self):
        self.render("./frontend/index.html", inputs=self.inputs,
                    title=self.title, github_url=self.github_url)

    def post(self):
        cmd = json.loads(self.request.body)
        if cmd['cmd'] == 'get_data':
            assert(0 <= cmd['tyid'] < len(self.inputs)),\
                'tyid {} not in [0,{})'.format(cmd['tyid'], len(self.inputs))
            data = self.inputs[cmd['tyid']].get_data(**cmd['info'])
            if data is not None:
                self.write(json.dumps(data))
            else:
                self.send_error()
        if cmd['cmd'] == 'arg_delivery':
            assert(len(cmd['args']) == len(self.inputs)),\
                'client args {} != num inputs {}'\
                .format(len(cmd['args']), len(self.inputs))
            feed = {inp.var: inp.decode(arg)
                    for inp, arg in zip(self.inputs, cmd['args'])}
            data = self.forward(**feed)
            data = decode(data)
            if data is not None:
                self.write(json.dumps(data))
            else:
                self.send_error()


def show(forward, inputs, port=5000, debug=True, title='Run',
         github_url=None):
    r"""
    Starts a server at `port` that visualizes the function `forward`.
    Args:
        forward (callable): The function to be visualized. `forward` should
            return a string of html, a PIL.Image.Image, or a matplotlib figure.
        inputs (list): List of `ty.Widget`s (one `ty.Widget` for each argument
            to `forward`) that dictate how the user is able to feed inputs
            to the function
        port (int): The port where the model is served
        debug (bool): Run the server in debug mode
        title (str): Submit button text
        github_url (str): url to link to a github page
    """
    check_type(inputs, Widget, islist=True)
    check_type(title, str)
    assert(callable(forward)), '{} is not callable'.format(forward)
    loop = ioloop.IOLoop.instance()
    app = web.Application([
            (r"/", MainHandler, {'forward': forward,
                                 'inputs': inputs, 'title': title,
                                 'github_url': github_url}),
            (r"/(.*)", NoCacheStaticFileHandler, {
                "path":
                os.path.join(os.path.dirname(__file__), "./frontend/")})
            ], debug=debug)
    print('view @ http://localhost:{}'.format(port))
    app.listen(port)
    loop.start()

Functions

def show(forward, inputs, port=5000, debug=True, title='Run', github_url=None)

Starts a server at port that visualizes the function forward.

Args

forward : callable
The function to be visualized. forward should return a string of html, a PIL.Image.Image, or a matplotlib figure.
inputs : list
List of ty.Widgets (one ty.Widget for each argument to forward) that dictate how the user is able to feed inputs to the function
port : int
The port where the model is served
debug : bool
Run the server in debug mode
title : str
Submit button text
github_url : str
url to link to a github page
Source code
def show(forward, inputs, port=5000, debug=True, title='Run',
         github_url=None):
    r"""
    Starts a server at `port` that visualizes the function `forward`.
    Args:
        forward (callable): The function to be visualized. `forward` should
            return a string of html, a PIL.Image.Image, or a matplotlib figure.
        inputs (list): List of `ty.Widget`s (one `ty.Widget` for each argument
            to `forward`) that dictate how the user is able to feed inputs
            to the function
        port (int): The port where the model is served
        debug (bool): Run the server in debug mode
        title (str): Submit button text
        github_url (str): url to link to a github page
    """
    check_type(inputs, Widget, islist=True)
    check_type(title, str)
    assert(callable(forward)), '{} is not callable'.format(forward)
    loop = ioloop.IOLoop.instance()
    app = web.Application([
            (r"/", MainHandler, {'forward': forward,
                                 'inputs': inputs, 'title': title,
                                 'github_url': github_url}),
            (r"/(.*)", NoCacheStaticFileHandler, {
                "path":
                os.path.join(os.path.dirname(__file__), "./frontend/")})
            ], debug=debug)
    print('view @ http://localhost:{}'.format(port))
    app.listen(port)
    loop.start()

Classes

class MainHandler (application, request, **kwargs)

Base class for HTTP request handlers.

Subclasses must define at least one of the methods defined in the "Entry points" section below.

Source code
class MainHandler(web.RequestHandler):

    def initialize(self, forward, inputs, title, github_url):
        self.forward = forward
        self.inputs = inputs
        self.title = title
        self.github_url = github_url

    def get(self):
        self.render("./frontend/index.html", inputs=self.inputs,
                    title=self.title, github_url=self.github_url)

    def post(self):
        cmd = json.loads(self.request.body)
        if cmd['cmd'] == 'get_data':
            assert(0 <= cmd['tyid'] < len(self.inputs)),\
                'tyid {} not in [0,{})'.format(cmd['tyid'], len(self.inputs))
            data = self.inputs[cmd['tyid']].get_data(**cmd['info'])
            if data is not None:
                self.write(json.dumps(data))
            else:
                self.send_error()
        if cmd['cmd'] == 'arg_delivery':
            assert(len(cmd['args']) == len(self.inputs)),\
                'client args {} != num inputs {}'\
                .format(len(cmd['args']), len(self.inputs))
            feed = {inp.var: inp.decode(arg)
                    for inp, arg in zip(self.inputs, cmd['args'])}
            data = self.forward(**feed)
            data = decode(data)
            if data is not None:
                self.write(json.dumps(data))
            else:
                self.send_error()

Ancestors

  • tornado.web.RequestHandler

Methods

def get(self)
Source code
def get(self):
    self.render("./frontend/index.html", inputs=self.inputs,
                title=self.title, github_url=self.github_url)
def initialize(self, forward, inputs, title, github_url)

Hook for subclass initialization. Called for each request.

A dictionary passed as the third argument of a url spec will be supplied as keyword arguments to initialize().

Example::

class ProfileHandler(RequestHandler):
    def initialize(self, database):
        self.database = database

    def get(self, username):
        ...

app = Application([
    (r'/user/(.*)', ProfileHandler, dict(database=database)),
    ])
Source code
def initialize(self, forward, inputs, title, github_url):
    self.forward = forward
    self.inputs = inputs
    self.title = title
    self.github_url = github_url
def post(self)
Source code
def post(self):
    cmd = json.loads(self.request.body)
    if cmd['cmd'] == 'get_data':
        assert(0 <= cmd['tyid'] < len(self.inputs)),\
            'tyid {} not in [0,{})'.format(cmd['tyid'], len(self.inputs))
        data = self.inputs[cmd['tyid']].get_data(**cmd['info'])
        if data is not None:
            self.write(json.dumps(data))
        else:
            self.send_error()
    if cmd['cmd'] == 'arg_delivery':
        assert(len(cmd['args']) == len(self.inputs)),\
            'client args {} != num inputs {}'\
            .format(len(cmd['args']), len(self.inputs))
        feed = {inp.var: inp.decode(arg)
                for inp, arg in zip(self.inputs, cmd['args'])}
        data = self.forward(**feed)
        data = decode(data)
        if data is not None:
            self.write(json.dumps(data))
        else:
            self.send_error()
class NoCacheStaticFileHandler (application, request, **kwargs)

A simple handler that can serve static content from a directory.

A StaticFileHandler is configured automatically if you pass the static_path keyword argument to Application. This handler can be customized with the static_url_prefix, static_handler_class, and static_handler_args settings.

To map an additional path to this handler for a static data directory you would add a line to your application like::

application = web.Application([
    (r"/content/(.*)", web.StaticFileHandler, {"path": "/var/www"}),
])

The handler constructor requires a path argument, which specifies the local root directory of the content to be served.

Note that a capture group in the regex is required to parse the value for the path argument to the get() method (different than the constructor argument above); see URLSpec for details.

To serve a file like index.html automatically when a directory is requested, set static_handler_args=dict(default_filename="index.html") in your application settings, or add default_filename as an initializer argument for your StaticFileHandler.

To maximize the effectiveness of browser caching, this class supports versioned urls (by default using the argument ?v=). If a version is given, we instruct the browser to cache this file indefinitely. make_static_url (also available as RequestHandler.static_url) can be used to construct a versioned url.

This handler is intended primarily for use in development and light-duty file serving; for heavy traffic it will be more efficient to use a dedicated static file server (such as nginx or Apache). We support the HTTP Accept-Ranges mechanism to return partial content (because some browsers require this functionality to be present to seek in HTML5 audio or video).

Subclassing notes

This class is designed to be extensible by subclassing, but because of the way static urls are generated with class methods rather than instance methods, the inheritance patterns are somewhat unusual. Be sure to use the @classmethod decorator when overriding a class method. Instance methods may use the attributes self.path self.absolute_path, and self.modified.

Subclasses should only override methods discussed in this section; overriding other methods is error-prone. Overriding StaticFileHandler.get is particularly problematic due to the tight coupling with compute_etag and other methods.

To change the way static urls are generated (e.g. to match the behavior of another server or CDN), override make_static_url, parse_url_path, get_cache_time, and/or get_version.

To replace all interaction with the filesystem (e.g. to serve static content from a database), override get_content, get_content_size, get_modified_time, get_absolute_path, and validate_absolute_path.

Changed in version: 3.1

Many of the methods for subclasses were added in Tornado 3.1.

Source code
class NoCacheStaticFileHandler(web.StaticFileHandler):

    def set_extra_headers(self, path):
        self.set_header('Cache-Control',
                        'no-store, no-cache, must-revalidate, max-age=0')

Ancestors

  • tornado.web.StaticFileHandler
  • tornado.web.RequestHandler

Methods

def set_extra_headers(self, path)

For subclass to add extra headers to the response

Source code
def set_extra_headers(self, path):
    self.set_header('Cache-Control',
                    'no-store, no-cache, must-revalidate, max-age=0')