|
@@ -0,0 +1,126 @@
|
|
|
|
+import sys
|
|
|
|
+import time
|
|
|
|
+
|
|
|
|
+import requests
|
|
|
|
+
|
|
|
|
+from metakernel import MetaKernel
|
|
|
|
+
|
|
|
|
+class EngineError(Exception):
|
|
|
|
+ pass
|
|
|
|
+
|
|
|
|
+class Engine:
|
|
|
|
+ API_URL = 'https://sylv.txlyre.website/api'
|
|
|
|
+
|
|
|
|
+ def __init__(self):
|
|
|
|
+ resp = requests.get(
|
|
|
|
+ f'{Engine.API_URL}/new'
|
|
|
|
+ ).json()
|
|
|
|
+
|
|
|
|
+ self.uid = resp['data']['session_uid']
|
|
|
|
+
|
|
|
|
+ def api(self, method, **data):
|
|
|
|
+ data['session_uid'] = self.uid
|
|
|
|
+
|
|
|
|
+ resp = requests.post(
|
|
|
|
+ f'{Engine.API_URL}/{method}',
|
|
|
|
+ json=data
|
|
|
|
+ ).json()
|
|
|
|
+
|
|
|
|
+ if resp['status'] != 'ok':
|
|
|
|
+ raise EngineError(resp['message'])
|
|
|
|
+
|
|
|
|
+ return resp['data']
|
|
|
|
+
|
|
|
|
+class Latex(object):
|
|
|
|
+ def __init__(self, text):
|
|
|
|
+ self.text = text
|
|
|
|
+
|
|
|
|
+ def _repr_latex_(self):
|
|
|
|
+ return f'$$\n{self.text}\n$$'
|
|
|
|
+
|
|
|
|
+class SVG(object):
|
|
|
|
+ def __init__(self, text):
|
|
|
|
+ self.text = text
|
|
|
|
+
|
|
|
|
+ def _repr_svg_(self):
|
|
|
|
+ return self.text
|
|
|
|
+
|
|
|
|
+class SylvyKernel(MetaKernel):
|
|
|
|
+ implementation = 'sylvy'
|
|
|
|
+ implementation_version = '0.1'
|
|
|
|
+ language = 'sylvy'
|
|
|
|
+ language_version = 'beta-alef'
|
|
|
|
+ banner = 'Sylvy CAS.'
|
|
|
|
+ language_info = {
|
|
|
|
+ 'name': 'sylvy',
|
|
|
|
+ 'mimetype': 'text/x-sylvy',
|
|
|
|
+ 'codemirror_mode': {
|
|
|
|
+ 'name': 'r'
|
|
|
|
+ },
|
|
|
|
+ 'pygments_lexer': 'r'
|
|
|
|
+ }
|
|
|
|
+ kernel_json = {
|
|
|
|
+ "argv": [sys.executable, "-m", "SylvyKernel", "-f", "{connection_file}"],
|
|
|
|
+ "display_name": "Sylvy CAS",
|
|
|
|
+ "language": "sylvy",
|
|
|
|
+ "name": "SylvyKernel",
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ _engine = None
|
|
|
|
+
|
|
|
|
+ def do_shutdown(self, restart):
|
|
|
|
+ if self._engine:
|
|
|
|
+ self._engine.api('discard')
|
|
|
|
+
|
|
|
|
+ self._engine = None
|
|
|
|
+
|
|
|
|
+ def do_execute_direct(self, code):
|
|
|
|
+ if not code.strip():
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ if not self._engine:
|
|
|
|
+ self._engine = Engine()
|
|
|
|
+
|
|
|
|
+ data = self._engine.api(
|
|
|
|
+ 'compute',
|
|
|
|
+ program=code
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ task_uid = data['task_uid']
|
|
|
|
+
|
|
|
|
+ result = None
|
|
|
|
+ while True:
|
|
|
|
+ data = self._engine.api(
|
|
|
|
+ 'results'
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ if data['count']:
|
|
|
|
+ result = data['results'][0]
|
|
|
|
+
|
|
|
|
+ break
|
|
|
|
+
|
|
|
|
+ time.sleep(0.5)
|
|
|
|
+
|
|
|
|
+ if result:
|
|
|
|
+ if result['status'] == 'ERROR':
|
|
|
|
+ self.Error(result['stdout'])
|
|
|
|
+
|
|
|
|
+ return
|
|
|
|
+ elif result['status'] == 'TIMEOUT':
|
|
|
|
+ self.Error('Execution timed out.')
|
|
|
|
+
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ if result['stdout'].strip():
|
|
|
|
+ self.Print(result['stdout'])
|
|
|
|
+
|
|
|
|
+ self.Display(Latex(result['output']))
|
|
|
|
+
|
|
|
|
+ if result['plots']:
|
|
|
|
+ for plot_id in result['plots']:
|
|
|
|
+ plot = self._engine.api(
|
|
|
|
+ 'plot',
|
|
|
|
+ plot_id=plot_id
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ self.Display(SVG(plot['svg']))
|