From f88db74922874e10436ded96f0b97ddc1ebc45c2 Mon Sep 17 00:00:00 2001
From: Philip ABBET <philip.abbet@idiap.ch>
Date: Wed, 23 Nov 2016 11:01:02 +0100
Subject: [PATCH] [website] Allows the forking of binary algorithms

---
 .../templates/algorithms/edition.html         | 20 ++++++++---
 beat/web/algorithms/tests/tests_api.py        | 35 ++++++++++++++++++-
 beat/web/algorithms/views.py                  | 31 +++++++++-------
 3 files changed, 68 insertions(+), 18 deletions(-)

diff --git a/beat/web/algorithms/templates/algorithms/edition.html b/beat/web/algorithms/templates/algorithms/edition.html
index 47fb65d44..92818d047 100644
--- a/beat/web/algorithms/templates/algorithms/edition.html
+++ b/beat/web/algorithms/templates/algorithms/edition.html
@@ -233,7 +233,7 @@ function setupEditor(algorithm, dataformats, libraries)
 
     var declaration = {};
 
-{% if not edition %}
+{% if not edition and not binary %}
     if (language_python_selector[0].checked)
       declaration.language = 'python';
     else
@@ -312,7 +312,11 @@ function setupEditor(algorithm, dataformats, libraries)
         window.location = data.object_view;
           {% endif %}
         {% else %}
-          $('.button_save')[0].shared_library.submit();
+          {% if edition %}
+        $('.button_save')[0].shared_library.submit();
+          {% else %}
+        window.location = data.object_view;
+          {% endif %}
         {% endif %}
       },
       error: function(jqXHR, textStatus, errorThrown) {
@@ -399,7 +403,7 @@ function setupEditor(algorithm, dataformats, libraries)
   </div>
 </div>
 
-{% if not edition %}
+{% if not edition and not binary %}
 <div class="row">
   <div class="col-sm-offset-1 col-sm-10 contribution_editor" style="display: none;">
     <label for="language_python">Language:</label>
@@ -566,7 +570,7 @@ function setupEditor(algorithm, dataformats, libraries)
     <p class="help">{{ messages.code|safe }}</p>
   </div>
 </div>
-{% else %}
+{% elif edition %}
 <div id="binary_file_selector" class="row">
   <div class="col-sm-offset-1 col-sm-10 contribution_editor" style="display: none;">
     <div class="alert alert-info">
@@ -582,6 +586,14 @@ function setupEditor(algorithm, dataformats, libraries)
     <p class="help">{{ messages.shared_library|safe }}</p>
   </div>
 </div>
+{% else %}
+<div class="row">
+  <div class="col-sm-offset-1 col-sm-10 contribution_editor" style="display: none;">
+    <div class="alert alert-info">
+      <i class="fa fa-info"></i> <span>The original algorithm is implemented in <strong>{{ algorithm_language_name }}</strong>, compiled as a <strong>shared library</strong>. The forked algorithm that will be created will copy the original shared library.</span>
+    </div>
+  </div>
+</div>
 {% endif %}
 
 {% smart_selector "smart_selector" %}
diff --git a/beat/web/algorithms/tests/tests_api.py b/beat/web/algorithms/tests/tests_api.py
index b9114418c..dd1a6e98b 100755
--- a/beat/web/algorithms/tests/tests_api.py
+++ b/beat/web/algorithms/tests/tests_api.py
@@ -930,7 +930,7 @@ class AlgorithmCreation(AlgorithmsAPIBase):
             json.dumps({
                 'name': 'valid-name1',
                 'description': 'blah',
-                'declaration':AlgorithmsAPIBase.CXX_DECLARATION,
+                'declaration': AlgorithmsAPIBase.CXX_DECLARATION,
             }), content_type='application/json')
 
         url = reverse('api_algorithms:object', args=['jackdoe', 'valid-name1', 1])
@@ -954,6 +954,39 @@ class AlgorithmCreation(AlgorithmsAPIBase):
         self.checkAlgorithm(algorithm, declaration=AlgorithmsAPIBase.CXX_DECLARATION, code=None)
 
 
+    def test_forked_cxx_algorithm(self):
+        self.client.login(username='jackdoe', password='1234')
+
+        response = self.client.post(self.url,
+            json.dumps({
+                'name': 'valid-name1',
+                'description': 'blah',
+                'declaration': AlgorithmsAPIBase.CXX_DECLARATION,
+                'fork_of': 'jackdoe/binary_personal/1',
+            }), content_type='application/json')
+
+        url = reverse('api_algorithms:object', args=['jackdoe', 'valid-name1', 1])
+        content = self.checkResponse(response, 201,
+                                     content_type='application/json',
+                                     location=url)
+
+        self.assertTrue(isinstance(content, dict))
+        self.assertEqual(content['name'], 'valid-name1')
+        self.assertTrue(content['url'].endswith(url))
+
+        try:
+            algorithm = Algorithm.objects.get(author__username='jackdoe', name='valid-name1')
+        except:
+            self.assertTrue(False)
+
+        self.assertEqual(algorithm.short_description, '')
+        self.assertEqual(algorithm.description, 'blah')
+        self.assertEqual(algorithm.language, Code.CXX)
+        self.assertTrue(algorithm.valid())
+        self.checkAlgorithm(algorithm, declaration=AlgorithmsAPIBase.CXX_DECLARATION, code=None)
+
+        self.assertEqual(algorithm.source_code, algorithm.fork_of.source_code)
+
 
 class AlgorithmUpdate(AlgorithmsAPIBase):
     def setUp(self):
diff --git a/beat/web/algorithms/views.py b/beat/web/algorithms/views.py
index 08cb8eced..d7a0c9a58 100755
--- a/beat/web/algorithms/views.py
+++ b/beat/web/algorithms/views.py
@@ -118,21 +118,26 @@ def fork(request, author, name, version):
 
     description = fork_of.description
 
-    parameters = {'original_author':   author,
-                  'algorithm_author':  request.user.username,
-                  'algorithm_name':    name,
-                  'algorithm_version': fork_of.version,
-                  'source_code':       fork_of.source_code_file.read(),
-                  'declaration':       fork_of.declaration_file.read().replace('\n', ''),
-                  'short_description': fork_of.short_description,
-                  'description':       description.replace('\n', '\\n'),
-                  'html_description':  restructuredtext(description).replace('\n', ''),
-                  'messages':          Messages,
-                  'fork_of':           fork_of,
-                  'edition':           False,
-                  'plot_account':      settings.PLOT_ACCOUNT,
+    parameters = {'original_author':         author,
+                  'algorithm_author':        request.user.username,
+                  'algorithm_name':          name,
+                  'algorithm_version':       fork_of.version,
+                  'algorithm_language':      fork_of.json_language,
+                  'algorithm_language_name': fork_of.language_fullname(),
+                  'declaration':             fork_of.declaration_file.read().replace('\n', ''),
+                  'short_description':       fork_of.short_description,
+                  'description':             description.replace('\n', '\\n'),
+                  'html_description':        restructuredtext(description).replace('\n', ''),
+                  'messages':                Messages,
+                  'fork_of':                 fork_of,
+                  'edition':                 False,
+                  'binary':                  fork_of.is_binary(),
+                  'plot_account':            settings.PLOT_ACCOUNT,
                  }
 
+    if not fork_of.is_binary():
+        parameters['source_code'] = fork_of.source_code_file.read()
+
     return render_to_response('algorithms/edition.html',
                               parameters,
                               context_instance=RequestContext(request))
-- 
GitLab