Skip to content

Commit

Permalink
EBR-79: add bucket widget and tests for the functionalities, add JUWE…
Browse files Browse the repository at this point in the history
…LS site for remote run
  • Loading branch information
915-Misan-Teodora committed Jul 12, 2024
1 parent eff4545 commit fec5ba2
Show file tree
Hide file tree
Showing 8 changed files with 232 additions and 28 deletions.
53 changes: 48 additions & 5 deletions notebooks/HeadWidget.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
"metadata": {},
"outputs": [],
"source": [
"config = HeadWidgetConfig(name='Cortex', color='beige')\n",
"config = HeadWidgetConfig(name='Cortex', color='#F5F5DC')\n",
"wid.add_datatype(surface, config)\n",
"config.__dict__"
]
Expand All @@ -92,7 +92,9 @@
"cell_type": "code",
"execution_count": null,
"id": "0b6c41e9-8a03-4996-929f-3ebbafadcc49",
"metadata": {},
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"display(wid)"
Expand Down Expand Up @@ -154,10 +156,43 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 1,
"id": "30dceb75-9940-4d80-8c3a-f134748411b9",
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"12-07-2024 02:54:08 - DEBUG - tvbwidgets - Package is not fully installed\n",
"12-07-2024 02:54:08 - DEBUG - tvbwidgets - Version read from the internal package.json file\n",
"12-07-2024 02:54:08 - INFO - tvbwidgets - Version: 2.0.3\n",
"Using matplotlib as 2D backend.\n",
"2024-07-12 14:54:18,814 - INFO - tvb.storage.h5.encryption.data_encryption_handler - Cannot import syncrypto library.\n",
"12-07-2024 02:54:18 - INFO - tvbwidgets.core.pse.parameters - ImportError: Dask dependency is not included, so this functionality won't be available\n",
"12-07-2024 02:54:18 - INFO - tvbwidgets.core.auth - We could not find Collab Auth Token, we will search for env CLB_AUTH variable\n",
"12-07-2024 02:54:18 - INFO - tvbwidgets.core.auth - We found Collab Auth in environment!\n",
"12-07-2024 02:54:20 - WARNING - tvb_ext_bucket.ebrains_drive_wrapper - Could not connect to EBRAINS to retrieve an auth token: No module named 'clb_nb_utils'\n",
"12-07-2024 02:54:20 - INFO - tvb_ext_bucket.ebrains_drive_wrapper - Will try to use the auth token defined by environment variable CLB_AUTH...\n",
"12-07-2024 02:54:20 - INFO - tvb_ext_bucket.ebrains_drive_wrapper - Successfully retrieved the auth token from environment variable CLB_AUTH!\n",
"12-07-2024 02:54:20 - INFO - tvb_ext_bucket.ebrains_drive_wrapper - Token retrieved successfully!\n"
]
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "5083b53dcb4548f1a7307643767f3327",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HeadBrowser(children=(StorageWidget(children=(VBox(), DriveWidget(children=(Dropdown(description='Repository',…"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from tvbwidgets.api import HeadBrowser\n",
"from IPython.core.display_functions import display\n",
Expand All @@ -172,6 +207,14 @@
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"id": "37c413d5-23ea-4954-9eba-cfc08ce8327a",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
Expand All @@ -190,7 +233,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.16"
"version": "3.9.19"
}
},
"nbformat": 4,
Expand Down
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ plotly==5.14.0
pythreejs
pyvista>=0.43.0
ipyreact>=0.4.1
requests
trame
trame-vuetify
trame-vtk
tvb-library
tvb-framework
tvb-ext-bucket
plotly-resampler
pyunicore>=1.0.0
traitlets>=5.7.1
Expand Down
20 changes: 10 additions & 10 deletions tvbwidgets/core/hpc/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ class HPCConfig(object):
resources: Resources
timeout = -1

STORAGES = {'DAINT-CSCS': 'HOME',
'JUSUF': 'PROJECT',
'JUDAC': 'PROJECT'}

PYTHON_DIRS = {'DAINT-CSCS': 'python3.9',
'JUSUF': 'python3.10',
'JUDAC': 'python3.10'}
MODULES = {'DAINT-CSCS': 'cray-python',
'JUSUF': 'Python',
'JUDAC': 'Python'}
STORAGES = {'JUSUF': 'PROJECT',
'JUDAC': 'PROJECT',
'JUWELS': 'HOME'}

PYTHON_DIRS = {'JUSUF': 'python3.10',
'JUDAC': 'python3.10',
'JUWELS': 'python3.11'}
MODULES = {'JUSUF': 'Python',
'JUDAC': 'Python',
'JUWELS': 'Python'}

def __post_init__(self):
if self.env_dir is None:
Expand Down
99 changes: 99 additions & 0 deletions tvbwidgets/tests/test_bucket_widget.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# -*- coding: utf-8 -*-
#
# "TheVirtualBrain - Widgets" package
#
# (c) 2022-2024, TVB Widgets Team
#
import os

import pytest
from ebrains_drive.exceptions import Unauthorized
from tvbwidgets.ui.bucket_widget import BucketWidget

DUMMY_CONTENT = b'test content'


class MockBucketDTO:
def __init__(self, name, role='', is_public=True):
self.name = name
self.role = role
self.is_public = is_public


class MockFile:
def __init__(self, name):
# type: (str) -> None
self.name = name

def get_content(self):
return DUMMY_CONTENT

def get_download_link(self):
return ''


class MockBucket:
def __init__(self, files_count=2, name='test_bucket', target='buckets', dataproxy_entity_name='test_bucket'):
self.name = name
self.files = [MockFile(f'file{number}') for number in range(files_count)]
self.target = target
self.dataproxy_entity_name = dataproxy_entity_name

def ls(self, prefix=''):
return [f for f in self.files if f.name.startswith(prefix)]


class MockBuckets:
def __init__(self):
self.buckets = {
'test_bucket': MockBucket()
}

def get_bucket(self, name):
try:
return self.buckets[name]
except KeyError:
raise Unauthorized('Unauthorized in tests')

def list_buckets(self):
return [MockBucketDTO(b) for b in self.buckets.keys()]


class MockBucketApiClient:
def __init__(self, token=''):
self.token = token
self.buckets = MockBuckets()


@pytest.fixture
def mock_client(mocker):
def mock_get_client(_):
return MockBucketApiClient()

mocker.patch('tvb_ext_bucket.ebrains_drive_wrapper.BucketWrapper.get_client', mock_get_client)


@pytest.fixture
def mock_requests_get(mocker):
mock_response = mocker.Mock()
mock_response.content = DUMMY_CONTENT
return mocker.patch('requests.get', return_value=mock_response)


def test_get_files_in_bucket(mock_client, mock_requests_get):
"""
tests that client returns list of files from bucket
"""
widget = BucketWidget()

# test observe event on buckets dropdown
assert widget.buckets_dropdown.value is None
assert widget.files_list.value is None
assert len(widget.files_list.options) == 0
widget.buckets_dropdown.value = widget.buckets_dropdown.options[0]
assert len(widget.files_list.options) == 2
widget.files_list.value = widget.files_list.options[0]

# test BucketWidget functions
assert widget.get_selected_file_path() == widget.buckets_dropdown.value + '/' + widget.files_list.value
assert widget.get_selected_file_content() == DUMMY_CONTENT
50 changes: 50 additions & 0 deletions tvbwidgets/ui/bucket_widget.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
#
# "TheVirtualBrain - Widgets" package
#
# (c) 2022-2024, TVB Widgets Team
#

import ipywidgets
import requests
from tvb_ext_bucket.ebrains_drive_wrapper import BucketWrapper
from tvbwidgets.ui.base_widget import TVBWidget


class BucketWidget(ipywidgets.VBox, TVBWidget):

def __init__(self, **kwargs):
TVBWidget.__init__(self, **kwargs)
self.client = BucketWrapper()

try:
all_buckets = self.client.list_buckets()
except Exception:
self.logger.error("Could not retrieve the list of available Buckets!")
all_buckets = []
layout = ipywidgets.Layout(width='400px')
self.buckets_dropdown = ipywidgets.Dropdown(description='Bucket', value=None,
options=all_buckets, layout=layout)
self.files_list = ipywidgets.Select(description='Files', value=None, disabled=False, layout=layout)

self.buckets_dropdown.observe(self.select_bucket, names='value')

self._parent_dir = None
self._map_names_to_files = dict()
ipywidgets.VBox.__init__(self, [self.buckets_dropdown, self.files_list], **kwargs)

def get_chosen_bucket(self):
return self.buckets_dropdown.value

def get_selected_file_path(self):
return self.buckets_dropdown.value + "/" + self.files_list.value

def get_selected_file_content(self):
path = self.files_list.value
downloadable_url = self.client.get_download_url(path, self.buckets_dropdown.value)
response = requests.get(downloadable_url)
return response.content

def select_bucket(self, _):
selected_bucket = self.buckets_dropdown.value
self.files_list.options = self.client.get_files_in_bucket(selected_bucket)
28 changes: 19 additions & 9 deletions tvbwidgets/ui/storage_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,38 @@
import ipywidgets

from tvbwidgets.ui.base_widget import TVBWidget
from tvbwidgets.ui.bucket_widget import BucketWidget
from tvbwidgets.ui.drive_widget import DriveWidget


class StorageWidget(ipywidgets.Tab, TVBWidget):

def __init__(self, collab=None, folder=None, **kwargs):
tab1 = ipywidgets.VBox()
tab2 = DriveWidget(collab, folder)
tab3 = ipywidgets.VBox()
def __init__(self, collab=None, folder=None, selected_storage=1, **kwargs):
self.tab1 = ipywidgets.VBox()
self.tab2 = DriveWidget(collab, folder)
self.tab3 = BucketWidget()

super().__init__([tab1, tab2, tab3], selected_index=1,
super().__init__([self.tab1, self.tab2, self.tab3], selected_index=selected_storage,
layout=ipywidgets.Layout(width='550px', height='200px'), **kwargs)

self.set_title(0, 'Current Selection')
self.set_title(1, 'Drive')
self.set_title(2, 'Bucket')
# TODO uniform API for all tabs
self.api = tab2
self.drive_api = self.tab2
self.bucket_api = self.tab3

def get_selected_file_content(self):
return self.api.get_selected_file_content()
api = self.retrieve_api()
return api.get_selected_file_content()

def get_selected_file_name(self):
filename = self.api.get_selected_file_path()
api = self.retrieve_api()
filename = api.get_selected_file_path()
return filename

def retrieve_api(self):
# TODO: add condition for Current Selection tab
if self.selected_index == 1:
return self.drive_api
else:
return self.bucket_api
4 changes: 2 additions & 2 deletions tvbwidgets/ui/ts/ts_widget_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@

class TimeSeriesBrowser(widgets.VBox, TVBWidgetWithBrowser):

def __init__(self, collab=None, folder=None):
super().__init__(**{'collab': collab, 'folder': folder})
def __init__(self, collab=None, folder=None, selected_storage=1):
super().__init__(**{'collab': collab, 'folder': folder, 'selected_storage': selected_storage})
btn_mne = widgets.Button(description='View TS with MNE')
btn_plotly = widgets.Button(description='View TS with Plotly')
self.buttons = widgets.HBox([btn_mne, btn_plotly], layout=widgets.Layout(margin="0px 0px 0px 20px"))
Expand Down
4 changes: 2 additions & 2 deletions tvbwidgets/ui/widget_with_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ class TVBWidgetWithBrowser(TVBWidget):
MSG_TEMPLATE = '<span style="color:{1};">{0}</span>'
MSG_COLOR = 'red'

def __init__(self, collab=None, folder=None):
def __init__(self, collab=None, folder=None, selected_storage=1):
super().__init__()
self.storage_widget = StorageWidget(collab, folder)
self.storage_widget = StorageWidget(collab, folder, selected_storage)
self.message_label = ipywidgets.HTML(layout=ipywidgets.Layout(height='25px'))

def __display_message(self, msg):
Expand Down

0 comments on commit fec5ba2

Please sign in to comment.