Skip to content
Snippets Groups Projects
Commit 1e6ea411 authored by Steffen Vogel's avatar Steffen Vogel :santa_tone2:
Browse files

Merge branch 'submission' into master

parents 97a502f5 8705b899
No related branches found
No related tags found
1 merge request!5WIP: Add new submission class which will communicate with the RWTH JupyterHub service
Pipeline #349915 passed
%% Cell type:markdown id: tags:
# Example notebooks for using the submission service
%% Cell type:code id: tags:
``` python
from rwth_nb.misc.submission import Submission
from random import randint
from pprint import pprint
sub = Submission('test_realm')
```
%% Cell type:code id: tags:
``` python
print('\nCreate some random submissions...')
for i in range(5):
sub.submit({
'random_integer': randint(1, 100)
})
```
%% Cell type:markdown id: tags:
## Admin actions
For performing admin actions the user must own the role manager-{profile_slug} or submission-{realm}
%% Cell type:code id: tags:
``` python
print('\nAll submissions:')
pprint(sub.get_all())
print('\nDelete all submissions')
sub.delete_all()
print('\nAll submissions:')
pprint(sub.get_all())
```
%% Cell type:markdown id: tags:
## User actions
%% Cell type:code id: tags:
``` python
if sub.is_submitted():
print('\nEvaluation already submitted')
else:
print('\nNothing submitted yet!')
sub.submit({'test': [1, 2, 3]})
if sub.is_submitted():
print('\nNow it is submitted!:')
pprint(sub.get())
print('\nMy submissions:')
mysubs = sub.get()
print(mysubs)
ident = mysubs[0]['id']
print(f'\nMy submission ID: {ident}')
print(f'\nDeleting my submission with ID: {ident}')
sub.delete(ident=ident)
print('\nMy submissions:')
mysubs = sub.get()
print(mysubs)
```
%% Cell type:markdown id: tags:
## Submitting whole notebooks
The following cell submits the current notebook contents
%% Cell type:code id: tags:
``` python
sub.submit_notebook()
```
%% Cell type:markdown id: tags:
The following cell fetches all submitted notebooks in the current realm by the current user and stores them in the current directory
%% Cell type:code id: tags:
``` python
sub.fetch_notebook(subdir='fetched_notebooks', prefix='a1')
```
import os
import requests
from IPython.lib import kernel
from notebook import notebookapp
def get_contents():
servers = list(notebookapp.list_running_servers())
token = servers[0]['token']
api_url = servers[0]['url'] + 'api'
connection_file_path = kernel.get_connection_file()
connection_file = os.path.basename(connection_file_path)
kernel_id = connection_file.split('-', 1)[1].split('.')[0]
headers = {
'Authorization': f'token {token}'
}
r = requests.request('GET', f'{api_url}/sessions', headers=headers)
for session in r.json():
if session['kernel']['id'] == kernel_id:
path = session['notebook']['path']
r = requests.request('GET', f'{api_url}/contents/{path}', headers=headers)
return r.json()
\ No newline at end of file
import requests
import json
import os
import datetime as dt
import rwth_nb.misc.notebook as notebook
class Submission:
"""Submit and retrieve submissions to RWTH JupyterHub Service"""
def __init__(self, realm):
self.realm = realm
self.profile = os.environ.get('JUPYTERHUB_PROFILE')
self.token = os.environ.get('JUPYTERHUB_API_TOKEN')
self.service_url = 'http://proxy-public.jhub/services/submission'
if self.token is None or self.profile is None:
raise Exception('Submissions only work inside the RWTHjupyter cluster!')
def url(self, user='me', ident=None):
url = f'{self.service_url}/{self.profile}/{self.realm}'
if user is not None:
url += f'/{user}'
if ident is not None:
url += f'/{ident}'
return url
def headers(self):
return {
'Authorization': f'token {self.token}'
}
def _parse_get(self, response):
payload = response.json()
if 'data' in payload:
for data in payload['data']:
if 'submitted' in data:
data['submitted'] = dt.datetime.fromisoformat(data['submitted'])
return payload
def submit(self, data):
"""Submit some arbitrary JSON payload"""
r = requests.request('POST',
url=self.url(user=None),
data=json.dumps(data),
headers=self.headers())
r.raise_for_status()
def submit_notebook(self):
"""Submit the notebook as JSON"""
nb = notebook.get_contents()
self.submit(nb)
def is_submitted(self):
"""Check if the user has already submitted something to this realm"""
s = self.get()
return len(s) > 0
def get(self, user='me', ident=None, limit=None):
"""Get all submissions for a user"""
params = {}
if limit is not None:
params['limit'] = limit
r = requests.request('GET', url=self.url(user, ident),
headers=self.headers(),
params=params)
r.raise_for_status()
j = self._parse_get(r)
return j['submissions']
def fetch_notebook(self, user='me', ident=None, limit=None, subdir=None, prefix=None):
subs = self.get(user, ident, limit)
for sub in subs:
nb = sub.pop('data')
realm = sub['realm']
submitter = sub['submitter']
id = sub['id']
name, ext = os.path.splitext(nb['name'])
# Add submission details as metadata to the notebook
nb['content']['metadata']['submission'] = sub
fn = f'{name}_{realm}_{submitter}-{id}{ext}'
if prefix:
fn = f'{prefix}_{fn}'
if subdir:
os.makedirs(subdir)
fn = f'{subdir}/{fn}'
with open(fn, 'w+') as nb_file:
json.dump(nb['content'], nb_file)
def fetch_all_notebooks(self):
"""Get all submissions in a realm"""
return self.fetch_notebook(user=None)
def delete(self, user='me', ident=None):
"""Delete the users submission"""
r = requests.request('DELETE', url=self.url(user, ident),
headers=self.headers())
r.raise_for_status()
def get_all(self):
"""Get all submissions in a realm"""
return self.get(user=None)
def delete_all(self):
"""Delete all submissions"""
return self.delete(user=None)
\ No newline at end of file
# Testing
from rwth_nb.misc.submission import Submission
#os.environ['JUPYTERHUB_API_TOKEN'] = 'xxx'
if __name__ == '__main__':
sub = Submission('test_realm')
is_submitted = sub.is_submitted()
if is_submitted:
print('Evaluation already submitted')
else:
sub.submit({
'test': [1, 2, 3]
})
print('All submissions:')
for s in sub.get_all():
print(s)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment