diff options
author | Aleksey Lim <alsroot@sugarlabs.org> | 2012-09-09 15:12:33 (GMT) |
---|---|---|
committer | Aleksey Lim <alsroot@sugarlabs.org> | 2012-09-09 15:12:33 (GMT) |
commit | a05942e9473696c65760050a0a23acfd43ea8155 (patch) | |
tree | 3821ad9edaa19a55098f9b877813ee92d665b198 | |
parent | 521eb6e45c8115eef0071864b2bbecec878a9166 (diff) |
Provide default context icons
-rw-r--r-- | README | 8 | ||||
-rw-r--r-- | sugar_network/node/router.py | 18 | ||||
-rw-r--r-- | sugar_network/resources/context.py | 20 | ||||
-rw-r--r-- | sugar_network/static/__init__.py | 19 | ||||
-rw-r--r-- | sugar_network/static/images/missing.png | bin | 0 -> 2727 bytes | |||
-rw-r--r-- | sugar_network/static/images/missing.svg | 69 | ||||
-rw-r--r-- | sugar_network/static/images/package.png | bin | 0 -> 3834 bytes | |||
-rw-r--r-- | tests/__init__.py | 1 | ||||
-rwxr-xr-x | tests/units/home_mount.py | 21 | ||||
-rwxr-xr-x | tests/units/node.py | 17 | ||||
-rwxr-xr-x | tests/units/node_mount.py | 24 | ||||
-rwxr-xr-x | tests/units/remote_mount.py | 18 | ||||
-rwxr-xr-x | tests/units/router.py | 7 |
13 files changed, 197 insertions, 25 deletions
@@ -11,5 +11,13 @@ Clone source repository from `Gitorious`_ project: ``git clone git://git.sugarlabs.org/network/client.git`` +Artwork +======= + +* `sugar-artwork`_ images. +* `Oxygen`_ icons. + .. _home page: http://wiki.sugarlabs.org/go/Platform_Team/Sugar_Network/Client .. _Gitorious: http://git.sugarlabs.org/network +.. _sugar-artwork: http://git.sugarlabs.org/sugar-artwork +.. _Oxygen: http://www.oxygen-icons.org/ diff --git a/sugar_network/node/router.py b/sugar_network/node/router.py index 57ffa1d..888235c 100644 --- a/sugar_network/node/router.py +++ b/sugar_network/node/router.py @@ -17,13 +17,13 @@ import os import cgi import json import types -import urllib import logging from urlparse import parse_qsl from bisect import bisect_left +from os.path import join, isfile import active_document as ad -from sugar_network import node +from sugar_network import node, static from active_toolkit.sockets import BUFFER_SIZE from active_toolkit import util, enforce @@ -52,7 +52,12 @@ class Router(object): try: request.principal = self._authenticate(request) - result = self._cp.call(request, response) + if request.path[:1] == ['static']: + static_path = join(static.PATH, *request.path[1:]) + enforce(isfile(static_path), 'No such file') + result = file(static_path) + else: + result = self._cp.call(request, response) except ad.Redirect, error: response.status = '303 See Other' response['Location'] = error.location @@ -130,11 +135,8 @@ class _Request(ad.Request): self.access_level = ad.ACCESS_REMOTE self.environ = environ - path = environ['PATH_INFO'] or '/' - __, path = urllib.splittype(path) - __, path = urllib.splithost(path) - self.url = path - self.path = [i for i in path.strip('/').split('/') if i] + self.url = '/' + environ['PATH_INFO'].strip('/') + self.path = [i for i in self.url[1:].split('/') if i] self['method'] = environ['REQUEST_METHOD'] self.content = None self.content_stream = environ.get('wsgi.input') diff --git a/sugar_network/resources/context.py b/sugar_network/resources/context.py index 8a6c66f..e670d10 100644 --- a/sugar_network/resources/context.py +++ b/sugar_network/resources/context.py @@ -13,9 +13,11 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +from os.path import join + import active_document as ad -from sugar_network import resources +from sugar_network import resources, static from sugar_network.resources.volume import Resource @@ -58,10 +60,24 @@ class Context(Resource): @ad.active_property(ad.BlobProperty, mime_type='image/png') def icon(self, value): - return value + if value is None: + if 'package' in self['type']: + return {'url': '/static/images/package.png', + 'path': join(static.PATH, 'images', 'package.png'), + 'mime_type': 'image/png'} + else: + return {'url': '/static/images/missing.png', + 'path': join(static.PATH, 'images', 'missing.png'), + 'mime_type': 'image/png'} + else: + return value @ad.active_property(ad.BlobProperty, mime_type='image/svg+xml') def artifact_icon(self, value): + if value is None: + return {'url': '/static/images/missing.svg', + 'path': join(static.PATH, 'images', 'missing.svg'), + 'mime_type': 'image/svg+xml'} return value @ad.active_property(ad.BlobProperty) diff --git a/sugar_network/static/__init__.py b/sugar_network/static/__init__.py new file mode 100644 index 0000000..e65e61d --- /dev/null +++ b/sugar_network/static/__init__.py @@ -0,0 +1,19 @@ +# Copyright (C) 2012 Aleksey Lim +# +# 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 3 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, see <http://www.gnu.org/licenses/>. + +from os.path import dirname + + +PATH = dirname(__file__) diff --git a/sugar_network/static/images/missing.png b/sugar_network/static/images/missing.png Binary files differnew file mode 100644 index 0000000..8d6c26d --- /dev/null +++ b/sugar_network/static/images/missing.png diff --git a/sugar_network/static/images/missing.svg b/sugar_network/static/images/missing.svg new file mode 100644 index 0000000..cba7e35 --- /dev/null +++ b/sugar_network/static/images/missing.svg @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + version="1.0" + width="75" + height="75" + viewBox="-13.5 -13.5 75 75" + id="svg1872" + sodipodi:version="0.32" + inkscape:version="0.44" + sodipodi:docname="stock-missing.svg" + sodipodi:docbase="/home/marco/sugar-jhbuild/source/artwork/art/icon-theme/scalable/stock"> + <metadata + id="metadata42"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <sodipodi:namedview + inkscape:window-height="624" + inkscape:window-width="860" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + guidetolerance="10.0" + gridtolerance="10.0" + objecttolerance="10.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" + inkscape:zoom="8.4791667" + inkscape:cx="24" + inkscape:cy="24.058968" + inkscape:window-x="55" + inkscape:window-y="49" + inkscape:current-layer="svg1872" /> + <defs + id="defs1874" /> + <g + id="layer1"> + <path + d="M 46.857141 26.285715 A 25.142857 16.714285 0 1 1 -3.4285717,26.285715 A 25.142857 16.714285 0 1 1 46.857141 26.285715 z" + transform="matrix(0.889463,0,0,1.337995,4.685959,-11.17014)" + style="opacity:0.66976743;fill:#8a8c90;fill-opacity:1;stroke:black;stroke-width:3;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path4550" /> + <text + x="4.7315407" + y="46.846149" + transform="scale(1.186648,0.84271)" + style="font-size:50.32819366px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + id="text4552" + xml:space="preserve"><tspan + x="4.7315407" + y="46.846149" + id="tspan4554" /></text> + </g> +</svg> diff --git a/sugar_network/static/images/package.png b/sugar_network/static/images/package.png Binary files differnew file mode 100644 index 0000000..b8134cf --- /dev/null +++ b/sugar_network/static/images/package.png diff --git a/tests/__init__.py b/tests/__init__.py index a1a83af..2c455c0 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -93,6 +93,7 @@ class Test(unittest.TestCase): Volume.RESOURCES = [ 'sugar_network.resources.user', 'sugar_network.resources.context', + 'sugar_network.resources.report', ] sugar.nickname = lambda: 'test' diff --git a/tests/units/home_mount.py b/tests/units/home_mount.py index a470200..c9c9119 100755 --- a/tests/units/home_mount.py +++ b/tests/units/home_mount.py @@ -9,6 +9,7 @@ from __init__ import tests from active_toolkit import sockets, coroutine from sugar_network import Client +from sugar_network.resources.report import Report class HomeMountTest(tests.Test): @@ -119,6 +120,19 @@ class HomeMountTest(tests.Test): assert not exists('file2') def test_GetAbsetnBLOB(self): + self.start_server([Report]) + client = Client('~') + + guid = client.Report( + context='context', + implementation='implementation', + description='description').post() + + path, mime_type = client.Report(guid).get_blob_path('data') + self.assertEqual(None, path) + self.assertEqual(True, client.Report(guid).get_blob('data').closed) + + def test_GetDefaultBLOB(self): self.start_server() client = Client('~') @@ -129,8 +143,9 @@ class HomeMountTest(tests.Test): description='description').post() path, mime_type = client.Context(guid).get_blob_path('icon') - self.assertEqual(None, path) - self.assertEqual(True, client.Context(guid).get_blob('icon').closed) + assert path.endswith('missing.png') + assert exists(path) + self.assertEqual(False, client.Context(guid).get_blob('icon').closed) def test_Subscription(self): self.start_server() @@ -202,7 +217,7 @@ class HomeMountTest(tests.Test): event = subscription.read_message() event.pop('props') self.assertEqual( - {'document': 'context', 'event': 'update', 'guid': guid, 'seqno': 2}, + {'document': 'context', 'event': 'update', 'guid': guid, 'seqno': 4}, event) def test_Connect(self): diff --git a/tests/units/node.py b/tests/units/node.py index ea3c120..4d54456 100755 --- a/tests/units/node.py +++ b/tests/units/node.py @@ -282,9 +282,14 @@ class NodeTest(tests.Test): 'description': 'description', }) volume['context'].set_blob(guid3, 'icon', '/foo/bar') + guid4 = call(cp, method='POST', document='report', principal='principal', content={ + 'context': 'context', + 'implementation': 'implementation', + 'description': 'description', + }) self.assertEqual( - {'guid': guid1, 'icon': 'http://localhost:8000/context/%s/icon' % guid1}, + {'guid': guid1, 'icon': 'http://localhost:8000/static/images/missing.png'}, call(cp, method='GET', document='context', guid=guid1, reply=['guid', 'icon'])) self.assertEqual( {'guid': guid2, 'icon': 'http://foo/bar'}, @@ -292,14 +297,22 @@ class NodeTest(tests.Test): self.assertEqual( {'guid': guid3, 'icon': 'http://localhost:8000/foo/bar'}, call(cp, method='GET', document='context', guid=guid3, reply=['guid', 'icon'])) + self.assertEqual( + {'guid': guid4, 'data': 'http://localhost:8000/report/%s/data' % guid4}, + call(cp, method='GET', document='report', guid=guid4, reply=['guid', 'data'])) self.assertEqual([ - {'guid': guid1, 'icon': 'http://localhost:8000/context/%s/icon' % guid1}, + {'guid': guid1, 'icon': 'http://localhost:8000/static/images/missing.png'}, {'guid': guid2, 'icon': 'http://foo/bar'}, {'guid': guid3, 'icon': 'http://localhost:8000/foo/bar'}, ], call(cp, method='GET', document='context', reply=['guid', 'icon'])['result']) + self.assertEqual([ + {'guid': guid4, 'data': 'http://localhost:8000/report/%s/data' % guid4}, + ], + call(cp, method='GET', document='report', reply=['guid', 'data'])['result']) + def call(cp, principal=None, content=None, **kwargs): request = ad.Request(**kwargs) diff --git a/tests/units/node_mount.py b/tests/units/node_mount.py index 8aa0043..eed94f7 100755 --- a/tests/units/node_mount.py +++ b/tests/units/node_mount.py @@ -20,6 +20,7 @@ from sugar_network.resources.user import User from sugar_network.resources.context import Context from sugar_network import local, Client, sugar from sugar_network.resources.volume import Volume +from sugar_network.resources.report import Report class NodeMountTest(tests.Test): @@ -34,7 +35,7 @@ class NodeMountTest(tests.Test): def start_server(self, ipc=False): local.mounts_root.value = tests.tmpdir - volume = Volume('local', [User, Context]) + volume = Volume('local', [User, Context, Report]) mounts = Mountset(volume) if ipc: self.server = IPCServer(mounts) @@ -325,6 +326,22 @@ class NodeMountTest(tests.Test): self.got_event.wait() client = Client(tests.tmpdir + '/mnt') + guid = client.Report( + context='context', + implementation='implementation', + description='description').post() + + path, mime_type = client.Report(guid).get_blob_path('data') + self.assertEqual(None, path) + self.assertEqual(True, client.Report(guid).get_blob('data').closed) + + def test_GetDefaultBLOB(self): + self.touch('mnt/.sugar-network') + self.touch(('mnt/node', 'node')) + self.start_server() + self.got_event.wait() + client = Client(tests.tmpdir + '/mnt') + guid = client.Context( type='activity', title='title', @@ -332,8 +349,9 @@ class NodeMountTest(tests.Test): description='description').post() path, mime_type = client.Context(guid).get_blob_path('icon') - self.assertEqual(None, path) - self.assertEqual(True, client.Context(guid).get_blob('icon').closed) + assert path.endswith('missing.png') + assert exists(path) + self.assertEqual(False, client.Context(guid).get_blob('icon').closed) def test_get_blob_ExtractImplementations(self): Volume.RESOURCES = [ diff --git a/tests/units/remote_mount.py b/tests/units/remote_mount.py index 45876dd..b06e686 100755 --- a/tests/units/remote_mount.py +++ b/tests/units/remote_mount.py @@ -17,6 +17,7 @@ from sugar_network.local.bus import IPCServer from sugar_network.toolkit import sugar, http from sugar_network.resources.user import User from sugar_network.resources.context import Context +from sugar_network.resources.report import Report from sugar_network.resources.volume import Volume @@ -297,6 +298,19 @@ class RemoteMountTest(tests.Test): self.assertEqual(4, json.load(file(cache_path + '.meta'))['seqno']) def test_GetAbsentBLOB(self): + self.start_ipc_and_restful_server([User, Report]) + client = Client('/') + + guid = client.Report( + context='context', + implementation='implementation', + description='description').post() + + path, mime_type = client.Report(guid).get_blob_path('data') + self.assertEqual(None, path) + self.assertEqual(True, client.Report(guid).get_blob('data').closed) + + def test_GetDefaultBLOB(self): self.start_ipc_and_restful_server() client = Client('/') @@ -307,8 +321,8 @@ class RemoteMountTest(tests.Test): description='description').post() path, mime_type = client.Context(guid).get_blob_path('icon') - self.assertEqual(None, path) - self.assertEqual(True, client.Context(guid).get_blob('icon').closed) + assert exists(path) + self.assertEqual(False, client.Context(guid).get_blob('icon').closed) def test_Localize(self): os.environ['LANG'] = 'en_US' diff --git a/tests/units/router.py b/tests/units/router.py index f41ae10..b2daef8 100755 --- a/tests/units/router.py +++ b/tests/units/router.py @@ -224,13 +224,10 @@ class RouterTest(tests.Test): self.fork(self.restful_server, [User, Document]) rest = tests.Request('http://localhost:8800') - # Should `urllib.splithost('//foo')` return `('foo', '')` ? - self.assertRaises(RuntimeError, rest.post, '//document/', {'term': 'probe'}) - - guid = rest.post('/document//', {'term': 'probe'}) + guid = rest.post('///document//', {'term': 'probe'}) self.assertEqual( {'term': 'probe'}, - rest.get('///document//%s/' % guid, reply='term')) + rest.get('///document///%s///' % guid, reply='term')) def test_HandleRedirects(self): URL = 'http://sugarlabs.org' |