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!
Bases: twisted.web2.resource.Resource
Bases: sagenb.simple.twist.CellResource
Bases: twisted.web2.resource.Resource
This differs from the rest as it does not print a header, just the raw file data.
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}
Bases: sagenb.simple.twist.CellResource
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" }