Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/sugar_network
diff options
context:
space:
mode:
authorAleksey Lim <alsroot@sugarlabs.org>2014-02-01 19:01:16 (GMT)
committer Aleksey Lim <alsroot@sugarlabs.org>2014-02-01 19:03:18 (GMT)
commitde24419942178dbf17acd9311d0c0edf8d49be17 (patch)
treef3658ce9ac43a45cde2259056fb467b8d398e7d7 /sugar_network
parent2ca3e5f20ec1ad1c122a098abb174dc737df7c32 (diff)
Simplify objects model by introducing Post resource
Diffstat (limited to 'sugar_network')
-rw-r--r--sugar_network/model/__init__.py29
-rw-r--r--sugar_network/model/comment.py66
-rw-r--r--sugar_network/model/context.py4
-rw-r--r--sugar_network/model/feedback.py40
-rw-r--r--sugar_network/model/notification.py47
-rw-r--r--sugar_network/model/post.py (renamed from sugar_network/model/artifact.py)57
-rw-r--r--sugar_network/model/review.py52
-rw-r--r--sugar_network/model/solution.py39
-rw-r--r--sugar_network/node/routes.py14
-rw-r--r--sugar_network/node/stats_node.py90
10 files changed, 86 insertions, 352 deletions
diff --git a/sugar_network/model/__init__.py b/sugar_network/model/__init__.py
index 117649b..167eb30 100644
--- a/sugar_network/model/__init__.py
+++ b/sugar_network/model/__init__.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2012-2013 Aleksey Lim
+# Copyright (C) 2012-2014 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
@@ -16,13 +16,19 @@
from sugar_network.model.routes import VolumeRoutes, FrontRoutes
-CONTEXT_TYPES = ['activity', 'group', 'package', 'book']
-NOTIFICATION_TYPES = ['create', 'update', 'delete', 'vote']
-FEEDBACK_TYPES = ['question', 'idea', 'problem']
-ARTIFACT_TYPES = ['instance', 'preview']
-
-NOTIFICATION_OBJECT_TYPES = [
- '', 'content', 'feedback', 'solution', 'artifact', 'version', 'report',
+CONTEXT_TYPES = [
+ 'activity', 'group', 'package', 'book',
+ ]
+POST_TYPES = [
+ 'review', # Review the Context
+ 'object', # Object generated by Context application
+ 'question', # Q&A request
+ 'answer', # Q&A response
+ 'issue', # Propblem with the Context
+ 'announce', # General announcement
+ 'update', # Auto-generated Post for updates within the Context
+ 'feedback', # Review parent Post
+ 'comment', # Dependent Post
]
STABILITIES = [
@@ -32,14 +38,9 @@ STABILITIES = [
RATINGS = [0, 1, 2, 3, 4, 5]
RESOURCES = (
- 'sugar_network.model.artifact',
- 'sugar_network.model.comment',
'sugar_network.model.context',
+ 'sugar_network.model.post',
'sugar_network.model.release',
- 'sugar_network.model.notification',
- 'sugar_network.model.feedback',
'sugar_network.model.report',
- 'sugar_network.model.review',
- 'sugar_network.model.solution',
'sugar_network.model.user',
)
diff --git a/sugar_network/model/comment.py b/sugar_network/model/comment.py
deleted file mode 100644
index 88917ed..0000000
--- a/sugar_network/model/comment.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright (C) 2012-2013 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 sugar_network import db
-from sugar_network.toolkit.router import ACL
-
-
-class Comment(db.Resource):
-
- @db.indexed_property(prefix='C',
- acl=ACL.READ)
- def context(self, value):
- return value
-
- @db.indexed_property(prefix='R', default='',
- acl=ACL.CREATE | ACL.READ)
- def review(self, value):
- return value
-
- @review.setter
- def review(self, value):
- if value:
- review = self.volume['review'].get(value)
- self['context'] = review['context']
- return value
-
- @db.indexed_property(prefix='F', default='',
- acl=ACL.CREATE | ACL.READ)
- def feedback(self, value):
- return value
-
- @feedback.setter
- def feedback(self, value):
- if value:
- feedback = self.volume['feedback'].get(value)
- self['context'] = feedback['context']
- return value
-
- @db.indexed_property(prefix='S', default='',
- acl=ACL.CREATE | ACL.READ)
- def solution(self, value):
- return value
-
- @solution.setter
- def solution(self, value):
- if value:
- solution = self.volume['solution'].get(value)
- self['context'] = solution['context']
- return value
-
- @db.indexed_property(prefix='M', full_text=True, localized=True,
- acl=ACL.CREATE | ACL.READ)
- def message(self, value):
- return value
diff --git a/sugar_network/model/context.py b/sugar_network/model/context.py
index 461960b..872d74d 100644
--- a/sugar_network/model/context.py
+++ b/sugar_network/model/context.py
@@ -111,11 +111,11 @@ class Context(db.Resource):
'mime_type': 'image/png',
})
- @db.indexed_property(slot=3, default=0, acl=ACL.READ | ACL.CALC)
+ @db.indexed_property(slot=2, default=0, acl=ACL.READ | ACL.CALC)
def downloads(self, value):
return value
- @db.indexed_property(slot=4, typecast=model.RATINGS, default=0,
+ @db.indexed_property(slot=3, typecast=model.RATINGS, default=0,
acl=ACL.READ | ACL.CALC)
def rating(self, value):
return value
diff --git a/sugar_network/model/feedback.py b/sugar_network/model/feedback.py
deleted file mode 100644
index 45bacfe..0000000
--- a/sugar_network/model/feedback.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright (C) 2012-2013 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 sugar_network import db, model
-from sugar_network.toolkit.router import ACL
-
-
-class Feedback(db.Resource):
-
- @db.indexed_property(prefix='C', acl=ACL.CREATE | ACL.READ)
- def context(self, value):
- return value
-
- @db.indexed_property(prefix='T', typecast=[model.FEEDBACK_TYPES])
- def type(self, value):
- return value
-
- @db.indexed_property(prefix='S', full_text=True, localized=True)
- def title(self, value):
- return value
-
- @db.indexed_property(prefix='N', full_text=True, localized=True)
- def content(self, value):
- return value
-
- @db.indexed_property(prefix='A', default='')
- def solution(self, value):
- return value
diff --git a/sugar_network/model/notification.py b/sugar_network/model/notification.py
deleted file mode 100644
index e567b65..0000000
--- a/sugar_network/model/notification.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright (C) 2012-2013 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 sugar_network import db, model
-from sugar_network.toolkit.router import ACL
-
-
-class Notification(db.Resource):
-
- @db.indexed_property(prefix='T',
- acl=ACL.CREATE | ACL.READ,
- typecast=model.NOTIFICATION_TYPES)
- def type(self, value):
- return value
-
- @db.indexed_property(prefix='K',
- acl=ACL.CREATE | ACL.READ,
- default='', typecast=model.NOTIFICATION_OBJECT_TYPES)
- def resource(self, value):
- return value
-
- @db.indexed_property(prefix='O',
- acl=ACL.CREATE | ACL.READ, default='')
- def object(self, value):
- return value
-
- @db.indexed_property(prefix='D',
- acl=ACL.CREATE | ACL.READ, default='')
- def to(self, value):
- return value
-
- @db.indexed_property(prefix='M', full_text=True, localized=True,
- acl=ACL.CREATE | ACL.READ)
- def message(self, value):
- return value
diff --git a/sugar_network/model/artifact.py b/sugar_network/model/post.py
index 0a0239d..d7a742c 100644
--- a/sugar_network/model/artifact.py
+++ b/sugar_network/model/post.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2012-2013 Aleksey Lim
+# Copyright (C) 2012-2014 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
@@ -17,44 +17,48 @@ from sugar_network import db, model, static
from sugar_network.toolkit.router import Blob, ACL
-class Artifact(db.Resource):
+class Post(db.Resource):
@db.indexed_property(prefix='C',
acl=ACL.CREATE | ACL.READ)
def context(self, value):
return value
- @db.indexed_property(prefix='T', typecast=[model.ARTIFACT_TYPES])
+ @db.indexed_property(prefix='A', default='',
+ acl=ACL.CREATE | ACL.READ)
+ def topic(self, value):
+ return value
+
+ @topic.setter
+ def topic(self, value):
+ if value and not self['context']:
+ post = self.volume['post'].get(value)
+ self['context'] = post['context']
+ return value
+
+ @db.indexed_property(prefix='T', typecast=model.POST_TYPES)
def type(self, value):
return value
- @db.indexed_property(slot=1, prefix='S', full_text=True, localized=True,
+ @db.indexed_property(slot=1, prefix='N', full_text=True, localized=True,
acl=ACL.CREATE | ACL.READ)
def title(self, value):
return value
@db.indexed_property(prefix='D', full_text=True, localized=True,
acl=ACL.CREATE | ACL.READ)
- def description(self, value):
+ def message(self, value):
return value
- @db.indexed_property(slot=2, default=0, acl=ACL.READ | ACL.CALC)
- def downloads(self, value):
+ @db.indexed_property(prefix='R', default='')
+ def solution(self, value):
return value
- @db.indexed_property(slot=3, typecast=model.RATINGS, default=0,
- acl=ACL.READ | ACL.CALC)
- def rating(self, value):
+ @db.indexed_property(prefix='V', typecast=model.RATINGS, default=0,
+ acl=ACL.CREATE | ACL.READ)
+ def vote(self, value):
return value
- @db.stored_property(typecast=[], default=[0, 0],
- acl=ACL.READ | ACL.CALC)
- def reviews(self, value):
- if value is None:
- return 0
- else:
- return value[0]
-
@db.blob_property(mime_type='image/png')
def preview(self, value):
if value:
@@ -70,3 +74,20 @@ class Artifact(db.Resource):
if value:
value['name'] = self['title']
return value
+
+ @db.indexed_property(slot=2, default=0, acl=ACL.READ | ACL.CALC)
+ def downloads(self, value):
+ return value
+
+ @db.indexed_property(slot=3, typecast=model.RATINGS, default=0,
+ acl=ACL.READ | ACL.CALC)
+ def rating(self, value):
+ return value
+
+ @db.stored_property(typecast=[], default=[0, 0],
+ acl=ACL.READ | ACL.CALC)
+ def reviews(self, value):
+ if value is None:
+ return 0
+ else:
+ return value[0]
diff --git a/sugar_network/model/review.py b/sugar_network/model/review.py
deleted file mode 100644
index 621ac87..0000000
--- a/sugar_network/model/review.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright (C) 2012-2013 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 sugar_network import db, model
-from sugar_network.toolkit.router import ACL
-
-
-class Review(db.Resource):
-
- @db.indexed_property(prefix='C',
- acl=ACL.CREATE | ACL.READ)
- def context(self, value):
- return value
-
- @db.indexed_property(prefix='A', default='',
- acl=ACL.CREATE | ACL.READ)
- def artifact(self, value):
- return value
-
- @artifact.setter
- def artifact(self, value):
- if value and not self['context']:
- artifact = self.volume['artifact'].get(value)
- self['context'] = artifact['context']
- return value
-
- @db.indexed_property(prefix='S', full_text=True, localized=True,
- acl=ACL.CREATE | ACL.READ)
- def title(self, value):
- return value
-
- @db.indexed_property(prefix='N', full_text=True, localized=True,
- acl=ACL.CREATE | ACL.READ)
- def content(self, value):
- return value
-
- @db.indexed_property(slot=1, typecast=model.RATINGS,
- acl=ACL.CREATE | ACL.READ)
- def rating(self, value):
- return value
diff --git a/sugar_network/model/solution.py b/sugar_network/model/solution.py
deleted file mode 100644
index 549e0f2..0000000
--- a/sugar_network/model/solution.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (C) 2012-2013 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 sugar_network import db
-from sugar_network.toolkit.router import ACL
-
-
-class Solution(db.Resource):
-
- @db.indexed_property(prefix='C', acl=ACL.READ)
- def context(self, value):
- return value
-
- @db.indexed_property(prefix='P', acl=ACL.CREATE | ACL.READ)
- def feedback(self, value):
- return value
-
- @feedback.setter
- def feedback(self, value):
- if value:
- feedback = self.volume['feedback'].get(value)
- self['context'] = feedback['context']
- return value
-
- @db.indexed_property(prefix='N', full_text=True, localized=True)
- def content(self, value):
- return value
diff --git a/sugar_network/node/routes.py b/sugar_network/node/routes.py
index 5f066a9..4bc97e4 100644
--- a/sugar_network/node/routes.py
+++ b/sugar_network/node/routes.py
@@ -438,12 +438,8 @@ def generate_node_stats(volume, path):
('user', []),
('context', []),
('release', ['context']),
- ('artifact', ['context', 'type']),
- ('feedback', ['context']),
- ('solution', ['context', 'feedback']),
- ('review', ['context', 'artifact', 'rating']),
('report', ['context', 'release']),
- ('comment', ['context', 'review', 'feedback', 'solution']),
+ ('post', ['context', 'topic', 'type', 'vote']),
]:
objs, __ = volume[resource].find(
query='ctime:%s..%s' % (left, right))
@@ -455,12 +451,8 @@ def generate_node_stats(volume, path):
('user', ['layer']),
('context', ['layer']),
('release', ['layer']),
- ('artifact', ['layer']),
- ('feedback', ['layer', 'solution']),
- ('solution', ['layer']),
- ('review', ['layer']),
('report', ['layer']),
- ('comment', ['layer']),
+ ('post', ['layer']),
]:
objs, __ = volume[resource].find(
query='mtime:%s..%s' % (left, right))
@@ -473,7 +465,7 @@ def generate_node_stats(volume, path):
content=obj.properties(props))
new_stats.log(request)
downloaded = {}
- for resource in ('context', 'artifact'):
+ for resource in ('context', 'post'):
stats = old_stats.report(
{resource: ['downloaded']}, left - step, right, 1)
if not stats.get(resource):
diff --git a/sugar_network/node/stats_node.py b/sugar_network/node/stats_node.py
index cc77424..ed2c0bd 100644
--- a/sugar_network/node/stats_node.py
+++ b/sugar_network/node/stats_node.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2012-2013 Aleksey Lim
+# Copyright (C) 2012-2014 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
@@ -170,7 +170,7 @@ class Sniffer(object):
class _Stats(dict):
RESOURCE = None
- OWNERS = []
+ PARENTS = []
def __init__(self, stats, volume):
self.objects = {}
@@ -205,14 +205,14 @@ class _ResourceStats(_Stats):
directory = self._volume[self.RESOURCE]
def parse_context(props):
- for owner in self.OWNERS:
- guid = props.get(owner)
+ for prop, resource in self.PARENTS:
+ guid = props.get(prop)
if not guid:
continue
- if owner == 'context':
+ if resource == 'context':
return guid
else:
- return self._volume[owner].get(guid)['context']
+ return self._volume[resource].get(guid)['context']
if request.method == 'GET':
if not request.guid:
@@ -253,7 +253,7 @@ class _ContextStats(_ResourceStats):
class _ReleaseStats(_Stats):
RESOURCE = 'release'
- OWNERS = ['context']
+ PARENTS = [('context', 'context')]
def log(self, request):
if request.method == 'GET':
@@ -268,81 +268,45 @@ class _ReleaseStats(_Stats):
class _ReportStats(_Stats):
RESOURCE = 'report'
- OWNERS = ['context', 'release']
+ PARENTS = [('context', 'context'), ('release', 'release')]
def log(self, request):
if request.method == 'POST':
self._stats['context']['failed'] += 1
-class _ReviewStats(_ResourceStats):
+class _PostStats(_ResourceStats):
- RESOURCE = 'review'
- OWNERS = ['artifact', 'context']
-
- def log(self, request):
- _ResourceStats.log(self, request)
-
- if request.method == 'POST':
- if request.content.get('artifact'):
- stats = self._stats['artifact']
- guid = request.content['artifact']
- else:
- stats = self._stats['context']
- guid = self.parse_context(request)
- stats.inc(guid, 'reviews')
- stats.inc(guid, 'rating', request.content.get('rating') or 0)
-
-
-class _FeedbackStats(_ResourceStats):
-
- RESOURCE = 'feedback'
- OWNERS = ['context']
-
-
-class _SolutionStats(_ResourceStats):
-
- RESOURCE = 'solution'
- OWNERS = ['feedback']
-
-
-class _ArtifactStats(_ResourceStats):
-
- RESOURCE = 'artifact'
- OWNERS = ['context']
+ RESOURCE = 'post'
+ PARENTS = [('context', 'context'), ('topic', 'post')]
def __init__(self, stats, volume):
_ResourceStats.__init__(self, stats, volume)
self['downloaded'] = 0
def log(self, request):
- if request.method == 'POST':
- if request.content.get('type') != 'preview':
- self['total'] += 1
- elif request.method == 'DELETE':
- existing = self._volume[self.RESOURCE].get(request.guid)
- if existing['type'] != 'preview':
- self['total'] -= 1
- elif request.method == 'GET' and request.prop == 'data':
- existing = self._volume[self.RESOURCE].get(request.guid)
- if existing['type'] != 'preview':
- self.inc(request.guid, 'downloads')
- self['downloaded'] += 1
-
+ _ResourceStats.log(self, request)
-class _CommentStats(_ResourceStats):
+ if request.method == 'POST':
+ stats = None
+ if request.content['type'] == 'review':
+ stats = self._stats['context']
+ guid = request.content['context']
+ elif request.content['type'] == 'feedback':
+ stats = self._stats['post']
+ guid = request.content['topic']
+ if stats:
+ stats.inc(guid, 'reviews')
+ stats.inc(guid, 'rating', request.content.get('vote') or 0)
- RESOURCE = 'comment'
- OWNERS = ['solution', 'feedback', 'review']
+ elif request.method == 'GET' and request.prop == 'data':
+ self.inc(request.guid, 'downloads')
+ self['downloaded'] += 1
_STATS = {_UserStats.RESOURCE: _UserStats,
_ContextStats.RESOURCE: _ContextStats,
_ReleaseStats.RESOURCE: _ReleaseStats,
_ReportStats.RESOURCE: _ReportStats,
- _ReviewStats.RESOURCE: _ReviewStats,
- _FeedbackStats.RESOURCE: _FeedbackStats,
- _SolutionStats.RESOURCE: _SolutionStats,
- _ArtifactStats.RESOURCE: _ArtifactStats,
- _CommentStats.RESOURCE: _CommentStats,
+ _PostStats.RESOURCE: _PostStats,
}