Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksey Lim <alsroot@sugarlabs.org>2012-03-26 18:42:46 (GMT)
committer Aleksey Lim <alsroot@sugarlabs.org>2012-03-26 18:42:46 (GMT)
commitda6f0b92e2e58b5d8ad7c4f0dc901a4e07c932de (patch)
treef9a0d9b62ff180299a0bb3c8981ac177356b925a
parentf1dcc4e647e4f06127e3c4f41d2f7aaa40f46022 (diff)
Keep feed for entire context to avoid needless queries
-rw-r--r--doc/objects.dia107
-rwxr-xr-xmisc/aslo_sync.py55
-rw-r--r--sugar_network_server/resources/context.py100
-rw-r--r--sugar_network_server/resources/implementation.py76
-rw-r--r--sugar_network_server/resources/resource.py2
5 files changed, 193 insertions, 147 deletions
diff --git a/doc/objects.dia b/doc/objects.dia
index 4579ae3..b3e7ce2 100644
--- a/doc/objects.dia
+++ b/doc/objects.dia
@@ -87,19 +87,19 @@
<dia:layer name="Background" visible="true" active="true">
<dia:object type="UML - Class" version="0" id="O0">
<dia:attribute name="obj_pos">
- <dia:point val="30,25"/>
+ <dia:point val="30,21"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="29.985,24.985;48.6675,51.015"/>
+ <dia:rectangle val="29.985,20.985;48.6675,51.815"/>
</dia:attribute>
<dia:attribute name="elem_corner">
- <dia:point val="30,25"/>
+ <dia:point val="30,21"/>
</dia:attribute>
<dia:attribute name="elem_width">
<dia:real val="18.6525"/>
</dia:attribute>
<dia:attribute name="elem_height">
- <dia:real val="26"/>
+ <dia:real val="30.800000000000001"/>
</dia:attribute>
<dia:attribute name="name">
<dia:string>#Context#</dia:string>
@@ -197,7 +197,7 @@
<dia:string>#type#</dia:string>
</dia:attribute>
<dia:attribute name="type">
- <dia:string>#enum [R WN S]#</dia:string>
+ <dia:string>#[enum] [R WN S]#</dia:string>
</dia:attribute>
<dia:attribute name="value">
<dia:string>##</dia:string>
@@ -355,6 +355,29 @@
</dia:composite>
<dia:composite type="umlattribute">
<dia:attribute name="name">
+ <dia:string>#mime_types#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="type">
+ <dia:string>#[str] [R WA]#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="value">
+ <dia:string>#[]#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="comment">
+ <dia:string>#List of MIME types that supported for Artifacts created within the Context#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="visibility">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ <dia:attribute name="abstract">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ <dia:attribute name="class_scope">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ </dia:composite>
+ <dia:composite type="umlattribute">
+ <dia:attribute name="name">
<dia:string>#icon#</dia:string>
</dia:attribute>
<dia:attribute name="type">
@@ -401,6 +424,29 @@
</dia:composite>
<dia:composite type="umlattribute">
<dia:attribute name="name">
+ <dia:string>#feed#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="type">
+ <dia:string>#blob [R]#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="value">
+ <dia:string>##</dia:string>
+ </dia:attribute>
+ <dia:attribute name="comment">
+ <dia:string>#Zero Instrall feed informaiton#</dia:string>
+ </dia:attribute>
+ <dia:attribute name="visibility">
+ <dia:enum val="0"/>
+ </dia:attribute>
+ <dia:attribute name="abstract">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ <dia:attribute name="class_scope">
+ <dia:boolean val="false"/>
+ </dia:attribute>
+ </dia:composite>
+ <dia:composite type="umlattribute">
+ <dia:attribute name="name">
<dia:string>#rating#</dia:string>
</dia:attribute>
<dia:attribute name="type">
@@ -1050,17 +1096,17 @@
</dia:object>
<dia:object type="UML - Association" version="2" id="O3">
<dia:attribute name="obj_pos">
- <dia:point val="48.6676,38"/>
+ <dia:point val="48.6676,36.4"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="48.65,37.24;53.0176,54.84"/>
+ <dia:rectangle val="48.65,35.64;53.0176,54.84"/>
</dia:attribute>
<dia:attribute name="meta">
<dia:composite type="dict"/>
</dia:attribute>
<dia:attribute name="orth_points">
- <dia:point val="48.6676,38"/>
- <dia:point val="51,38"/>
+ <dia:point val="48.6676,36.4"/>
+ <dia:point val="51,36.4"/>
<dia:point val="51,54"/>
<dia:point val="53,54"/>
</dia:attribute>
@@ -1124,7 +1170,7 @@
<dia:color val="#000000ff"/>
</dia:attribute>
<dia:connections>
- <dia:connection handle="0" to="O0" connection="30"/>
+ <dia:connection handle="0" to="O0" connection="34"/>
</dia:connections>
</dia:object>
<dia:object type="UML - Association" version="2" id="O4">
@@ -1209,17 +1255,17 @@
</dia:object>
<dia:object type="UML - Association" version="2" id="O5">
<dia:attribute name="obj_pos">
- <dia:point val="39.3263,51"/>
+ <dia:point val="39.3263,51.8"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="39.3087,50.24;40.1,54.84"/>
+ <dia:rectangle val="39.3086,51.04;40.1,54.84"/>
</dia:attribute>
<dia:attribute name="meta">
<dia:composite type="dict"/>
</dia:attribute>
<dia:attribute name="orth_points">
- <dia:point val="39.3263,51"/>
- <dia:point val="40,51"/>
+ <dia:point val="39.3263,51.8"/>
+ <dia:point val="40,51.8"/>
<dia:point val="40,54"/>
<dia:point val="39.5,54"/>
</dia:attribute>
@@ -3651,7 +3697,7 @@
<dia:point val="54,38"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="53.985,37.985;65.6275,64.415"/>
+ <dia:rectangle val="53.985,37.985;65.6275,61.615"/>
</dia:attribute>
<dia:attribute name="elem_corner">
<dia:point val="54,38"/>
@@ -3660,7 +3706,7 @@
<dia:real val="11.612500000000001"/>
</dia:attribute>
<dia:attribute name="elem_height">
- <dia:real val="26.400000000000006"/>
+ <dia:real val="23.600000000000005"/>
</dia:attribute>
<dia:attribute name="name">
<dia:string>#Implementation#</dia:string>
@@ -3893,29 +3939,6 @@
</dia:composite>
<dia:composite type="umlattribute">
<dia:attribute name="name">
- <dia:string>#feed#</dia:string>
- </dia:attribute>
- <dia:attribute name="type">
- <dia:string>#dict [R WN]#</dia:string>
- </dia:attribute>
- <dia:attribute name="value">
- <dia:string>##</dia:string>
- </dia:attribute>
- <dia:attribute name="comment">
- <dia:string>#Zero Install Implementation parameters to add to feed#</dia:string>
- </dia:attribute>
- <dia:attribute name="visibility">
- <dia:enum val="0"/>
- </dia:attribute>
- <dia:attribute name="abstract">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="class_scope">
- <dia:boolean val="false"/>
- </dia:attribute>
- </dia:composite>
- <dia:composite type="umlattribute">
- <dia:attribute name="name">
<dia:string>#bundle#</dia:string>
</dia:attribute>
<dia:attribute name="type">
@@ -4175,16 +4198,16 @@
</dia:object>
<dia:object type="UML - Association" version="2" id="O24">
<dia:attribute name="obj_pos">
- <dia:point val="59.8062,64.4"/>
+ <dia:point val="59.8062,61.6"/>
</dia:attribute>
<dia:attribute name="obj_bb">
- <dia:rectangle val="59.7886,64.3824;68.0176,73.14"/>
+ <dia:rectangle val="59.7886,61.5824;68.0176,73.14"/>
</dia:attribute>
<dia:attribute name="meta">
<dia:composite type="dict"/>
</dia:attribute>
<dia:attribute name="orth_points">
- <dia:point val="59.8062,64.4"/>
+ <dia:point val="59.8062,61.6"/>
<dia:point val="59.8062,72.3"/>
<dia:point val="68,72.3"/>
</dia:attribute>
diff --git a/misc/aslo_sync.py b/misc/aslo_sync.py
index fde4b6a..68e31e8 100755
--- a/misc/aslo_sync.py
+++ b/misc/aslo_sync.py
@@ -7,6 +7,8 @@ import getpass
import MySQLdb as mdb
+from sweets_recipe import GOOD_LICENSES
+
import restful_document
import sugar_network as client
import sugar_network_server as server
@@ -79,25 +81,20 @@ def import_versions():
(select max(localized_string) from translations where
id=licenses.text),
versions.created,
- versions.version,
(select max(localized_string) from translations where
id=versions.releasenotes),
- files.filename,
- (select version from appversions where
- id=applications_versions.min),
- (select version from appversions where
- id=applications_versions.max)
+ files.filename
FROM addons
INNER JOIN versions ON versions.addon_id=addons.id
INNER JOIN licenses ON licenses.id=versions.license_id
INNER JOIN files ON files.version_id=versions.id
INNER JOIN applications_versions ON
applications_versions.version_id=versions.id
- WHERE addons.status=4
+ WHERE addons.status=4 and addons.id = 4037
""")
for row in rows:
- addon_id, bundle_id, license_id, alicense, release_date, version, \
- releasenotes, filename, sugar_min, sugar_max = row
+ addon_id, bundle_id, license_id, alicense, release_date, \
+ releasenotes, filename = row
if [i for i in EXCLUDE_BUNDLE_IDS if i in bundle_id]:
continue
@@ -116,7 +113,7 @@ def import_versions():
elif license_id == 6:
alicense = 'BSD'
else:
- for good in server.GOOD_LICENSES:
+ for good in GOOD_LICENSES:
if not alicense or good in ['ec']:
continue
if good in alicense:
@@ -136,27 +133,17 @@ def import_versions():
for i in client.Context.find(implement=[bundle_id]):
if i['implement'] == [bundle_id]:
- context_guid = i['guid']
+ context = i
break
else:
- context_guid = context_new(addon_id, bundle_id)
-
- impl = client.Implementation()
- impl['context'] = context_guid
- impl['license'] = [alicense]
- impl['version'] = version
- impl['date'] = int(time.mktime(release_date.timetuple()))
- impl['stability'] = 'stable'
- impl['notes'] = releasenotes or ''
- impl['feed'] = {
- 'requires': {
- sugar_guid: {'constraints': sugar_max},
- },
- }
- impl.post()
- impl.set_blob_with_url('bundle',
- 'http://download.sugarlabs.org/activities/%s/%s' % \
- (addon_id, filename))
+ context = context_new(addon_id, bundle_id)
+
+ context.call('release-from-aslo', 'POST',
+ url='http://download.sugarlabs.org/activities/%s/%s' % \
+ (addon_id, filename),
+ notes=releasenotes or 'Mirror activity from ASLO',
+ date=int(time.mktime(release_date.timetuple())),
+ licenses=alicense)
def context_new(addon_id, bundle_id):
@@ -210,7 +197,7 @@ def context_new(addon_id, bundle_id):
context.post()
if icondata:
- context.set_blob('icon', icondata)
+ context.blobs['icon'] = icondata
for row in sqlexec("""
SELECT
@@ -232,11 +219,11 @@ def context_new(addon_id, bundle_id):
artifact.post()
if thumb:
- artifact.set_blob('preview', thumb)
+ artifact.blobs['preview'] = thumb
if data:
- artifact.set_blob('data', data)
+ artifact.blobs['data'] = data
- return context['guid']
+ return context
def sqlexec(text):
@@ -255,7 +242,7 @@ if __name__ == '__main__':
server.index_flush_timeout.value = 0
server.trust_users.value = True
- server_pid = restful_document.fork(server.resources())
+ server_pid = restful_document.fork(server.resources)
client.api_url.value = \
'http://%s:%s' % (server.host.value, server.port.value)
diff --git a/sugar_network_server/resources/context.py b/sugar_network_server/resources/context.py
index 1777146..0cfa534 100644
--- a/sugar_network_server/resources/context.py
+++ b/sugar_network_server/resources/context.py
@@ -15,21 +15,32 @@
# pylint: disable-msg=E1101,E0102
+import os
+import json
+from cStringIO import StringIO
+from os.path import exists, join
+from gettext import gettext as _
+
import active_document as ad
+import restful_document as rd
+from sweets_recipe import Bundle
+enforce = ad.util.enforce
from sugar_network_server import env
from sugar_network_server.resources.resource import Resource, Vote
+_ASLO_DOWNLOAD_URL = 'http://download.sugarlabs.org/activities'
+_ASLO_ACTIVITIES_PATH = '/upload/activities'
+
+
class Context(Resource):
- @ad.active_property(slot=1, prefix='T',
- permissions=ad.ACCESS_CREATE | ad.ACCESS_READ,
- typecast=env.CONTEXT_TYPES)
+ @ad.active_property(prefix='T', typecast=[env.CONTEXT_TYPES])
def type(self, value):
return value
- @ad.active_property(slot=2, prefix='N', full_text=True,
+ @ad.active_property(slot=1, prefix='N', full_text=True,
permissions=ad.ACCESS_READ, default='')
def name(self, value):
return value
@@ -43,7 +54,7 @@ class Context(Resource):
def implement(self, value):
return value
- @ad.active_property(slot=3, prefix='S', full_text=True)
+ @ad.active_property(slot=2, prefix='S', full_text=True)
def title(self, value):
return value
@@ -51,7 +62,7 @@ class Context(Resource):
def title(self, value):
return value
- @ad.active_property(slot=4, prefix='R', full_text=True)
+ @ad.active_property(slot=3, prefix='R', full_text=True)
def summary(self, value):
return value
@@ -67,7 +78,7 @@ class Context(Resource):
def description(self, value):
return value
- @ad.active_property(slot=5, prefix='H', default='', full_text=True)
+ @ad.active_property(slot=4, prefix='H', default='', full_text=True)
def homepage(self, value):
return value
@@ -75,11 +86,24 @@ class Context(Resource):
def homepage(self, value):
return value
+ @ad.active_property(prefix='Y', default=[], typecast=[])
+ def mime_types(self, value):
+ return value
+
@ad.active_property(ad.BlobProperty)
def icon(self, value):
return value
- @ad.active_property(ad.CounterProperty, slot=6)
+ @ad.active_property(ad.BlobProperty)
+ def artifact_icon(self, value):
+ return value
+
+ @ad.active_property(ad.BlobProperty,
+ permissions=ad.ACCESS_READ, mime_type='application/json')
+ def feed(self, value):
+ return value
+
+ @ad.active_property(ad.CounterProperty, slot=5)
def rating(self, value):
return value
@@ -90,3 +114,63 @@ class Context(Resource):
@vote.setter
def vote(self, value):
return value
+
+ @rd.restful_method(method='POST', cmd='release-from-aslo')
+ def _release_from_aslo(self, url, date, notes, licenses):
+ from sugar_network_server import resources
+
+ enforce(rd.principal.user in self.author, rd.Forbidden,
+ _('Operation is permitted only for authors'))
+ enforce(url.startswith(_ASLO_DOWNLOAD_URL))
+
+ path = url[len(_ASLO_DOWNLOAD_URL):].strip('/').split('/')
+ enforce(len(path) == 2 and path[-1].endswith('.xo'),
+ _('Incorrect activities.sugarlabs.org path'))
+ path = join(_ASLO_ACTIVITIES_PATH, *path)
+ enforce(exists(path), _('Cannot find ASLO bundle at %s'), path)
+
+ bundle = Bundle(path)
+ spec = bundle.get_spec()
+ # TODO
+ #spec.lint()
+
+ feed_data = self.get_blob('feed')
+ if feed_data is None:
+ feed = {}
+ else:
+ feed = json.load(feed_data)
+
+ impl = resources.Implementation(
+ author=[rd.principal.user],
+ context=self.guid,
+ license=licenses,
+ version=spec.version,
+ date=date,
+ stability=spec.stability,
+ notes=notes)
+ impl.post()
+
+ if not feed or spec.version >= max(feed.keys()):
+ self['type'] = spec.types
+ self['title'] = spec.name
+ self['summary'] = spec.summary
+ self['description'] = spec.description
+ self['homepage'] = spec.homepage
+ self['tags'] = spec.tags
+ self['mime_types'] = spec.mime_types
+ self.post()
+
+ icon_path = join(bundle.extract, spec.icon)
+ self.set_blob('artifact_icon', bundle.extractfile(icon_path))
+
+ feed.setdefault(spec.version, {})
+ feed[spec.version]['*-*'] = {
+ 'guid': impl.guid,
+ 'stability': spec.stability,
+ 'commands': spec.commands,
+ 'requires': spec.requires,
+ 'url': url,
+ 'extract': bundle.extract,
+ 'size': os.stat(path).st_size,
+ }
+ self.set_blob('feed', StringIO(json.dumps(feed)), raw=True)
diff --git a/sugar_network_server/resources/implementation.py b/sugar_network_server/resources/implementation.py
index 8b2f5ad..a766375 100644
--- a/sugar_network_server/resources/implementation.py
+++ b/sugar_network_server/resources/implementation.py
@@ -15,26 +15,16 @@
# pylint: disable-msg=E1101,E0102,E0202
-import os
-import zipfile
-from cStringIO import StringIO
-from ConfigParser import ConfigParser
-from os.path import exists, join
-from gettext import gettext as _
+import json
import active_document as ad
import restful_document as rd
-enforce = ad.util.enforce
+from sweets_recipe import GOOD_LICENSES
from sugar_network_server import env
-from sugar_network_server.licenses import GOOD_LICENSES
from sugar_network_server.resources.resource import Resource
-_ASLO_DOWNLOAD_URL = 'http://download.sugarlabs.org/activities'
-_ASLO_ACTIVITIES_PATH = '/upload/activities'
-
-
class Implementation(Resource):
@ad.active_property(prefix='C',
@@ -63,16 +53,6 @@ class Implementation(Resource):
def stability(self, value):
return value
- @ad.active_property(ad.StoredProperty, typecast=dict, default={})
- def feed(self, value):
- return value
-
- @feed.setter
- def feed(self, value):
- value.setdefault('implementations', {})
- value['implementations'].setdefault('*-*', {})
- return value
-
@ad.active_property(full_text=True,
permissions=ad.ACCESS_CREATE | ad.ACCESS_READ)
def notes(self, value):
@@ -82,45 +62,17 @@ class Implementation(Resource):
def bundle(self, value):
return value
- def recv_blob(self, prop, url):
- if not url.startswith(_ASLO_DOWNLOAD_URL):
- return Resource.recv_blob(self, prop, url)
-
- path = url[len(_ASLO_DOWNLOAD_URL):].strip('/').split('/')
- enforce(len(path) == 2 and path[-1].endswith('.xo'),
- _('Incorrect activities.sugarlabs.org path'))
-
- feed = self.feed
- feed['implementations']['*-*']['url'] = url
-
- path = join(_ASLO_ACTIVITIES_PATH, *path)
- if exists(path):
- try:
- zp = zipfile.ZipFile(path)
- extract = zp.namelist()[0].split(os.sep)[0]
-
- activity_info_data = StringIO(
- zp.read(join(extract, 'activity', 'activity.info')))
- activity_info = ConfigParser()
- activity_info.readfp(activity_info_data)
-
- if activity_info.has_option('Activity', 'exec'):
- exec_cmd = activity_info.get('Activity', 'exec')
- else:
- exec_cmd = 'sugar-activity %s' % \
- activity_info.get('Activity', 'class')
- feed['commands'] = {
- 'activity': exec_cmd,
- }
- except Exception, error:
- ad.util.exception()
- raise RuntimeError(_('Cannot read bundle: %s') % error)
-
- self.feed = feed
- self.post()
-
def send_blob(self, prop):
- url = self.feed['implementations']['*-*'].get('url')
- if url:
- raise rd.SeeOther(url)
+ from sugar_network_server import resources
+
+ context = resources.Context(self['context'])
+ feed_data = context.get_blob('feed')
+
+ if feed_data is not None:
+ feed = json.load(feed_data)
+ if self['version'] in feed:
+ url = feed[self['version']]['*-*'].get('url')
+ if url:
+ raise rd.SeeOther(url)
+
return Resource.send_blob(self, prop)
diff --git a/sugar_network_server/resources/resource.py b/sugar_network_server/resources/resource.py
index 2e2e3d4..204a3bd 100644
--- a/sugar_network_server/resources/resource.py
+++ b/sugar_network_server/resources/resource.py
@@ -33,7 +33,7 @@ class Resource(rd.Document):
def author(self, value):
return value
- @ad.active_property(prefix='OT', full_text=True, default=[], typecast=[])
+ @ad.active_property(prefix='OT', default=[], typecast=[])
def tags(self, value):
return value