From 68cc4099f3cfe95a35657623a82834cf1fe903ae Mon Sep 17 00:00:00 2001
From: alice grosch <a.grosch@fz-juelich.de>
Date: Tue, 14 Jan 2020 12:10:52 +0100
Subject: [PATCH] Rename extension

---
 jsfileupload/__init__.py                     | 10 +++
 jsfileupload/_frontend.py                    | 12 ++++
 jsfileupload/_version.py                     |  8 +++
 jsfileupload/nbextension/__init__.py         | 13 ++++
 jsfileupload/nbextension/static/extension.js | 17 +++++
 jsfileupload/tests/__init__.py               |  0
 jsfileupload/tests/conftest.py               | 54 ++++++++++++++
 jsfileupload/tests/test_example.py           | 14 ++++
 jsfileupload/tests/test_nbextension_path.py  | 15 ++++
 jsfileupload/upload_widget.py                | 74 ++++++++++++++++++++
 10 files changed, 217 insertions(+)
 create mode 100644 jsfileupload/__init__.py
 create mode 100644 jsfileupload/_frontend.py
 create mode 100644 jsfileupload/_version.py
 create mode 100644 jsfileupload/nbextension/__init__.py
 create mode 100644 jsfileupload/nbextension/static/extension.js
 create mode 100644 jsfileupload/tests/__init__.py
 create mode 100644 jsfileupload/tests/conftest.py
 create mode 100644 jsfileupload/tests/test_example.py
 create mode 100644 jsfileupload/tests/test_nbextension_path.py
 create mode 100644 jsfileupload/upload_widget.py

