Simple Sage Server API

Simple Sage Server API

This module provides a very simple API for interacting with a Sage session over HTTP. It runs as part of the notebook server.

Note

The exact data in the JSON header may vary over time (for example, further data may be added), but should remain backwards compatible if it is being parsed as JSON data.

TESTS:

Here’s a usage example which demonstrates all the features of this server/API.

Start the notebook server.:

sage: from sage.server.misc import find_next_available_port
sage: port = find_next_available_port(9000, verbose=False)
sage: from sage.server.notebook.notebook_object import test_notebook
sage: passwd = str(randint(1,1<<128))
sage: nb = test_notebook(passwd, secure=False, address='localhost', port=port, verbose=True) #doctest: +ELLIPSIS 
...
Notebook started.

Now here’s what you can do on the client side. Import urllib and define a convenience function:

sage: import urllib, re
sage: def get_url(url): h = urllib.urlopen(url); data = h.read(); h.close(); return data

Login to a new session:

sage: sleep(1)
sage: login_page = get_url('http://localhost:%s/simple/login?username=admin&password=%s' % (port, passwd))
sage: print login_page # random session id
{
"session": "2afee978c09b3d666c88b9b845c69608"
}
___S_A_G_E___
sage: session = re.match(r'.*"session": "([^"]*)"', login_page, re.DOTALL).groups()[0]

Run a command:

sage: sleep(0.5)
sage: print get_url('http://localhost:%s/simple/compute?session=%s&code=2*2&timeout=60' % (port, session))
{
"status": "done",
"files": [],
"cell_id": 1
}
___S_A_G_E___
4

This API returns information as a string, the first part of which is a JSON-encoded dictionary. The second part – after the separator ___S_A_G_E___ – is the text of the output. To parse output, you just need to split the string and parse the JSON data into your local format.

Do a longer-running example:

sage: n = next_prime(10^25)*next_prime(10^30)
sage: print get_url('http://localhost:%s/simple/compute?session=%s&code=factor(%s)&timeout=0.1' % (port, session, n))
{
"status": "computing",
"files": [],
"cell_id": 2
}
___S_A_G_E___

Get the status of the computation:

sage: print get_url('http://localhost:%s/simple/status?session=%s&cell=2' % (port, session))
{
"status": "computing",
"files": [],
"cell_id": 2
}
___S_A_G_E___

Interrupt the computation:

sage: _ = get_url('http://localhost:%s/simple/interrupt?session=%s' % (port, session))

You can download files that your code creates on the remote server. Here we write a file, and then download it to our client:

sage: code = "h = open('a.txt', 'w'); h.write('test'); h.close()"
sage: print get_url('http://localhost:%s/simple/compute?session=%s&code=%s' % (port, session, urllib.quote(code)))
{
"status": "done",
"files": ["a.txt"],
"cell_id": 3
}
___S_A_G_E___

sage: print get_url('http://localhost:%s/simple/file?session=%s&cell=3&file=a.txt' % (port, session))
test

When you are done, log out:

sage: _ = get_url('http://localhost:%s/simple/logout?session=%s' % (port, session))
sage: nb.dispose()

Warning

It’s important that your code log out the session. Otherwise, it is very easy to create an unintentional denial-of-service attack by having the server accumulate a large number of idle worksheets which consume a lot of memory and make the server unresponsive!

class sagenb.simple.twist.CellResource

Bases: twisted.web2.resource.Resource

check_comp(cell, start_time, timeout, looper_list)
render_cell_result(looper)
start_comp(cell, timeout)
class sagenb.simple.twist.ComputeResource

Bases: sagenb.simple.twist.CellResource

render(ctx)
class sagenb.simple.twist.FileResource

Bases: twisted.web2.resource.Resource

This differs from the rest as it does not print a header, just the raw file data.

render(ctx)
class sagenb.simple.twist.InterruptResource

Bases: twisted.web2.resource.Resource

render(ctx)
class sagenb.simple.twist.LoginResource

Bases: twisted.web2.resource.Resource

render(ctx)
class sagenb.simple.twist.LogoutResource

Bases: twisted.web2.resource.Resource

render(ctx)
class sagenb.simple.twist.RestartResource

Bases: twisted.web2.resource.Resource

render(ctx)
class sagenb.simple.twist.SessionObject(id, username, worksheet, timeout=5)
get_status()

Return a dictionary to be returned (in JSON format) representing the status of self.

TEST:

sage: from sage.server.simple.twist import SessionObject
sage: s = SessionObject(id=1, username=None, worksheet=None)
sage: s.get_status()
{'session': 1}
class sagenb.simple.twist.SimpleServer

Bases: twisted.web2.resource.Resource

render(ctx)
class sagenb.simple.twist.StatusResource

Bases: sagenb.simple.twist.CellResource

render(ctx)
sagenb.simple.twist.late_import()
sagenb.simple.twist.simple_jsonize(data)

This will be replaced by a JSON spkg when Python 2.6 gets into Sage.

EXAMPLES:

sage: from sage.server.simple.twist import simple_jsonize
sage: print simple_jsonize({'a': [1,2,3], 'b': "yep"})
{ "a": [1, 2, 3], "b": "yep" }

Previous topic

The Sage Notebook Twisted Web Server

Next topic

Sage Trac Server

This Page