@@ -1,4 +1,4 @@
AC_INIT([Sugar],[0.101.3],[],[sugar])
AC_INIT([Sugar],[0.101.4],[],[sugar])

AC_PREREQ([2.59])

@@ -18,7 +18,7 @@

from gettext import gettext as _

from gi.repository import Gtk
from gi.repository import Gtk, Pango
from gi.repository import Gdk

from sugar3.graphics import style
@@ -206,6 +206,8 @@ def license_expander_cb(self, expander, param_spec):
view_license = Gtk.TextView()
view_license.set_editable(False)
view_license.get_buffer().set_text(self._model.get_license())
fd = Pango.FontDescription('Monospace')
view_license.modify_font(fd)
view_license.show()
expander.add(view_license)
else:
@@ -41,6 +41,7 @@ def __init__(self, model, alerts):
self._model = updater.get_instance()
self._model.connect('progress', self.__progress_cb)
self._model.connect('updates-available', self.__updates_available_cb)
self._model.connect('error', self.__error_cb)
self._model.connect('finished', self.__finished_cb)

self.set_spacing(style.DEFAULT_SPACING)
@@ -57,15 +58,15 @@ def __init__(self, model, alerts):
self.pack_start(separator, False, True, 0)
separator.show()

bottom_label = Gtk.Label()
bottom_label.set_line_wrap(True)
bottom_label.set_justify(Gtk.Justification.LEFT)
bottom_label.props.xalign = 0
bottom_label.set_markup(
self._bottom_label = Gtk.Label()
self._bottom_label.set_line_wrap(True)
self._bottom_label.set_justify(Gtk.Justification.LEFT)
self._bottom_label.props.xalign = 0
self._bottom_label.set_markup(
_('Software updates correct errors, eliminate security '
'vulnerabilities, and provide new features.'))
self.pack_start(bottom_label, False, True, 0)
bottom_label.show()
self.pack_start(self._bottom_label, False, True, 0)
self._bottom_label.show()

self._update_box = None
self._progress_pane = None
@@ -165,6 +166,15 @@ def __updates_available_cb(self, model, updates):
else:
self._switch_to_update_box(updates)

def __error_cb(self, model, updates):
logging.debug('ActivityUpdater.__error_cb')
top_message = _('Can\'t connect to the activity server')
self._top_label.set_markup('<big>%s</big>' % top_message)
self._bottom_label.set_markup(
_('Verify your connection to internet and try again, '
'or try again later'))
self._clear_center()

def __refresh_button_clicked_cb(self, button):
self._refresh()

@@ -182,9 +182,10 @@ def _check_next_update(self):
self._checker.check(bundle)

def fetch_update_info(self, installed_bundles, auto, progress_cb,
completion_cb):
completion_cb, error_cb):
self._completion_cb = completion_cb
self._progress_cb = progress_cb
self._error_cb = error_cb
self._cancelling = False
self._updates = []
self._bundles_to_check = installed_bundles
@@ -118,7 +118,10 @@ def handle_data(self, data):
self.group_desc = data.strip()

if self.in_activity_id > 0:
self.last_id = data.strip()
if self.last_id is None:
self.last_id = data.strip()
else:
self.last_id = self.last_id + data.strip()

if self.in_activity_version > 0:
try:
@@ -178,7 +181,10 @@ def _query(self):
return

self._parser = _UpdateHTMLParser(url)
downloader = Downloader(url)
# wiki.laptop.org have agresive cache, we set max-age=600
# to be sure the page is no older than 10 minutes
request_headers = {'Cache-Control': 'max-age=600'}
downloader = Downloader(url, request_headers=request_headers)
downloader.connect('got-chunk', self._got_chunk_cb)
downloader.connect('complete', self._complete_cb)
downloader.download_chunked()
@@ -190,7 +196,7 @@ def _got_chunk_cb(self, downloader, data):
def _complete_cb(self, downloader, result):
if isinstance(result, Exception):
_logger.warning("Failed to read update info: %s", result)
self._completion_cb([])
self._error_cb(result)
return

self._parser.close()
@@ -277,9 +283,10 @@ def _name_lookup_complete(self, lookup, result, size):
self._check_next_update()

