Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksey Lim <alsroot@sugarlabs.org>2013-10-08 05:58:01 (GMT)
committer Aleksey Lim <alsroot@sugarlabs.org>2013-10-08 05:58:01 (GMT)
commit2fc0aaf625151081feaf382c289d68620a720b61 (patch)
tree48fc3eb4b5222d78c9d213b073b2703728a5f9f9
parent89057aecc05219179107351bd2e8b3ecbc59d27d (diff)
Specify secondary languages on client side; use comma as a separtor
-rw-r--r--sugar_network/client/__init__.py6
-rw-r--r--sugar_network/node/__init__.py2
-rw-r--r--sugar_network/node/stats_node.py2
-rw-r--r--sugar_network/node/stats_user.py2
-rw-r--r--sugar_network/toolkit/__init__.py20
-rw-r--r--sugar_network/toolkit/http.py4
-rw-r--r--sugar_network/toolkit/options.py15
-rw-r--r--sugar_network/toolkit/spec.py5
-rwxr-xr-xtests/units/client/routes.py92
9 files changed, 131 insertions, 17 deletions
diff --git a/sugar_network/client/__init__.py b/sugar_network/client/__init__.py
index d9e68fd..6a620f9 100644
--- a/sugar_network/client/__init__.py
+++ b/sugar_network/client/__init__.py
@@ -95,7 +95,7 @@ hub_root = Option(
default='/usr/share/sugar-network/hub')
layers = Option(
- 'space separated list of layers to restrict Sugar Network content by',
+ 'comma separated list of layers to restrict Sugar Network content by',
default=[], type_cast=Option.list_cast, type_repr=Option.list_repr,
name='layers')
@@ -116,7 +116,9 @@ anonymous = Option(
name='anonymous')
accept_language = Option(
- 'specify HTTP Accept-Language header field value manually',
+ 'comma separated list to specify HTTP Accept-Language '
+ 'header field value manually',
+ default=[], type_cast=Option.list_cast, type_repr=Option.list_repr,
name='accept-language', short_option='-l')
cache_limit = Option(
diff --git a/sugar_network/node/__init__.py b/sugar_network/node/__init__.py
index 6b1588f..68f3e2a 100644
--- a/sugar_network/node/__init__.py
+++ b/sugar_network/node/__init__.py
@@ -61,7 +61,7 @@ pull_timeout = Option(
default=30, type_cast=int)
sync_layers = Option(
- 'space separated list of layers to restrict Sugar Network '
+ 'comma separated list of layers to restrict Sugar Network '
'synchronization content',
default=['pilot'], type_cast=Option.list_cast,
type_repr=Option.list_repr, name='sync-layers')
diff --git a/sugar_network/node/stats_node.py b/sugar_network/node/stats_node.py
index a2a2827..6c24278 100644
--- a/sugar_network/node/stats_node.py
+++ b/sugar_network/node/stats_node.py
@@ -30,7 +30,7 @@ stats_node_step = Option(
default=60 * 5, type_cast=int)
stats_node_rras = Option(
- 'space separated list of RRAs for node RRD databases',
+ 'comma separated list of RRAs for node RRD databases',
default=[
'RRA:AVERAGE:0.5:1:288', # one day with 5min step
'RRA:AVERAGE:0.5:3:672', # one week with 15min step
diff --git a/sugar_network/node/stats_user.py b/sugar_network/node/stats_user.py
index 9265502..0b96449 100644
--- a/sugar_network/node/stats_user.py
+++ b/sugar_network/node/stats_user.py
@@ -31,7 +31,7 @@ stats_user_step = Option(
default=60, type_cast=int)
stats_user_rras = Option(
- 'space separated list of RRAs for users\' RRD databases',
+ 'comma separated list of RRAs for users\' RRD databases',
default=[
'RRA:AVERAGE:0.5:1:4320', # one day with 60s step
'RRA:AVERAGE:0.5:5:2016', # one week with 5min step
diff --git a/sugar_network/toolkit/__init__.py b/sugar_network/toolkit/__init__.py
index f7e59ea..c805b06 100644
--- a/sugar_network/toolkit/__init__.py
+++ b/sugar_network/toolkit/__init__.py
@@ -137,6 +137,25 @@ def default_lang():
return _default_lang
+def default_langs():
+ """Default languages list, i.e., including all secondory languages.
+
+ :returns:
+ list of strings in format of HTTP's Accept-Language, e.g., `ru,en-gb`.
+
+ """
+ global _default_langs
+
+ if _default_langs is None:
+ langs = os.environ.get('LANGUAGE')
+ if langs:
+ _default_langs = langs.split(':')
+ else:
+ _default_langs = [default_lang()]
+
+ return _default_langs
+
+
def gettext(value, accept_language=None):
if not value:
return ''
@@ -862,3 +881,4 @@ def _nb_read(stream):
_default_lang = None
+_default_langs = None
diff --git a/sugar_network/toolkit/http.py b/sugar_network/toolkit/http.py
index cadf64c..31f9e5a 100644
--- a/sugar_network/toolkit/http.py
+++ b/sugar_network/toolkit/http.py
@@ -271,8 +271,8 @@ class Connection(object):
headers['content-length'] = str(len(request.content))
for env_key, key, value in (
('HTTP_IF_MODIFIED_SINCE', 'if-modified-since', None),
- ('HTTP_ACCEPT_LANGUAGE', 'accept-language',
- client.accept_language.value),
+ ('HTTP_ACCEPT_LANGUAGE', 'accept-language', ','.join(
+ client.accept_language.value or toolkit.default_langs())),
('HTTP_ACCEPT_ENCODING', 'accept-encoding', None),
):
if value is None:
diff --git a/sugar_network/toolkit/options.py b/sugar_network/toolkit/options.py
index da945af..5f10525 100644
--- a/sugar_network/toolkit/options.py
+++ b/sugar_network/toolkit/options.py
@@ -16,10 +16,15 @@
"""Command-line options parsing utilities."""
import os
+import re
import sys
from os.path import exists, expanduser, isdir, join
+# TODO Replace by ','
+_LIST_SEPARATOR = re.compile(r'[\s,]+')
+
+
class Option(object):
"""Configuration option.
@@ -256,7 +261,7 @@ class Option(object):
@staticmethod
def list_cast(x):
if isinstance(x, basestring):
- return [i for i in x.strip().split() if i]
+ return [i for i in _LIST_SEPARATOR.split(x.strip()) if i]
else:
return x
@@ -289,8 +294,6 @@ class Option(object):
@staticmethod
def _bind(parser, config_files, notice):
- import re
-
if config_files:
Option.config = Option()
Option.config.name = 'config'
@@ -298,10 +301,8 @@ class Option(object):
Option.config.description = \
'colon separated list of paths to configuration file(s)'
Option.config.short_option = '-c'
- Option.config.type_cast = \
- lambda x: [i for i in re.split('[\\s:;,]+', x) if i]
- Option.config.type_repr = \
- lambda x: ':'.join(x)
+ Option.config.type_cast = Option.paths_cast
+ Option.config.type_repr = Option.paths_repr
Option.config.value = ':'.join(config_files)
for prop in [Option.config] + Option.items.values():
diff --git a/sugar_network/toolkit/spec.py b/sugar_network/toolkit/spec.py
index 9dec4b8..6de2b36 100644
--- a/sugar_network/toolkit/spec.py
+++ b/sugar_network/toolkit/spec.py
@@ -43,7 +43,7 @@ _FIELDS = {
_ARCHES = ['all', 'any']
_STABILITIES = ('insecure', 'buggy', 'developer', 'testing', 'stable')
_POLICY_URL = 'http://wiki.sugarlabs.org/go/Sugar_Network/Policy'
-_LIST_SEPARATOR = ';'
+_LIST_SEPARATOR = ','
_RESTRICTION_RE = re.compile('(<|<=|=|>|>=)\\s*([0-9.]+)')
@@ -537,7 +537,8 @@ def _parse_list(str_list):
i = 0
while i < len(str_list):
- if not max(brackets.values()) and str_list[i] == _LIST_SEPARATOR:
+ if not max(brackets.values()) and \
+ str_list[i] in (_LIST_SEPARATOR, ';'):
parts.append(str_list[:i])
str_list = str_list[i + 1:]
i = 0
diff --git a/tests/units/client/routes.py b/tests/units/client/routes.py
index 7514c96..6b0d6e5 100755
--- a/tests/units/client/routes.py
+++ b/tests/units/client/routes.py
@@ -10,7 +10,7 @@ from os.path import exists
from __init__ import tests
-from sugar_network import db, client, model
+from sugar_network import db, client, model, toolkit
from sugar_network.client import journal, IPCConnection, cache_limit, cache_lifetime
from sugar_network.client.routes import ClientRoutes, CachedClientRoutes
from sugar_network.model.user import User
@@ -396,6 +396,96 @@ class RoutesTest(tests.Test):
assert home_volume['implementation'].exists(guid)
assert exists('client/implementation/%s/%s' % (guid[:2], guid))
+ def test_LanguagesFallbackInRequests(self):
+ self.start_online_client()
+ ipc = IPCConnection()
+
+ guid1 = self.node_volume['context'].create({
+ 'type': 'activity',
+ 'title': {'en': '1', 'ru': '2', 'es': '3'},
+ 'summary': '',
+ 'description': '',
+ })
+ guid2 = self.node_volume['context'].create({
+ 'type': 'activity',
+ 'title': {'en': '1', 'ru': '2'},
+ 'summary': '',
+ 'description': '',
+ })
+ guid3 = self.node_volume['context'].create({
+ 'type': 'activity',
+ 'title': {'en': '1'},
+ 'summary': '',
+ 'description': '',
+ })
+
+ client.accept_language.value = ['es', 'ru', 'en']
+ self.assertEqual('3', ipc.get(['context', guid1, 'title']))
+ self.assertEqual('2', ipc.get(['context', guid2, 'title']))
+ self.assertEqual('1', ipc.get(['context', guid3, 'title']))
+
+ client.accept_language.value = ['ru', 'en']
+ self.assertEqual('2', ipc.get(['context', guid1, 'title']))
+ self.assertEqual('2', ipc.get(['context', guid2, 'title']))
+ self.assertEqual('1', ipc.get(['context', guid3, 'title']))
+
+ client.accept_language.value = ['en']
+ self.assertEqual('1', ipc.get(['context', guid1, 'title']))
+ self.assertEqual('1', ipc.get(['context', guid2, 'title']))
+ self.assertEqual('1', ipc.get(['context', guid3, 'title']))
+
+ client.accept_language.value = ['foo']
+ self.assertEqual('1', ipc.get(['context', guid1, 'title']))
+ self.assertEqual('1', ipc.get(['context', guid2, 'title']))
+ self.assertEqual('1', ipc.get(['context', guid3, 'title']))
+
+ def test_DefaultLanguagesFallbackInRequests(self):
+ self.start_online_client()
+ ipc = IPCConnection()
+
+ guid1 = self.node_volume['context'].create({
+ 'type': 'activity',
+ 'title': {'en': '1', 'ru': '2', 'es': '3'},
+ 'summary': '',
+ 'description': '',
+ })
+ guid2 = self.node_volume['context'].create({
+ 'type': 'activity',
+ 'title': {'en': '1', 'ru': '2'},
+ 'summary': '',
+ 'description': '',
+ })
+ guid3 = self.node_volume['context'].create({
+ 'type': 'activity',
+ 'title': {'en': '1'},
+ 'summary': '',
+ 'description': '',
+ })
+
+ toolkit._default_langs = None
+ os.environ['LANGUAGE'] = 'es:ru:en'
+ self.assertEqual('3', ipc.get(['context', guid1, 'title']))
+ self.assertEqual('2', ipc.get(['context', guid2, 'title']))
+ self.assertEqual('1', ipc.get(['context', guid3, 'title']))
+
+ toolkit._default_langs = None
+ os.environ['LANGUAGE'] = 'ru:en'
+ self.assertEqual('2', ipc.get(['context', guid1, 'title']))
+ self.assertEqual('2', ipc.get(['context', guid2, 'title']))
+ self.assertEqual('1', ipc.get(['context', guid3, 'title']))
+
+ toolkit._default_langs = None
+ os.environ['LANGUAGE'] = 'en'
+ self.assertEqual('1', ipc.get(['context', guid1, 'title']))
+ self.assertEqual('1', ipc.get(['context', guid2, 'title']))
+ self.assertEqual('1', ipc.get(['context', guid3, 'title']))
+
+ toolkit._default_langs = None
+ os.environ['LANGUAGE'] = 'foo'
+ self.assertEqual('1', ipc.get(['context', guid1, 'title']))
+ self.assertEqual('1', ipc.get(['context', guid2, 'title']))
+ self.assertEqual('1', ipc.get(['context', guid3, 'title']))
+
def call(routes, request):
router = Router(routes)