diff options
author | Aleksey Lim <alsroot@sugarlabs.org> | 2014-02-01 19:01:16 (GMT) |
---|---|---|
committer | Aleksey Lim <alsroot@sugarlabs.org> | 2014-02-01 19:03:18 (GMT) |
commit | de24419942178dbf17acd9311d0c0edf8d49be17 (patch) | |
tree | f3658ce9ac43a45cde2259056fb467b8d398e7d7 /sugar_network | |
parent | 2ca3e5f20ec1ad1c122a098abb174dc737df7c32 (diff) |
Simplify objects model by introducing Post resource
Diffstat (limited to 'sugar_network')
-rw-r--r-- | sugar_network/model/__init__.py | 29 | ||||
-rw-r--r-- | sugar_network/model/comment.py | 66 | ||||
-rw-r--r-- | sugar_network/model/context.py | 4 | ||||
-rw-r--r-- | sugar_network/model/feedback.py | 40 | ||||
-rw-r--r-- | sugar_network/model/notification.py | 47 | ||||
-rw-r--r-- | sugar_network/model/post.py (renamed from sugar_network/model/artifact.py) | 57 | ||||
-rw-r--r-- | sugar_network/model/review.py | 52 | ||||
-rw-r--r-- | sugar_network/model/solution.py | 39 | ||||
-rw-r--r-- | sugar_network/node/routes.py | 14 | ||||
-rw-r--r-- | sugar_network/node/stats_node.py | 90 |
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, } |