def fetch_update_info(self, installed_bundles, auto, progress_cb,
completion_cb):
completion_cb, error_cb):
self._completion_cb = completion_cb
self._progress_cb = progress_cb
self._error_cb = error_cb
self._cancelling = False
self._updates = []
self._bundles_to_check = []
@@ -58,6 +58,8 @@ class Updater(GObject.GObject):
'progress': (GObject.SignalFlags.RUN_FIRST,
None,
(int, str, float)),
'error': (GObject.SignalFlags.RUN_FIRST,
None, (str,)),
'finished': (GObject.SignalFlags.RUN_FIRST,
None,
(object, object, bool))
@@ -105,7 +107,8 @@ def check_updates(self, auto=False):
bundles = list(bundleregistry.get_registry())
self._model.fetch_update_info(bundles, auto,
self._backend_progress_cb,
self._backend_finished_cb)
self._backend_finished_cb,
self._backend_error_cb)

def _backend_progress_cb(self, bundle_name, progress):
self.emit('progress', self._state, bundle_name, progress)
@@ -123,6 +126,11 @@ def _backend_finished_cb(self, updates):
else:
self.emit('updates-available', self._updates)

def _backend_error_cb(self, error):
_logger.debug("_backend_error_cb %s", error)
self._finished(True)
self.emit('error', error)

def update(self, bundle_ids):
if self._state != STATE_CHECKED:
raise UpdaterStateException()
@@ -59,7 +59,7 @@ class Downloader(GObject.GObject):
(object,)),
}

def __init__(self, url, session=None):
def __init__(self, url, session=None, request_headers=None):
GObject.GObject.__init__(self)
self._uri = Soup.URI.new(url)
self._session = session or get_soup_session()
@@ -71,11 +71,16 @@ def __init__(self, url, session=None):
self._output_file = None
self._output_stream = None
self._message = None
self._request_headers = request_headers

def _setup_message(self, method="GET"):
self._message = Soup.Message(method=method, uri=self._uri)
self._message.connect('got-chunk', self._got_chunk_cb)
self._message.connect('got-headers', self._headers_cb, None)
if self._request_headers is not None:
for header_key in self._request_headers.keys():
self._message.request_headers.append(
header_key, self._request_headers[header_key])

def download_to_temp(self):
"""
@@ -0,0 +1,63 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2014, Ignacio Rodriguez
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

import unittest

from cpsection.aboutme import model
from jarabe.intro.agepicker import AGES
from jarabe.intro.genderpicker import GENDERS

TEST_NICKS = ['Ajay Garg', 'Aleksey Lim',
'Bernie H. Innocenti', 'Daniel Narvaez',
'Emil Dudev', 'Gonzalo Odiard',
'Ignacio Rodríguez', 'Jorge Alberto Gómez López',
'Sai Vineet', 'Sam Parkinson',
'Sascha Silbe', 'Walter Bender']

TEST_COLORS = [['#FF8F00', '#FF2B34'],
['#00A0FF', '#008009'],
['#BCCEFF', '#F8E800'],
['#FF2B34', '#7F00BF'],
['#FF2B34', '#5E008C'],
['#BCCDFF', '#AC32FF'],
['#00EA11', '#9A5200'],
['#A700FF', '#FF8F00'],
['#00EA11', '#7F00BF'],
['#8BFF7A', '#F8E800'],
['#00A0FF', '#5E008C'],
['#7F00BF', '#AC32FF']]


class TestUserProfile(unittest.TestCase):
def test_user_gender_age(self):
for gender in GENDERS:
for age in AGES:
model.set_gender(gender)
model.set_age(age)
self.assertEqual(model.get_age(), age)
self.assertEqual(model.get_gender(), gender)

def test_user_nick(self):
for nick in TEST_NICKS:
model.set_nick(nick)
self.assertEqual(model.get_nick(), nick)

def test_user_color(self):
for new_color in TEST_COLORS:
new_color = "%s,%s" % (new_color[0], new_color[1])
model.set_color_xo(new_color)
self.assertEqual(model.get_color(), new_color)