Skip to content

Commit

Permalink
Merge pull request #3454 from learningequality/0.13.x
Browse files Browse the repository at this point in the history
0.13.x to central-develop
  • Loading branch information
aronasorman committed Apr 3, 2015
2 parents 3aaeea8 + 5064fda commit 5f82a77
Show file tree
Hide file tree
Showing 11 changed files with 77 additions and 20 deletions.
2 changes: 1 addition & 1 deletion data/khan/channel_data.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"channel_name": "KA Lite",
"head_line": "A free world-class education for anyone anywhere.",
"tag_line": "KA Lite is a lightweight web server for viewing and interacting with core Khan Academy content (videos and exercises) without needing an Internet connection.",
"tag_line": "KA Lite is a light-weight web server for viewing and interacting with core Khan Academy content (videos and exercises) without needing an Internet connection.",
"channel_license": "CC-BY-NC-SA",
"footer_text": "Videos © 2015 Khan Academy (Creative Commons) // Exercises © 2015 Khan Academy"
}
8 changes: 8 additions & 0 deletions kalite/distributed/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import requests
from kalite.version import *

# Modify Request's default user agent to include the KA Lite version number
# (this is done in this file because putting it in __init__.py causes circular imports,
# and putting it in urls.py doesn't get loaded by management commands)
base_headers = requests.defaults.defaults["base_headers"]
base_headers["User-Agent"] = ("ka-lite/%s " % VERSION) + base_headers["User-Agent"]
2 changes: 1 addition & 1 deletion kalite/distributed/static/perseus/ke/local-only/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
str = str.messages[0];
}

return interpolateStringToArray(str, options).join("");
return interpolateStringToArray(gettext(str), options).join("");
};

