From b6459d4ed59fae90de78eb6c04b6e50ab69e96f4 Mon Sep 17 00:00:00 2001
From: Philip ABBET <philip.abbet@idiap.ch>
Date: Thu, 10 Nov 2016 16:10:42 +0100
Subject: [PATCH] [algorithms, api] Add support for retrieving binary
 algorithms

---
 beat/web/algorithms/api.py                    |  44 +++
 beat/web/algorithms/api_urls.py               |  10 +
 .../algorithms/migrations/0002_cxx_backend.py |  20 +
 beat/web/algorithms/tests/core.py             | 160 ++++++++
 beat/web/algorithms/tests/tests_api.py        | 366 ++++++++++++++++--
 beat/web/code/api.py                          |   2 +-
 beat/web/code/models.py                       |  28 +-
 beat/web/code/serializers.py                  |   6 +-
 beat/web/common/models.py                     |  15 +-
 .../libraries/migrations/0002_cxx_backend.py  |  20 +
 .../plotters/migrations/0002_cxx_backend.py   |  20 +
 11 files changed, 631 insertions(+), 60 deletions(-)
 mode change 100644 => 100755 beat/web/algorithms/api.py
 mode change 100644 => 100755 beat/web/algorithms/api_urls.py
 create mode 100644 beat/web/algorithms/migrations/0002_cxx_backend.py
 mode change 100644 => 100755 beat/web/algorithms/tests/core.py
 mode change 100644 => 100755 beat/web/algorithms/tests/tests_api.py
 mode change 100644 => 100755 beat/web/code/api.py
 mode change 100644 => 100755 beat/web/code/models.py
 mode change 100644 => 100755 beat/web/code/serializers.py
 mode change 100644 => 100755 beat/web/common/models.py
 create mode 100644 beat/web/libraries/migrations/0002_cxx_backend.py
 create mode 100644 beat/web/plotters/migrations/0002_cxx_backend.py

diff --git a/beat/web/algorithms/api.py b/beat/web/algorithms/api.py
old mode 100644
new mode 100755
index e9b7c7723..f0f4912bf
--- a/beat/web/algorithms/api.py
+++ b/beat/web/algorithms/api.py
@@ -25,6 +25,9 @@
 #                                                                             #
 ###############################################################################
 
+from django.http import Http404
+from django.http import HttpResponse
+
 from .models import Algorithm
 from .serializers import AlgorithmSerializer
 from .serializers import FullAlgorithmSerializer
@@ -118,3 +121,44 @@ class DiffAlgorithmView(DiffView):
     """
     model = Algorithm
     serializer_class = CodeDiffSerializer
+
+
+#----------------------------------------------------------
+
+
+def binary(request, author_name, object_name, version=None):
+    """Returns the shared library of a binary algorithm
+    """
+
+    # Retrieves the algorithm
+    if version:
+        algorithm = get_object_or_404(
+                Algorithm,
+                author__username__iexact=author_name,
+                name__iexact=object_name,
+                version=int(version),
+                )
+    else:
+        algorithm = Algorithm.objects.filter(author__username__iexact=author_name,
+                name__iexact=object_name).order_by('-version')
+        if not algorithm:
+            raise Http404()
+        else:
+            algorithm = algorithm[0]
+
+    (has_access, _, accessibility) = algorithm.accessibility_for(request.user, without_usable=True)
+
+    if not has_access:
+        raise Http404()
+
+    if not algorithm.is_binary():
+        raise Http404()
+
+    binary_data = algorithm.source_code
+
+    response = HttpResponse(binary_data, content_type='application/octet-stream')
+
+    response['Content-Length'] = len(binary_data)
+    response['Content-Disposition'] = 'attachment; filename=%d.so' % algorithm.version
+
+    return response
diff --git a/beat/web/algorithms/api_urls.py b/beat/web/algorithms/api_urls.py
old mode 100644
new mode 100755
index d12f252f7..c0e84a2a1
--- a/beat/web/algorithms/api_urls.py
+++ b/beat/web/algorithms/api_urls.py
@@ -66,4 +66,14 @@ urlpatterns = [
             name='object',
             ),
 
+        url(r'^(?P<author_name>\w+)/(?P<object_name>[-\w]+)/(?P<version>\d+)/binary/$',
+            api.binary,
+            name='binary',
+            ),
+
+        url(r'^(?P<author_name>\w+)/(?P<object_name>[-\w]+)/binary/$',
+            api.binary,
+            name='binary',
+            ),
+
         ]
diff --git a/beat/web/algorithms/migrations/0002_cxx_backend.py b/beat/web/algorithms/migrations/0002_cxx_backend.py
new file mode 100644
index 000000000..abe1969ad
--- /dev/null
+++ b/beat/web/algorithms/migrations/0002_cxx_backend.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.11 on 2016-11-09 11:05
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('algorithms', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='algorithm',
+            name='language',
+            field=models.CharField(choices=[(b'U', b'Unknown'), (b'C', b'C++'), (b'M', b'Matlab'), (b'P', b'Python'), (b'R', b'R')], default=b'P', max_length=1),
+        ),
+    ]
diff --git a/beat/web/algorithms/tests/core.py b/beat/web/algorithms/tests/core.py
old mode 100644
new mode 100755
index 2f3c375bb..421f05508
--- a/beat/web/algorithms/tests/core.py
+++ b/beat/web/algorithms/tests/core.py
@@ -188,6 +188,7 @@ class AlgorithmsCreationFunction(AlgorithmsBaseTestCase):
 
 
 class AlgorithmsTestCase(AlgorithmsBaseTestCase):
+
     def setup_algorithms(self, declaration, code):
         user1 = User.objects.get(username='jackdoe')
         user2 = User.objects.get(username='johndoe')
@@ -304,6 +305,138 @@ class AlgorithmsTestCase(AlgorithmsBaseTestCase):
         algorithm.share(public=True)
 
 
+    def setup_binary_algorithms(self, declaration, binary_data):
+        user1 = User.objects.get(username='jackdoe')
+        user2 = User.objects.get(username='johndoe')
+
+        team1 = Team.objects.get(name="teamdoe", owner=user1)
+        team2 = Team.objects.get(name="teamdoe2", owner=user1)
+
+        # Personal
+        (algorithm, errors) = Algorithm.objects.create_algorithm(
+            author=user1,
+            name='binary_personal',
+            short_description='',
+            declaration=declaration,
+            )
+        assert algorithm, errors
+
+        algorithm.source_code = binary_data
+        algorithm.save()
+
+        # Usable by one user
+        (algorithm, errors) = Algorithm.objects.create_algorithm(
+            author=user1,
+            name='binary_usable_by_one_user',
+            short_description='',
+            declaration=declaration,
+            )
+        assert algorithm, errors
+
+        algorithm.source_code = binary_data
+        algorithm.save()
+
+        algorithm.share(public=False, users=[user2])
+
+        # Usable by one team
+        (algorithm, errors) = Algorithm.objects.create_algorithm(
+            author=user1,
+            name='binary_usable_by_one_team',
+            short_description='',
+            declaration=declaration,
+            )
+        assert algorithm, errors
+
+        algorithm.source_code = binary_data
+        algorithm.save()
+
+        algorithm.share(public=False, teams=[team1])
+
+        # Usable by teams
+        (algorithm, errors) = Algorithm.objects.create_algorithm(
+            author=user1,
+            name='binary_usable_by_teams',
+            short_description='',
+            declaration=declaration,
+            )
+        assert algorithm, errors
+
+        algorithm.source_code = binary_data
+        algorithm.save()
+
+        algorithm.share(public=False, teams=[team1, team2])
+
+        # Usable by all
+        (algorithm, errors) = Algorithm.objects.create_algorithm(
+            author=user1,
+            name='binary_usable_by_all',
+            short_description='',
+            declaration=declaration,
+            )
+        assert algorithm, errors
+
+        algorithm.source_code = binary_data
+        algorithm.save()
+
+        algorithm.share(public=False)
+
+        # Accessible to one user
+        (algorithm, errors) = Algorithm.objects.create_algorithm(
+            author=user1,
+            name='binary_public_for_one_user',
+            short_description='',
+            declaration=declaration,
+            )
+        assert algorithm, errors
+
+        algorithm.source_code = binary_data
+        algorithm.save()
+
+        algorithm.share(public=True, users=[user2])
+
+        # Accessible to one team
+        (algorithm, errors) = Algorithm.objects.create_algorithm(
+            author=user1,
+            name='binary_public_for_one_team',
+            short_description='',
+            declaration=declaration,
+            )
+        assert algorithm, errors
+
+        algorithm.source_code = binary_data
+        algorithm.save()
+
+        algorithm.share(public=True, teams=[team1])
+
+        # Accessible to teams
+        (algorithm, errors) = Algorithm.objects.create_algorithm(
+            author=user1,
+            name='binary_public_for_teams',
+            short_description='',
+            declaration=declaration,
+            )
+        assert algorithm, errors
+
+        algorithm.source_code = binary_data
+        algorithm.save()
+
+        algorithm.share(public=True, teams=[team1, team2])
+
+        # Accessible to all
+        (algorithm, errors) = Algorithm.objects.create_algorithm(
+            author=user1,
+            name='binary_public_for_all',
+            short_description='',
+            declaration=declaration,
+            )
+        assert algorithm, errors
+
+        algorithm.source_code = binary_data
+        algorithm.save()
+
+        algorithm.share(public=True)
+
+
 class AlgorithmsAccessibilityFunctionsBase(AlgorithmsTestCase):
 
     def setUp(self):
@@ -379,6 +512,27 @@ class AlgorithmsAPIBase(AlgorithmsTestCase):
 
     JSON_DECLARATION = json.loads(DECLARATION)
 
+    CXX_DECLARATION = """{
+  "language": "cxx",
+  "splittable": false,
+  "groups": [
+    {
+      "name": "channel1",
+      "inputs": {
+        "a": { "type": "johndoe/single_integer/1" },
+        "b": { "type": "johndoe/single_integer/1" }
+      },
+      "outputs": {
+        "sum": { "type": "johndoe/single_integer/1" }
+      }
+    }
+  ],
+  "parameters": {
+  }
+}"""
+
+    JSON_CXX_DECLARATION = json.loads(CXX_DECLARATION)
+
     CODE = """class Algorithm:
 
     def process(self, inputs, outputs):