diff --git a/jsfileupload/__init__.py b/jsfileupload/__init__.py
new file mode 100644
index 0000000..bd7a852
--- /dev/null
+++ b/jsfileupload/__init__.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+# coding: utf-8
+
+# Copyright (c) Juelich Supercomputing Centre (JSC).
+# Distributed under the terms of the Modified BSD License.
+
+from .upload_widget import FileUpload
+from ._version import __version__, version_info
+
+from .nbextension import _jupyter_nbextension_paths
diff --git a/jsfileupload/_frontend.py b/jsfileupload/_frontend.py
new file mode 100644
index 0000000..a5bc604
--- /dev/null
+++ b/jsfileupload/_frontend.py
@@ -0,0 +1,12 @@
+#!/usr/bin/env python
+# coding: utf-8
+
+# Copyright (c) Juelich Supercomputing Centre (JSC).
+# Distributed under the terms of the Modified BSD License.
+
+"""
+Information about the frontend package of the widgets.
+"""
+
+module_name = "jsfileupload"
+module_version = "^0.1.0"
diff --git a/jsfileupload/_version.py b/jsfileupload/_version.py
new file mode 100644
index 0000000..fdb1be3
--- /dev/null
+++ b/jsfileupload/_version.py
@@ -0,0 +1,8 @@
+#!/usr/bin/env python
+# coding: utf-8
+
+# Copyright (c) Juelich Supercomputing Centre (JSC).
+# Distributed under the terms of the Modified BSD License.
+
+version_info = (0, 1, 0, 'dev')
+__version__ = ".".join(map(str, version_info))
diff --git a/jsfileupload/nbextension/__init__.py b/jsfileupload/nbextension/__init__.py
new file mode 100644
index 0000000..b525f3a
--- /dev/null
+++ b/jsfileupload/nbextension/__init__.py
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+# coding: utf-8
+
+# Copyright (c) Juelich Supercomputing Centre (JSC)
+# Distributed under the terms of the Modified BSD License.
+
+def _jupyter_nbextension_paths():
+    return [{
+        'section': 'notebook',
+        'src': 'nbextension/static',
+        'dest': 'jsfileupload',
+        'require': 'jsfileupload/extension'
+    }]
diff --git a/jsfileupload/nbextension/static/extension.js b/jsfileupload/nbextension/static/extension.js
new file mode 100644
index 0000000..fed306e
--- /dev/null
+++ b/jsfileupload/nbextension/static/extension.js
@@ -0,0 +1,17 @@
+// Entry point for the notebook bundle containing custom model definitions.
+//
+define(function() {
+    "use strict";
+
+    window['requirejs'].config({
+        map: {
+            '*': {
+                'jsfileupload': 'nbextensions/jsfileupload/index',
+            },
+        }
+    });
+    // Export the required load_ipython_extension function
+    return {
+        load_ipython_extension : function() {}
+    };
+});
diff --git a/jsfileupload/tests/__init__.py b/jsfileupload/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/jsfileupload/tests/conftest.py b/jsfileupload/tests/conftest.py
new file mode 100644
index 0000000..f4ecae6
--- /dev/null
+++ b/jsfileupload/tests/conftest.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+# coding: utf-8
+
+# Copyright (c) Juelich Supercomputing Centre (JSC).
+# Distributed under the terms of the Modified BSD License.
+
+import pytest
+
+from ipykernel.comm import Comm
+from ipywidgets import Widget
+
+class MockComm(Comm):
+    """A mock Comm object.
+
+    Can be used to inspect calls to Comm's open/send/close methods.
+    """
+    comm_id = 'a-b-c-d'
+    kernel = 'Truthy'
+
+    def __init__(self, *args, **kwargs):
+        self.log_open = []
+        self.log_send = []
+        self.log_close = []
+        super(MockComm, self).__init__(*args, **kwargs)
+
+    def open(self, *args, **kwargs):
+        self.log_open.append((args, kwargs))
+
+    def send(self, *args, **kwargs):
+        self.log_send.append((args, kwargs))
+
+    def close(self, *args, **kwargs):
+        self.log_close.append((args, kwargs))
+
+_widget_attrs = {}
+undefined = object()
+
+
+@pytest.fixture
+def mock_comm():
+    _widget_attrs['_comm_default'] = getattr(Widget, '_comm_default', undefined)
+    Widget._comm_default = lambda self: MockComm()
+    _widget_attrs['_ipython_display_'] = Widget._ipython_display_
+    def raise_not_implemented(*args, **kwargs):
+        raise NotImplementedError()
+    Widget._ipython_display_ = raise_not_implemented
+
+    yield MockComm()
+
+    for attr, value in _widget_attrs.items():
+        if value is undefined:
+            delattr(Widget, attr)
+        else:
+            setattr(Widget, attr, value)
diff --git a/jsfileupload/tests/test_example.py b/jsfileupload/tests/test_example.py
new file mode 100644
index 0000000..112621d
--- /dev/null
+++ b/jsfileupload/tests/test_example.py
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# coding: utf-8
+
+# Copyright (c) Juelich Supercomputing Centre (JSC).
+# Distributed under the terms of the Modified BSD License.
+
+import pytest
+
+from ..example import ExampleWidget
+
+
+def test_example_creation_blank():
+    w = ExampleWidget()
+    assert w.value == 'Hello World'
diff --git a/jsfileupload/tests/test_nbextension_path.py b/jsfileupload/tests/test_nbextension_path.py
new file mode 100644
index 0000000..9193605
--- /dev/null
+++ b/jsfileupload/tests/test_nbextension_path.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+# coding: utf-8
+
+# Copyright (c) Juelich Supercomputing Centre (JSC).
+# Distributed under the terms of the Modified BSD License.
+
+
+def test_nbextension_path():
+    # Check that magic function can be imported from package root:
+    from jsfileupload import _jupyter_nbextension_paths
+    # Ensure that it can be called without incident:
+    path = _jupyter_nbextension_paths()
+    # Some sanity checks:
+    assert len(path) == 1
+    assert isinstance(path[0], dict)
diff --git a/jsfileupload/upload_widget.py b/jsfileupload/upload_widget.py
new file mode 100644
index 0000000..5bbc0b5
--- /dev/null
+++ b/jsfileupload/upload_widget.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+# coding: utf-8
+
+# Copyright (c) Juelich Supercomputing Centre (JSC).
+# Distributed under the terms of the Modified BSD License.
+
+"""
+FileUpload Widget using the Jupyter Notebook Server RestAPI.
+Can handle large files by uploading files in chunks.
+"""
+from ipywidgets import ValueWidget
+from ipywidgets import register, widget_serialization
+from ipywidgets.widgets.trait_types import InstanceDict
+from ipywidgets.widgets.widget_button import ButtonStyle
+from ipywidgets.widgets.widget_description import DescriptionWidget
+
+from traitlets import (
+     default, Unicode, Dict, List, Int, Bool, Bytes, CaselessStrEnum
+)
+from ._frontend import module_name, module_version
+
+
+class FileUpload(DescriptionWidget, ValueWidget):
+    """FileUpload Widget. Uploads via the Jupyter Notebook Server RestAPI.
+
+    The widget is able to upload large files by uploading them in chunks.
+    The file contents will however not be directly available over the widget,
+    but will have to be read into the notebook seperately.
+    """
+    _model_name = Unicode('FileUploadModel').tag(sync=True)
+    _model_module = Unicode(module_name).tag(sync=True)
+    _model_module_version = Unicode(module_version).tag(sync=True)
+    _view_name = Unicode('FileUploadView').tag(sync=True)
+    _view_module = Unicode(module_name).tag(sync=True)
+    _view_module_version = Unicode(module_version).tag(sync=True)
+
+    accept = Unicode(help='File types to accept, empty string for all').tag(sync=True)
+    multiple = Bool(help='If True, allow for multiple files upload').tag(sync=True)
+    disabled = Bool(help='Enable or disable button').tag(sync=True)
+    icon = Unicode('folder', help="Font-awesome icon name, without the 'fa-' prefix.").tag(sync=True)
+    button_style = CaselessStrEnum(
+        values=['primary', 'success', 'info', 'warning', 'danger', ''], default_value='',
+        help="""Use a predefined styling for the button.""").tag(sync=True)
+    style = InstanceDict(ButtonStyle).tag(sync=True, **widget_serialization)
+    metadata = List(Dict(), help='List of file metadata').tag(sync=True)
+
+    # Needed for uploading using the Notebook Server RestAPI.
+    token = Unicode(help='Jupyter API token').tag(sync=True)
+    upload_url = Unicode('http://localhost:8888/api/contents/',
+                        help='http(s)://<notebook_url>/api/contents/<path>').tag(sync=True)
+
+    # Variables set on the JavaScript side.
+    files = List().tag(sync=True)
+    responses = List().tag(sync=True)
+    finished = Bool(False).tag(sync=True)
+    _upload = Bool(False).tag(sync=True)
+
+    
+    def __init__(self, upload_url='http://localhost:8888/api/contents/', token='', *args, **kwargs):
+        """Args:
+            upload_url (str): Jupyter notebook URL appended by api/contents/<path>/. Directories on <path> must already exist.
+            token (str): Jupyter notebook authentication token.
+        """
+        super(FileUpload, self).__init__(*args, **kwargs)
+        self.upload_url = upload_url
+        self.token = token
+
+    @default('description')
+    def _default_description(self):
+        return 'Browse'
+
+    def upload(self):
+        """Uploads file(s) via the JS fetch API."""
+        self._upload = True
\ No newline at end of file
-- 
GitLab