/**
Expand Down
2 changes: 1 addition & 1 deletion kalite/distributed/static/perseus/lib/react-with-addons.js
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@
// hopefully people will notice the second alert if they fix the first
// one and reload.
if (lastAlertTime + 2000 < Date.now()) {
alert('Dev-only warning: ' + message);
// alert('Dev-only warning: ' + message);
lastAlertTime = Date.now();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

{% trans "KA Lite" %}
{% trans "A free world-class education for anyone anywhere." %}
{% trans "KA Lite is a lightweight web server for viewing and interacting with core Khan Academy content (videos and exercises) without needing an Internet connection." %}
{% trans "Videos and Exercises © 2014 Khan Academy" %}
{% trans "KA Lite is a light-weight web server for viewing and interacting with core Khan Academy content (videos and exercises) without needing an Internet connection." %}
{% trans "Videos and Exercises © 2014 Khan Academy" %}
14 changes: 10 additions & 4 deletions kalite/topic_tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ def get_exercise_cache(force=False, language=settings.LANGUAGE_CODE):
exercise_template = os.path.join(exercise_lang, exercise_file)


with i18n.translate_block(exercise_lang):
with i18n.translate_block(language):
exercise["available"] = available
exercise["lang"] = exercise_lang
exercise["template"] = exercise_template
Expand Down Expand Up @@ -517,7 +517,14 @@ def smart_translate_item_data(item_data):
item_data and translates only the content field.
"""
if isinstance(item_data, dict):
# just translate strings immediately
if isinstance(item_data, basestring):
return _(item_data)

elif isinstance(item_data, list):
return map(smart_translate_item_data, item_data)

elif isinstance(item_data, dict):
if 'content' in item_data:
item_data['content'] = _(item_data['content']) if item_data['content'] else ""

Expand All @@ -527,8 +534,7 @@ def smart_translate_item_data(item_data):
elif isinstance(field_data, list):
item_data[field] = map(smart_translate_item_data, field_data)


return item_data
return item_data



Expand Down
31 changes: 30 additions & 1 deletion kalite/topic_tools/tests/utils_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,27 @@ class SmartTranslateItemDataTests(KALiteTestCase):
def tearDown(self):
ugettext_dummy.reset_mock()

def test_list_of_dicts(self):
# test_data = {"hints": [{"content": TRANS_STRING, "images": {}, "widgets": {}}]}
# expected_data = {"hints": [{"content": DUMMY_STRING, "images": {}, "widgets": {}}]}
self.maxDiff = None
test_data = {'question': {'content': TRANS_STRING, 'images': {'/content/khan/f24b1c8daf0d1b16bf2dc391393b655e72190290.png': {'width': 450, 'height': 81}}, 'widgets': {'radio 1': {'version': {'major': 0, 'minor': 0}, 'type': 'radio', 'graded': True, 'options': {'onePerLine': True, 'noneOfTheAbove': False, 'choices': [], 'displayCount': None, 'multipleSelect': False, 'randomize': True}}}}, 'answerArea': {'calculator': False, 'type': 'multiple', 'options': {'content': '', 'images': {}, 'widgets': {}}}, 'itemDataVersion': {'major': 0, 'minor': 1}, 'hints': [{'content': TRANS_STRING, 'images': {}, 'widgets': {}}]}
expected_data = {'question': {'content': DUMMY_STRING, 'images': {'/content/khan/f24b1c8daf0d1b16bf2dc391393b655e72190290.png': {'width': 450, 'height': 81}}, 'widgets': {'radio 1': {'version': {'major': 0, 'minor': 0}, 'type': 'radio', 'graded': True, 'options': {'onePerLine': True, 'noneOfTheAbove': False, 'choices': [], 'displayCount': None, 'multipleSelect': False, 'randomize': True}}}}, 'answerArea': {'calculator': False, 'type': 'multiple', 'options': {'content': '', 'images': {}, 'widgets': {}}}, 'itemDataVersion': {'major': 0, 'minor': 1}, 'hints': [{'content': DUMMY_STRING, 'images': {}, 'widgets': {}}]}

result = mod.smart_translate_item_data(test_data)
# ugettext_dummy.assert_called_once_with(TRANS_STRING)

self.assertEqual(result, expected_data)

def test_list_of_lists(self):
test_data = [[TRANS_STRING]]
expected_data = [[DUMMY_STRING]]

result = mod.smart_translate_item_data(test_data)
ugettext_dummy.assert_called_once_with(TRANS_STRING)

self.assertEqual(result, expected_data)

def test_simple_content_dict(self):
# ugettext_method.return_value = DUMMY_STRING
test_data = {'content': TRANS_STRING}
Expand All @@ -37,11 +58,19 @@ def test_content_in_widgets_field(self):
self.assertEqual(result, expected_data)

def test_content_inside_radio_field(self):
pass
test_data = {'radio 1': {'widgets': {'content': TRANS_STRING}}}
expected_data = {'radio 1': {'widgets': {'content': DUMMY_STRING}}}

result = mod.smart_translate_item_data(test_data)
ugettext_dummy.assert_called_once_with(TRANS_STRING)

self.assertEqual(result, expected_data)

def test_simple_string(self):
test_data = TRANS_STRING
expected_data = DUMMY_STRING

result = mod.smart_translate_item_data(test_data)
ugettext_dummy.assert_called_once_with(TRANS_STRING)

self.assertEqual(result, expected_data)
16 changes: 14 additions & 2 deletions python-packages/securesync/devices/api_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from django.conf import settings
from django.contrib import messages
from django.contrib.messages.api import get_messages
from django.core.mail import send_mail
from django.core.urlresolvers import reverse
from django.db import models as db_models
from django.http import HttpResponse
Expand Down Expand Up @@ -53,8 +54,19 @@ def register_device(request):
# Validate the loaded data
if not isinstance(client_device, Device):
return JsonResponseMessageError("Client device must be an instance of the 'Device' model.", code=EC.CLIENT_DEVICE_NOT_DEVICE)
if not client_device.verify():
return JsonResponseMessageError("Client device must be self-signed with a signature matching its own public key.", code=EC.CLIENT_DEVICE_INVALID_SIGNATURE)

try:
if not client_device.verify():
# We've been getting this verification error a lot, even when we shouldn't. Send more details to us by email so we can diagnose.
msg = "\n\n".join([request.body, client_device._hashable_representation(), str(client_device.validate()), client_device.signed_by_id, client_device.id, str(request)])
send_mail("Client device did not verify", msg, "[email protected]", ["[email protected]"])
return JsonResponseMessageError("Client device must be self-signed with a signature matching its own public key!", code=EC.CLIENT_DEVICE_INVALID_SIGNATURE)
except Exception as e:
# Can't properly namespace to a particular Exception here, since the only reason we would be getting here is
# that what should be proper exception namespacing in code being called isn't correctly catching this exception
msg = "\n\n".join([request.body, client_device._hashable_representation(), "Exception: %s" % e, str(type(e)), client_device.signed_by_id, client_device.id, str(request)])
send_mail("Exception while verifying client device", msg, "[email protected]", ["[email protected]"])
return JsonResponseMessageError("Client device must be self-signed with a signature matching its own public key!", code=EC.CLIENT_DEVICE_INVALID_SIGNATURE)

try:
zone = register_self_registered_device(client_device, models, data)
Expand Down
3 changes: 2 additions & 1 deletion python-packages/securesync/devices/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ def clean_zone(self):
return zone

def clean_public_key(self):
public_key = self.cleaned_data["public_key"]
# Some browsers (unclear which) are converting plus signs to spaces during decodeURIComponent
public_key = self.cleaned_data["public_key"].replace(" ", "+")
if RegisteredDevicePublicKey.objects.filter(public_key=public_key).count() > 0:
raise forms.ValidationError(_("This public key has already been registered!"))
return public_key
5 changes: 3 additions & 2 deletions python-packages/securesync/devices/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""
"""
import requests
import urllib
from annoying.decorators import render_to
from annoying.functions import get_object_or_None
Expand Down Expand Up @@ -92,8 +93,8 @@ def central_server_down_or_error(error_msg):
error_msg: a string
"""
if error_msg:
if urllib.urlopen(settings.CENTRAL_SERVER_URL).getcode() != 200:
return {"error_msg": "Central Server is not reachable, Please try after sometime."}
if requests.get(settings.CENTRAL_SERVER_URL).status_code != 200:
return {"error_msg": _("Central Server is not reachable; please try again after some time.")}
else:
return {"error_msg": error_msg}

Expand Down
10 changes: 5 additions & 5 deletions python-packages/securesync/tests/regression_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ class CentralServerDownMessageTest(TestCase):
was returned by the central server, and pass it along.
"""

@patch('urllib.urlopen')
@patch('requests.get')
def test_error_message_when_central_server_down(self, mock):
mock().getcode.return_value = 500
mock().status_code = 500
error_msg = "Some error message ah!"
expected_msg = "Central Server is not reachable, Please try after sometime."
expected_msg = "Central Server is not reachable; please try again after some time."
self.assertEqual(central_server_down_or_error(error_msg)['error_msg'], expected_msg)

@patch('urllib.urlopen')
@patch('requests.get')
def test_error_message_when_central_server_up(self, mock):
mock().getcode.return_value = 200
mock().status_code = 200
error_msg = "Some error message ah!"
expected_msg = "Some error message ah!"
self.assertEqual(central_server_down_or_error(error_msg)['error_msg'], expected_msg)

0 comments on commit 5f82a77

Please sign in to comment.