@@ -405,6 +559,9 @@ class AlgorithmsAPIBase(AlgorithmsTestCase):
   }
 }"""
 
+    BINARY = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" \
+             "\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"
+
 
     def setUp(self):
         super(AlgorithmsAPIBase, self).setUp()
@@ -446,3 +603,6 @@ class AlgorithmsAPIBase(AlgorithmsTestCase):
         algorithm.previous_version = None
         algorithm.fork_of = Algorithm.objects.get(name='public_for_all')
         algorithm.save()
+
+        self.setup_binary_algorithms(AlgorithmsAPIBase.CXX_DECLARATION,
+                                     AlgorithmsAPIBase.BINARY)
diff --git a/beat/web/algorithms/tests/tests_api.py b/beat/web/algorithms/tests/tests_api.py
old mode 100644
new mode 100755
index 749fd77b8..7d9db6b7d
--- a/beat/web/algorithms/tests/tests_api.py
+++ b/beat/web/algorithms/tests/tests_api.py
@@ -50,18 +50,34 @@ class AlgorithmsListRetrieval(AlgorithmsAPIBase):
         content = self.checkResponse(response, 200, content_type='application/json')
 
         self.assertTrue(isinstance(content, list))
-        self.assertEqual(len(content), 2)
+        self.assertEqual(len(content), 4)
 
         algorithm = filter(lambda x: x['name'] == 'jackdoe/public_for_all/1', content)[0]
         self.assertEqual(algorithm['short_description'], '')
         self.assertTrue(algorithm['fork_of'] is None)
         self.assertEqual(algorithm['accessibility'], 'public')
+        self.assertEqual(algorithm['language'], 'python')
         self.assertFalse(algorithm.has_key('is_owner'))
 
         algorithm = filter(lambda x: x['name'] == 'jackdoe/usable_by_all/1', content)[0]
         self.assertEqual(algorithm['short_description'], '')
         self.assertTrue(algorithm['fork_of'] is None)
         self.assertEqual(algorithm['accessibility'], 'confidential')
+        self.assertEqual(algorithm['language'], 'python')
+        self.assertFalse(algorithm.has_key('is_owner'))
+
+        algorithm = filter(lambda x: x['name'] == 'jackdoe/binary_public_for_all/1', content)[0]
+        self.assertEqual(algorithm['short_description'], '')
+        self.assertTrue(algorithm['fork_of'] is None)
+        self.assertEqual(algorithm['accessibility'], 'public')
+        self.assertEqual(algorithm['language'], 'cxx')
+        self.assertFalse(algorithm.has_key('is_owner'))
+
+        algorithm = filter(lambda x: x['name'] == 'jackdoe/binary_usable_by_all/1', content)[0]
+        self.assertEqual(algorithm['short_description'], '')
+        self.assertTrue(algorithm['fork_of'] is None)
+        self.assertEqual(algorithm['accessibility'], 'confidential')
+        self.assertEqual(algorithm['language'], 'cxx')
         self.assertFalse(algorithm.has_key('is_owner'))
 
     def test_all_accessible_algorithms(self):
@@ -73,7 +89,7 @@ class AlgorithmsListRetrieval(AlgorithmsAPIBase):
         content = self.checkResponse(response, 200, content_type='application/json')
 
         self.assertTrue(isinstance(content, list))
-        self.assertEqual(len(content), 9)
+        self.assertEqual(len(content), 17)
 
         algorithm = filter(lambda x: x['name'] == 'jackdoe/usable_by_one_user/1', content)[0]
         self.assertEqual(algorithm['short_description'], '')
@@ -82,6 +98,7 @@ class AlgorithmsListRetrieval(AlgorithmsAPIBase):
         self.assertTrue(algorithm['fork_of'] is None)
         self.assertEqual(algorithm['is_owner'], False)
         self.assertEqual(algorithm['accessibility'], 'confidential')
+        self.assertEqual(algorithm['language'], 'python')
 
         algorithm = filter(lambda x: x['name'] == 'jackdoe/usable_by_one_team/1', content)[0]
         self.assertEqual(algorithm['short_description'], '')
@@ -90,6 +107,7 @@ class AlgorithmsListRetrieval(AlgorithmsAPIBase):
         self.assertTrue(algorithm['fork_of'] is None)
         self.assertEqual(algorithm['is_owner'], False)
         self.assertEqual(algorithm['accessibility'], 'confidential')
+        self.assertEqual(algorithm['language'], 'python')
 
         algorithm = filter(lambda x: x['name'] == 'jackdoe/usable_by_teams/1', content)[0]
         self.assertEqual(algorithm['short_description'], '')
@@ -98,6 +116,7 @@ class AlgorithmsListRetrieval(AlgorithmsAPIBase):
         self.assertTrue(algorithm['fork_of'] is None)
         self.assertEqual(algorithm['is_owner'], False)
         self.assertEqual(algorithm['accessibility'], 'confidential')
+        self.assertEqual(algorithm['language'], 'python')
 
         algorithm = filter(lambda x: x['name'] == 'jackdoe/public_for_all/1', content)[0]
         self.assertEqual(algorithm['short_description'], '')
@@ -106,6 +125,7 @@ class AlgorithmsListRetrieval(AlgorithmsAPIBase):
         self.assertTrue(algorithm['fork_of'] is None)
         self.assertEqual(algorithm['is_owner'], False)
         self.assertEqual(algorithm['accessibility'], 'public')
+        self.assertEqual(algorithm['language'], 'python')
 
         algorithm = filter(lambda x: x['name'] == 'jackdoe/usable_by_all/1', content)[0]
         self.assertEqual(algorithm['short_description'], '')
@@ -114,6 +134,7 @@ class AlgorithmsListRetrieval(AlgorithmsAPIBase):
         self.assertTrue(algorithm['fork_of'] is None)
         self.assertEqual(algorithm['is_owner'], False)
         self.assertEqual(algorithm['accessibility'], 'confidential')
+        self.assertEqual(algorithm['language'], 'python')
 
         algorithm = filter(lambda x: x['name'] == 'jackdoe/public_for_one_user/1', content)[0]
         self.assertEqual(algorithm['short_description'], '')
@@ -122,6 +143,7 @@ class AlgorithmsListRetrieval(AlgorithmsAPIBase):
         self.assertTrue(algorithm['fork_of'] is None)
         self.assertEqual(algorithm['is_owner'], False)
         self.assertEqual(algorithm['accessibility'], 'confidential')
+        self.assertEqual(algorithm['language'], 'python')
 
         algorithm = filter(lambda x: x['name'] == 'jackdoe/public_for_one_team/1', content)[0]
         self.assertEqual(algorithm['short_description'], '')
@@ -130,6 +152,7 @@ class AlgorithmsListRetrieval(AlgorithmsAPIBase):
         self.assertTrue(algorithm['fork_of'] is None)
         self.assertEqual(algorithm['is_owner'], False)
         self.assertEqual(algorithm['accessibility'], 'confidential')
+        self.assertEqual(algorithm['language'], 'python')
 
         algorithm = filter(lambda x: x['name'] == 'jackdoe/public_for_teams/1', content)[0]
         self.assertEqual(algorithm['short_description'], '')
@@ -138,6 +161,7 @@ class AlgorithmsListRetrieval(AlgorithmsAPIBase):
         self.assertTrue(algorithm['fork_of'] is None)
         self.assertEqual(algorithm['is_owner'], False)
         self.assertEqual(algorithm['accessibility'], 'confidential')
+        self.assertEqual(algorithm['language'], 'python')
 
         algorithm = filter(lambda x: x['name'] == 'johndoe/forked_algo/1', content)[0]
         self.assertEqual(algorithm['short_description'], '')
@@ -146,6 +170,79 @@ class AlgorithmsListRetrieval(AlgorithmsAPIBase):
         self.assertEqual(algorithm['fork_of'], 'jackdoe/public_for_all/1')
         self.assertEqual(algorithm['is_owner'], True)
         self.assertEqual(algorithm['accessibility'], 'private')
+        self.assertEqual(algorithm['language'], 'python')
+
+        algorithm = filter(lambda x: x['name'] == 'jackdoe/binary_usable_by_one_user/1', content)[0]
+        self.assertEqual(algorithm['short_description'], '')
+        self.assertEqual(algorithm['version'], 1)
+        self.assertEqual(algorithm['previous_version'], None)
+        self.assertTrue(algorithm['fork_of'] is None)
+        self.assertEqual(algorithm['is_owner'], False)
+        self.assertEqual(algorithm['accessibility'], 'confidential')
+        self.assertEqual(algorithm['language'], 'cxx')
+
+        algorithm = filter(lambda x: x['name'] == 'jackdoe/binary_usable_by_one_team/1', content)[0]
+        self.assertEqual(algorithm['short_description'], '')
+        self.assertEqual(algorithm['version'], 1)
+        self.assertEqual(algorithm['previous_version'], None)
+        self.assertTrue(algorithm['fork_of'] is None)
+        self.assertEqual(algorithm['is_owner'], False)
+        self.assertEqual(algorithm['accessibility'], 'confidential')
+        self.assertEqual(algorithm['language'], 'cxx')
+
+        algorithm = filter(lambda x: x['name'] == 'jackdoe/binary_usable_by_teams/1', content)[0]
+        self.assertEqual(algorithm['short_description'], '')
+        self.assertEqual(algorithm['version'], 1)
+        self.assertEqual(algorithm['previous_version'], None)
+        self.assertTrue(algorithm['fork_of'] is None)
+        self.assertEqual(algorithm['is_owner'], False)
+        self.assertEqual(algorithm['accessibility'], 'confidential')
+        self.assertEqual(algorithm['language'], 'cxx')
+
+        algorithm = filter(lambda x: x['name'] == 'jackdoe/binary_public_for_all/1', content)[0]
+        self.assertEqual(algorithm['short_description'], '')
+        self.assertEqual(algorithm['version'], 1)
+        self.assertEqual(algorithm['previous_version'], None)
+        self.assertTrue(algorithm['fork_of'] is None)
+        self.assertEqual(algorithm['is_owner'], False)
+        self.assertEqual(algorithm['accessibility'], 'public')
+        self.assertEqual(algorithm['language'], 'cxx')
+
+        algorithm = filter(lambda x: x['name'] == 'jackdoe/binary_usable_by_all/1', content)[0]
+        self.assertEqual(algorithm['short_description'], '')
+        self.assertEqual(algorithm['version'], 1)
+        self.assertEqual(algorithm['previous_version'], None)
+        self.assertTrue(algorithm['fork_of'] is None)
+        self.assertEqual(algorithm['is_owner'], False)
+        self.assertEqual(algorithm['accessibility'], 'confidential')
+        self.assertEqual(algorithm['language'], 'cxx')
+
+        algorithm = filter(lambda x: x['name'] == 'jackdoe/binary_public_for_one_user/1', content)[0]
+        self.assertEqual(algorithm['short_description'], '')
+        self.assertEqual(algorithm['version'], 1)
+        self.assertEqual(algorithm['previous_version'], None)
+        self.assertTrue(algorithm['fork_of'] is None)
+        self.assertEqual(algorithm['is_owner'], False)
+        self.assertEqual(algorithm['accessibility'], 'confidential')
+        self.assertEqual(algorithm['language'], 'cxx')
+
+        algorithm = filter(lambda x: x['name'] == 'jackdoe/binary_public_for_one_team/1', content)[0]
+        self.assertEqual(algorithm['short_description'], '')
+        self.assertEqual(algorithm['version'], 1)
+        self.assertEqual(algorithm['previous_version'], None)
+        self.assertTrue(algorithm['fork_of'] is None)
+        self.assertEqual(algorithm['is_owner'], False)
+        self.assertEqual(algorithm['accessibility'], 'confidential')
+        self.assertEqual(algorithm['language'], 'cxx')
+
+        algorithm = filter(lambda x: x['name'] == 'jackdoe/binary_public_for_teams/1', content)[0]
+        self.assertEqual(algorithm['short_description'], '')
+        self.assertEqual(algorithm['version'], 1)
+        self.assertEqual(algorithm['previous_version'], None)
+        self.assertTrue(algorithm['fork_of'] is None)
+        self.assertEqual(algorithm['is_owner'], False)
+        self.assertEqual(algorithm['accessibility'], 'confidential')
+        self.assertEqual(algorithm['language'], 'cxx')
 
 
     def test_own_algorithms(self):
@@ -157,7 +254,7 @@ class AlgorithmsListRetrieval(AlgorithmsAPIBase):
         content = self.checkResponse(response, 200, content_type='application/json')
 
         self.assertTrue(isinstance(content, list))
-        self.assertEqual(len(content), 9)
+        self.assertEqual(len(content), 18)
 
         self.assertEqual(len(filter(lambda x: x['name'] == 'jackdoe/usable_by_one_user/1', content)), 1)
         self.assertEqual(len(filter(lambda x: x['name'] == 'jackdoe/usable_by_one_team/1', content)), 1)
@@ -169,43 +266,23 @@ class AlgorithmsListRetrieval(AlgorithmsAPIBase):
         self.assertEqual(len(filter(lambda x: x['name'] == 'jackdoe/public_for_teams/1', content)), 1)
         self.assertEqual(len(filter(lambda x: x['name'] == 'jackdoe/personal/1', content)), 1)
 
+        self.assertEqual(len(filter(lambda x: x['name'] == 'jackdoe/binary_usable_by_one_user/1', content)), 1)
+        self.assertEqual(len(filter(lambda x: x['name'] == 'jackdoe/binary_usable_by_one_team/1', content)), 1)
+        self.assertEqual(len(filter(lambda x: x['name'] == 'jackdoe/binary_usable_by_teams/1', content)), 1)
+        self.assertEqual(len(filter(lambda x: x['name'] == 'jackdoe/binary_usable_by_all/1', content)), 1)
+        self.assertEqual(len(filter(lambda x: x['name'] == 'jackdoe/binary_public_for_all/1', content)), 1)
+        self.assertEqual(len(filter(lambda x: x['name'] == 'jackdoe/binary_public_for_one_user/1', content)), 1)
+        self.assertEqual(len(filter(lambda x: x['name'] == 'jackdoe/binary_public_for_one_team/1', content)), 1)
+        self.assertEqual(len(filter(lambda x: x['name'] == 'jackdoe/binary_public_for_teams/1', content)), 1)
+        self.assertEqual(len(filter(lambda x: x['name'] == 'jackdoe/binary_personal/1', content)), 1)
 
         algorithm = filter(lambda x: x['name'] == 'jackdoe/usable_by_one_user/1', content)[0]
         self.assertEqual(algorithm['short_description'], '')
         self.assertTrue(algorithm['fork_of'] is None)
-        # self.assertEqual(len(algorithm['inputs']), 2)
-        # self.assertEqual(len(algorithm['outputs']), 1)
-
-        # input = algorithm['inputs'][0]
-        # self.assertEqual(input['name'], 'a')
-        # self.assertEqual(input['dataformat'], 'johndoe/single_integer/1')
-
-        # input = algorithm['inputs'][1]
-        # self.assertEqual(input['name'], 'b')
-        # self.assertEqual(input['dataformat'], 'johndoe/single_integer/1')
-
-        # output = algorithm['outputs'][0]
-        # self.assertEqual(output['name'], 'sum')
-        # self.assertEqual(output['dataformat'], 'johndoe/single_integer/1')
-
 
         algorithm = filter(lambda x: x['name'] == 'jackdoe/public_for_all/1', content)[0]
         self.assertEqual(algorithm['short_description'], '')
         self.assertTrue(algorithm['fork_of'] is None)
-        # self.assertEqual(len(algorithm['inputs']), 2)
-        # self.assertEqual(len(algorithm['outputs']), 1)
-
-        # input = algorithm['inputs'][0]
-        # self.assertEqual(input['name'], 'a')
-        # self.assertEqual(input['dataformat'], 'johndoe/single_integer/1')
-
-        # input = algorithm['inputs'][1]
-        # self.assertEqual(input['name'], 'b')
-        # self.assertEqual(input['dataformat'], 'johndoe/single_integer/1')
-
-        # output = algorithm['outputs'][0]
-        # self.assertEqual(output['name'], 'sum')
-        # self.assertEqual(output['dataformat'], 'johndoe/single_integer/1')
 
 
     def test_other_user_algorithms(self):
@@ -217,55 +294,119 @@ class AlgorithmsListRetrieval(AlgorithmsAPIBase):
         content = self.checkResponse(response, 200, content_type='application/json')
 
         self.assertTrue(isinstance(content, list))
-        self.assertEqual(len(content), 8)
+        self.assertEqual(len(content), 16)
 
         algorithm = filter(lambda x: x['name'] == 'jackdoe/usable_by_one_user/1', content)[0]
         self.assertEqual(algorithm['short_description'], '')
         self.assertTrue(algorithm['fork_of'] is None)
         self.assertEqual(algorithm['accessibility'], 'confidential')
         self.assertFalse(algorithm['opensource'])
+        self.assertEqual(algorithm['language'], 'python')
 
         algorithm = filter(lambda x: x['name'] == 'jackdoe/usable_by_one_team/1', content)[0]
         self.assertEqual(algorithm['short_description'], '')
         self.assertTrue(algorithm['fork_of'] is None)
         self.assertEqual(algorithm['accessibility'], 'confidential')
         self.assertFalse(algorithm['opensource'])
+        self.assertEqual(algorithm['language'], 'python')
 
         algorithm = filter(lambda x: x['name'] == 'jackdoe/usable_by_teams/1', content)[0]
         self.assertEqual(algorithm['short_description'], '')
         self.assertTrue(algorithm['fork_of'] is None)
         self.assertEqual(algorithm['accessibility'], 'confidential')
         self.assertFalse(algorithm['opensource'])
+        self.assertEqual(algorithm['language'], 'python')
 
         algorithm = filter(lambda x: x['name'] == 'jackdoe/usable_by_all/1', content)[0]
         self.assertEqual(algorithm['short_description'], '')
         self.assertTrue(algorithm['fork_of'] is None)
         self.assertEqual(algorithm['accessibility'], 'confidential')
         self.assertFalse(algorithm['opensource'])
+        self.assertEqual(algorithm['language'], 'python')
 
         algorithm = filter(lambda x: x['name'] == 'jackdoe/public_for_one_user/1', content)[0]
         self.assertEqual(algorithm['short_description'], '')
         self.assertTrue(algorithm['fork_of'] is None)
         self.assertEqual(algorithm['accessibility'], 'confidential')
         self.assertTrue(algorithm['opensource'])
+        self.assertEqual(algorithm['language'], 'python')
 
         algorithm = filter(lambda x: x['name'] == 'jackdoe/public_for_one_team/1', content)[0]
         self.assertEqual(algorithm['short_description'], '')
         self.assertTrue(algorithm['fork_of'] is None)
         self.assertEqual(algorithm['accessibility'], 'confidential')
         self.assertTrue(algorithm['opensource'])
+        self.assertEqual(algorithm['language'], 'python')
 
         algorithm = filter(lambda x: x['name'] == 'jackdoe/public_for_teams/1', content)[0]
         self.assertEqual(algorithm['short_description'], '')
         self.assertTrue(algorithm['fork_of'] is None)
         self.assertEqual(algorithm['accessibility'], 'confidential')
         self.assertTrue(algorithm['opensource'])
+        self.assertEqual(algorithm['language'], 'python')
 
         algorithm = filter(lambda x: x['name'] == 'jackdoe/public_for_all/1', content)[0]
         self.assertEqual(algorithm['short_description'], '')
         self.assertTrue(algorithm['fork_of'] is None)
         self.assertEqual(algorithm['accessibility'], 'public')
         self.assertTrue(algorithm['opensource'])
+        self.assertEqual(algorithm['language'], 'python')
+
+        algorithm = filter(lambda x: x['name'] == 'jackdoe/binary_usable_by_one_user/1', content)[0]
+        self.assertEqual(algorithm['short_description'], '')
+        self.assertTrue(algorithm['fork_of'] is None)
+        self.assertEqual(algorithm['accessibility'], 'confidential')
+        self.assertFalse(algorithm['opensource'])
+        self.assertEqual(algorithm['language'], 'cxx')
+
+        algorithm = filter(lambda x: x['name'] == 'jackdoe/binary_usable_by_one_team/1', content)[0]
+        self.assertEqual(algorithm['short_description'], '')
+        self.assertTrue(algorithm['fork_of'] is None)
+        self.assertEqual(algorithm['accessibility'], 'confidential')
+        self.assertFalse(algorithm['opensource'])
+        self.assertEqual(algorithm['language'], 'cxx')
+
+        algorithm = filter(lambda x: x['name'] == 'jackdoe/binary_usable_by_teams/1', content)[0]
+        self.assertEqual(algorithm['short_description'], '')
+        self.assertTrue(algorithm['fork_of'] is None)
+        self.assertEqual(algorithm['accessibility'], 'confidential')
+        self.assertFalse(algorithm['opensource'])
+        self.assertEqual(algorithm['language'], 'cxx')
+
+        algorithm = filter(lambda x: x['name'] == 'jackdoe/binary_usable_by_all/1', content)[0]
+        self.assertEqual(algorithm['short_description'], '')
+        self.assertTrue(algorithm['fork_of'] is None)
+        self.assertEqual(algorithm['accessibility'], 'confidential')
+        self.assertFalse(algorithm['opensource'])
+        self.assertEqual(algorithm['language'], 'cxx')
+
+        algorithm = filter(lambda x: x['name'] == 'jackdoe/binary_public_for_one_user/1', content)[0]
+        self.assertEqual(algorithm['short_description'], '')
+        self.assertTrue(algorithm['fork_of'] is None)
+        self.assertEqual(algorithm['accessibility'], 'confidential')
+        self.assertTrue(algorithm['opensource'])
+        self.assertEqual(algorithm['language'], 'cxx')
+
+        algorithm = filter(lambda x: x['name'] == 'jackdoe/binary_public_for_one_team/1', content)[0]
+        self.assertEqual(algorithm['short_description'], '')
+        self.assertTrue(algorithm['fork_of'] is None)
+        self.assertEqual(algorithm['accessibility'], 'confidential')
+        self.assertTrue(algorithm['opensource'])
+        self.assertEqual(algorithm['language'], 'cxx')
+
+        algorithm = filter(lambda x: x['name'] == 'jackdoe/binary_public_for_teams/1', content)[0]
+        self.assertEqual(algorithm['short_description'], '')
+        self.assertTrue(algorithm['fork_of'] is None)
+        self.assertEqual(algorithm['accessibility'], 'confidential')
+        self.assertTrue(algorithm['opensource'])
+        self.assertEqual(algorithm['language'], 'cxx')
+
+        algorithm = filter(lambda x: x['name'] == 'jackdoe/binary_public_for_all/1', content)[0]
+        self.assertEqual(algorithm['short_description'], '')
+        self.assertTrue(algorithm['fork_of'] is None)
+        self.assertEqual(algorithm['accessibility'], 'public')
+        self.assertTrue(algorithm['opensource'])
+        self.assertEqual(algorithm['language'], 'cxx')
 
 
     def test_user_algorithms_for_anonymous_user(self):
@@ -275,13 +416,21 @@ class AlgorithmsListRetrieval(AlgorithmsAPIBase):
         content = self.checkResponse(response, 200, content_type='application/json')
 
         self.assertTrue(isinstance(content, list))
-        self.assertEqual(len(content), 1)
+        self.assertEqual(len(content), 2)
 
         algorithm = filter(lambda x: x['name'] == 'jackdoe/public_for_all/1', content)[0]
         self.assertEqual(algorithm['short_description'], '')
         self.assertTrue(algorithm['fork_of'] is None)
         self.assertEqual(algorithm['accessibility'], 'public')
         self.assertTrue(algorithm['opensource'])
+        self.assertEqual(algorithm['language'], 'python')
+
+        algorithm = filter(lambda x: x['name'] == 'jackdoe/binary_public_for_all/1', content)[0]
+        self.assertEqual(algorithm['short_description'], '')
+        self.assertTrue(algorithm['fork_of'] is None)
+        self.assertEqual(algorithm['accessibility'], 'public')
+        self.assertTrue(algorithm['opensource'])
+        self.assertEqual(algorithm['language'], 'cxx')
 
 
 class AlgorithmsNameCheck(AlgorithmsAPIBase):
@@ -1477,6 +1626,7 @@ class AlgorithmRetrieval(AlgorithmsAPIBase):
 
         self.assertEqual(data['accessibility'], 'public')
         self.assertTrue(data['opensource'])
+        self.assertEqual(data['language'], 'python')
         self.assertEqual(data['description'], '')
         self.assertFalse(data.has_key('is_owner'))
 
@@ -1490,6 +1640,7 @@ class AlgorithmRetrieval(AlgorithmsAPIBase):
 
         self.assertEqual(data['accessibility'], 'confidential')
         self.assertFalse(data['opensource'])
+        self.assertEqual(data['language'], 'python')
         self.assertEqual(data['description'], '')
         self.assertFalse(data.has_key('code'))
         self.assertFalse(data.has_key('is_owner'))
@@ -1505,6 +1656,7 @@ class AlgorithmRetrieval(AlgorithmsAPIBase):
         self.assertEqual(data['is_owner'], False)
         self.assertEqual(data['accessibility'], 'public')
         self.assertTrue(data['opensource'])
+        self.assertEqual(data['language'], 'python')
         self.assertEqual(data['description'], '')
 
         self.assertEqual(data['declaration'], AlgorithmsAPIBase.JSON_DECLARATION)
@@ -1521,6 +1673,7 @@ class AlgorithmRetrieval(AlgorithmsAPIBase):
         self.assertEqual(data['is_owner'], False)
         self.assertEqual(data['accessibility'], 'confidential')
         self.assertFalse(data['opensource'])
+        self.assertEqual(data['language'], 'python')
         self.assertEqual(data['description'], '')
         self.assertFalse(data.has_key('code'))
 
@@ -1535,6 +1688,7 @@ class AlgorithmRetrieval(AlgorithmsAPIBase):
         self.assertEqual(data['is_owner'], False)
         self.assertEqual(data['accessibility'], 'confidential')
         self.assertFalse(data['opensource'])
+        self.assertEqual(data['language'], 'python')
         self.assertEqual(data['description'], '')
         self.assertFalse(data.has_key('code'))
 
@@ -1549,6 +1703,7 @@ class AlgorithmRetrieval(AlgorithmsAPIBase):
         self.assertEqual(data['is_owner'], False)
         self.assertEqual(data['accessibility'], 'confidential')
         self.assertTrue(data['opensource'])
+        self.assertEqual(data['language'], 'python')
         self.assertEqual(data['description'], '')
 
         self.assertEqual(data['declaration'], AlgorithmsAPIBase.JSON_DECLARATION)
@@ -1565,6 +1720,7 @@ class AlgorithmRetrieval(AlgorithmsAPIBase):
         self.assertEqual(data['is_owner'], True)
         self.assertEqual(data['accessibility'], 'public')
         self.assertTrue(data['opensource'])
+        self.assertEqual(data['language'], 'python')
         self.assertEqual(data['description'], '')
 
         self.assertEqual(data['declaration'], AlgorithmsAPIBase.JSON_DECLARATION)
@@ -1586,6 +1742,7 @@ class AlgorithmRetrieval(AlgorithmsAPIBase):
         self.assertEqual(data['is_owner'], True)
         self.assertEqual(data['accessibility'], 'confidential')
         self.assertFalse(data['opensource'])
+        self.assertEqual(data['language'], 'python')
         self.assertEqual(data['description'], '')
 
         self.assertEqual(data['declaration'], AlgorithmsAPIBase.JSON_DECLARATION)
@@ -1607,6 +1764,7 @@ class AlgorithmRetrieval(AlgorithmsAPIBase):
         self.assertEqual(data['is_owner'], True)
         self.assertEqual(data['accessibility'], 'confidential')
         self.assertFalse(data['opensource'])
+        self.assertEqual(data['language'], 'python')
         self.assertEqual(data['description'], '')
 
         self.assertEqual(data['declaration'], AlgorithmsAPIBase.JSON_DECLARATION)
@@ -1628,6 +1786,7 @@ class AlgorithmRetrieval(AlgorithmsAPIBase):
         self.assertEqual(data['is_owner'], True)
         self.assertEqual(data['accessibility'], 'confidential')
         self.assertFalse(data['opensource'])
+        self.assertEqual(data['language'], 'python')
         self.assertEqual(data['description'], '')
 
         self.assertEqual(data['declaration'], AlgorithmsAPIBase.JSON_DECLARATION)
@@ -1639,6 +1798,145 @@ class AlgorithmRetrieval(AlgorithmsAPIBase):
         self.assertFalse(data['sharing'].has_key('usable_by'))
 
 
+    def test_successful_retrieval_of_binary_algorithm(self):
+        self.client.login(username='jackdoe', password='1234')
+
+        url = reverse('api_algorithms:object', args=['jackdoe', 'binary_personal'])
+        response = self.client.get(url)
+        data = self.checkResponse(response, 200, content_type='application/json')
+
+        self.assertEqual(data['is_owner'], True)
+        self.assertEqual(data['accessibility'], 'private')
+        self.assertFalse(data['opensource'])
+        self.assertEqual(data['language'], 'cxx')
+        self.assertEqual(data['description'], '')
+
+        self.assertEqual(data['declaration'], AlgorithmsAPIBase.JSON_CXX_DECLARATION)
+        self.assertFalse(data.has_key('code'))
+
+
+
+class AlgorithmBinaryRetrieval(AlgorithmsAPIBase):
+
+    def test_no_retrieval_of_confidential_algorithm_for_anonymous_user(self):
+        url = reverse('api_algorithms:binary', args=['jackdoe', 'binary_personal'])
+        response = self.client.get(url)
+        self.checkResponse(response, 404)
+
+
+    def test_fail_to_retrieve_with_invalid_username(self):
+        self.client.login(username='johndoe', password='1234')
+
+        url = reverse('api_algorithms:binary', args=['unknown', 'binary_personal'])
+        response = self.client.get(url)
+        self.checkResponse(response, 404)
+
+
+    def test_fail_to_retrieve_with_invalid_algorithm_name(self):
+        self.client.login(username='johndoe', password='1234')
+
+        url = reverse('api_algorithms:binary', args=['johndoe', 'unknown'])
+        response = self.client.get(url)
+        self.checkResponse(response, 404)
+
+
+    def test_no_retrieval_of_confidential_algorithm(self):
+        self.client.login(username='jackdoe', password='1234')
+
+        url = reverse('api_algorithms:binary', args=['johndoe', 'binary_personal'])
+        response = self.client.get(url)
+        self.checkResponse(response, 404)
+
+
+    def test_successful_retrieval_of_public_algorithm_for_anonymous_user(self):
+        url = reverse('api_algorithms:binary', args=['jackdoe', 'binary_public_for_all'])
+        response = self.client.get(url)
+        data = self.checkResponse(response, 200, content_type='application/octet-stream')
+
+        self.assertEqual(data, AlgorithmsAPIBase.BINARY)
+
+    def test_no_retrieval_of_usable_algorithm_for_anonymous_user(self):
+        url = reverse('api_algorithms:binary', args=['jackdoe', 'usable_by_all'])
+        response = self.client.get(url)
+        self.checkResponse(response, 404)
+
+
+    def test_successful_retrieval_of_public_algorithm(self):
+        self.client.login(username='johndoe', password='1234')
+
+        url = reverse('api_algorithms:binary', args=['jackdoe', 'binary_public_for_all'])
+        response = self.client.get(url)
+        data = self.checkResponse(response, 200, content_type='application/octet-stream')
+
+        self.assertEqual(data, AlgorithmsAPIBase.BINARY)
+
+
+    def test_no_retrieval_of_usable_algorithm(self):
+        self.client.login(username='johndoe', password='1234')
+
+        url = reverse('api_algorithms:binary', args=['jackdoe', 'binary_usable_by_one_user'])
+        response = self.client.get(url)
+        self.checkResponse(response, 404)
+
+
+    def test_no_retrieval_of_publicly_usable_algorithm(self):
+        self.client.login(username='johndoe', password='1234')
+
+        url = reverse('api_algorithms:binary', args=['jackdoe', 'binary_usable_by_all'])
+        response = self.client.get(url)
+        self.checkResponse(response, 404)
+
+
+    def test_successful_retrieval_of_confidential_algorithm(self):
+        self.client.login(username='johndoe', password='1234')
+
+        url = reverse('api_algorithms:binary', args=['jackdoe', 'binary_public_for_one_user'])
+        response = self.client.get(url)
+        data = self.checkResponse(response, 200, content_type='application/octet-stream')
+
+        self.assertEqual(data, AlgorithmsAPIBase.BINARY)
+
+
+    def test_successful_retrieval_of_own_public_algorithm(self):
+        self.client.login(username='jackdoe', password='1234')
+
+        url = reverse('api_algorithms:binary', args=['jackdoe', 'binary_public_for_all'])
+        response = self.client.get(url)
+        data = self.checkResponse(response, 200, content_type='application/octet-stream')
+
+        self.assertEqual(data, AlgorithmsAPIBase.BINARY)
+
+
+    def test_successful_retrieval_of_own_confidential_algorithm(self):
+        self.client.login(username='jackdoe', password='1234')
+
+        url = reverse('api_algorithms:binary', args=['jackdoe', 'binary_personal'])
+        response = self.client.get(url)
+        data = self.checkResponse(response, 200, content_type='application/octet-stream')
+
+        self.assertEqual(data, AlgorithmsAPIBase.BINARY)
+
+
+    def test_successful_retrieval_of_own_usable_algorithm(self):
+        self.client.login(username='jackdoe', password='1234')
+
+        url = reverse('api_algorithms:binary', args=['jackdoe', 'binary_usable_by_all'])
+        response = self.client.get(url)
+        data = self.checkResponse(response, 200, content_type='application/octet-stream')
+
+        self.assertEqual(data, AlgorithmsAPIBase.BINARY)
+
+
+    def test_successful_retrieval_of_own_shared_algorithm(self):
+        self.client.login(username='jackdoe', password='1234')
+
+        url = reverse('api_algorithms:binary', args=['jackdoe', 'binary_public_for_one_user'])
+        response = self.client.get(url)
+        data = self.checkResponse(response, 200, content_type='application/octet-stream')
+
+        self.assertEqual(data, AlgorithmsAPIBase.BINARY)
+
+
 
 class AlgorithmDeletion(AlgorithmsAPIBase):
 
diff --git a/beat/web/code/api.py b/beat/web/code/api.py
old mode 100644
new mode 100755
index 7046ce6d4..b778eb7ac
--- a/beat/web/code/api.py
+++ b/beat/web/code/api.py
@@ -226,7 +226,7 @@ class RetrieveUpdateDestroyCodeView(RetrieveUpdateDestroyContributionView):
         #    - needed_dataformats
         #    - attestations
         fields_to_remove = []
-        if (request.user != db_object.author) and not(open_source):
+        if ((request.user != db_object.author) and not(open_source)) or db_object.is_binary():
             fields_to_remove = ['code']
 
         fields_to_return = self.get_serializer_fields(request, allow_sharing=(request.user == db_object.author),
diff --git a/beat/web/code/models.py b/beat/web/code/models.py
old mode 100644
new mode 100755
index b76b514ed..8131372e8
--- a/beat/web/code/models.py
+++ b/beat/web/code/models.py
@@ -132,7 +132,7 @@ class CodeManager(StoredContributionManager):
 
         # Figure out the language
         language = declaration.get('language', 'unknown')
-        language = getattr(Code, language.upper())
+        code_db.language = getattr(Code, language.upper())
 
         # Check the provided source code
         if code is None:
@@ -140,7 +140,7 @@ class CodeManager(StoredContributionManager):
                 code_db.source_code = previous_version.source_code
             elif fork_of is not None:
                 code_db.source_code = fork_of.source_code
-            else:
+            elif code_db.language != Code.CXX:
                 code_db.source_code = default.code
         else:
             code_db.source_code = code
@@ -194,14 +194,14 @@ class Code(StoredContribution):
 
     # All possible values should be in sync with beat.core.utils
     UNKNOWN = 'U'
-    BINARY  = 'B'
+    CXX     = 'C'
     MATLAB  = 'M'
     PYTHON  = 'P'
     R       = 'R'
 
     CODE_LANGUAGE = (
         (UNKNOWN, 'Unknown'),
-        (BINARY,  'Binary'),
+        (CXX,     'Cxx'),
         (MATLAB,  'Matlab'),
         (PYTHON,  'Python'),
         (R,       'R'),
@@ -470,6 +470,10 @@ class Code(StoredContribution):
         return open_source
 
 
+    def is_binary(self):
+        return self.language in [Code.CXX]
+
+
     #_____ Overrides __________
 
     def save(self, *args, **kwargs):
@@ -477,10 +481,6 @@ class Code(StoredContribution):
         # Invoke the base implementation
         super(Code, self).save(*args, **kwargs)
 
-        # If the filename has changed, move all the files
-        if self.source_code_filename() != self.source_code_file.name:
-            self._rename_file('source_code_file', self.source_code_filename())
-
         # Ensures that the sharing informations are consistent
         if self.sharing == Code.PUBLIC:
             self.shared_with.clear()
@@ -514,7 +514,7 @@ class Code(StoredContribution):
         return wrapper
 
 
-    def _accessibility_for_user(self, user):
+    def _accessibility_for_user(self, user, without_usable=False):
         """Returns a tuple (<has_access>, <open_source>, <accessibility>), with <accessibility> being
            either 'public', 'private', 'confidential' """
 
@@ -531,29 +531,29 @@ class Code(StoredContribution):
                 return (False, False, None)
             elif self.sharing == Contribution.PUBLIC:
                 return (True, True, 'public')
-            elif self.sharing == Contribution.USABLE:
+            elif not without_usable and (self.sharing == Contribution.USABLE):
                 return (True, False, 'confidential')
             elif not user.is_anonymous():
                 if self.shared_with.filter(id=user.id).exists() or (self.shared_with_team.filter(members=user).count() > 0):
                     return (True, True, 'confidential')
-                elif self.usable_by.filter(id=user.id).exists() or (self.usable_by_team.filter(members=user).count() > 0):
+                elif not without_usable and (self.usable_by.filter(id=user.id).exists() or (self.usable_by_team.filter(members=user).count() > 0)):
                     return (True, False, 'confidential')
 
         return (False, False, None)
 
 
-    def _accessibility_for_team(self, team):
+    def _accessibility_for_team(self, team, without_usable=False):
         """Team specific accessibility check """
 
         if self.sharing == Contribution.PRIVATE:
             return (False, False, None)
         elif self.sharing == Contribution.PUBLIC:
             return (True, True, 'public')
-        elif self.sharing == Contribution.USABLE:
+        elif not without_usable and (self.sharing == Contribution.USABLE):
             return (True, False, 'confidential')
         elif self.shared_with_team.filter(id=team.id).exists():
             return (True, True, 'confidential')
-        elif self.usable_by_team.filter(id=team.id).exists():
+        elif not without_usable and self.usable_by_team.filter(id=team.id).exists():
             return (True, False, 'confidential')
 
         return (False, False, None)
diff --git a/beat/web/code/serializers.py b/beat/web/code/serializers.py
old mode 100644
new mode 100755
index 77f50e8db..b50d101f6
--- a/beat/web/code/serializers.py
+++ b/beat/web/code/serializers.py
@@ -65,11 +65,12 @@ class CodeSharingSerializer(SharingSerializer):
 
 class CodeSerializer(ContributionSerializer):
     opensource = serializers.SerializerMethodField()
+    language = serializers.SerializerMethodField()
     modifiable = serializers.BooleanField()
 
     class Meta(ContributionSerializer.Meta):
         model = Code
-        default_fields = ContributionSerializer.Meta.default_fields + ['opensource']
+        default_fields = ContributionSerializer.Meta.default_fields + ['opensource', 'language']
         extra_fields = ContributionSerializer.Meta.extra_fields + ['code']
         exclude = ContributionSerializer.Meta.exclude + ['source_code_file']
 
@@ -85,6 +86,9 @@ class CodeSerializer(ContributionSerializer):
         (has_access, open_source, accessibility) = obj.accessibility_for(user)
         return open_source
 
+    def get_language(self, obj):
+        return filter(lambda x: x[0] == obj.language, iter(Code.CODE_LANGUAGE))[0][1].lower()
+
     def get_accessibility(self, obj):
         if obj.sharing == Code.PUBLIC:
             return 'public'
diff --git a/beat/web/common/models.py b/beat/web/common/models.py
old mode 100644
new mode 100755
index 66e680a07..50b3b68e6
--- a/beat/web/common/models.py
+++ b/beat/web/common/models.py
@@ -151,14 +151,14 @@ class Shareable(models.Model):
             return (self.attestations.count() == 0)
         return True
 
-    def accessibility_for(self, user_or_team):
+    def accessibility_for(self, user_or_team, without_usable=False):
         """Returns a tuple (<has_access>, <accessibility>), with <accessibility> being
            either 'public', 'private', 'confidential' """
 
         if isinstance(user_or_team, User) or isinstance(user_or_team, AnonymousUser):
-            return self._accessibility_for_user(user_or_team)
+            return self._accessibility_for_user(user_or_team, without_usable)
         elif isinstance(user_or_team, Team):
-            return self._accessibility_for_team(user_or_team)
+            return self._accessibility_for_team(user_or_team, without_usable)
         else:
             raise NotUserNorTeam
 
@@ -295,7 +295,7 @@ class Shareable(models.Model):
 
     #_____ Protected Methods __________
 
-    def _accessibility_for_user(self, user):
+    def _accessibility_for_user(self, user, without_usable=False):
         """User specific accessibility check """
 
         if hasattr(self, 'author') and self.author == user:
@@ -317,7 +317,7 @@ class Shareable(models.Model):
 
         return (False, None)
 
-    def _accessibility_for_team(self, team):
+    def _accessibility_for_team(self, team, without_usable=False):
         """Team specific accessibility check """
 
         if self.sharing == Shareable.PRIVATE:
@@ -726,11 +726,6 @@ class StoredContribution(Contribution):
         # Invoke the base implementation
         super(StoredContribution, self).save(*args, **kwargs)
 
-        # If the filename has changed, move all the files
-        if self.declaration_filename() != self.declaration_file.name:
-            self._rename_file('declaration_file', self.declaration_filename())
-            self._rename_file('description_file', self.description_filename())
-
 
     #_____ Properties __________
 
diff --git a/beat/web/libraries/migrations/0002_cxx_backend.py b/beat/web/libraries/migrations/0002_cxx_backend.py
new file mode 100644
index 000000000..a0d8060e6
--- /dev/null
+++ b/beat/web/libraries/migrations/0002_cxx_backend.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.11 on 2016-11-09 11:05
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('libraries', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='library',
+            name='language',
+            field=models.CharField(choices=[(b'U', b'Unknown'), (b'C', b'C++'), (b'M', b'Matlab'), (b'P', b'Python'), (b'R', b'R')], default=b'P', max_length=1),
+        ),
+    ]
diff --git a/beat/web/plotters/migrations/0002_cxx_backend.py b/beat/web/plotters/migrations/0002_cxx_backend.py
new file mode 100644
index 000000000..709a1a571
--- /dev/null
+++ b/beat/web/plotters/migrations/0002_cxx_backend.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.11 on 2016-11-09 11:05
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('plotters', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='plotter',
+            name='language',
+            field=models.CharField(choices=[(b'U', b'Unknown'), (b'C', b'C++'), (b'M', b'Matlab'), (b'P', b'Python'), (b'R', b'R')], default=b'P', max_length=1),
+        ),
+    ]
-- 
GitLab