Просмотр исходного кода

Fixed DenormalizedText and renamed it to SetType.

sh4nks 11 лет назад
Родитель
Сommit
2b2e7cb768
2 измененных файлов с 39 добавлено и 15 удалено
  1. 3 3
      flaskbb/forum/models.py
  2. 36 12
      flaskbb/utils/types.py

+ 3 - 3
flaskbb/forum/models.py

@@ -11,7 +11,7 @@
 from datetime import datetime
 
 from flaskbb.extensions import db
-from flaskbb.utils.types import DenormalizedText
+from flaskbb.utils.types import SetType, MutableSet
 from flaskbb.utils.query import TopicQuery
 from helpers import get_forum_ids
 
@@ -325,10 +325,10 @@ class Forum(db.Model):
     post_count = db.Column(db.Integer, default=0)
     topic_count = db.Column(db.Integer, default=0)
 
-    moderators = db.Column(DenormalizedText)
+    moderators = db.Column(MutableSet.as_mutable(SetType))
 
     # A set with all parent forums
-    parents = db.Column(DenormalizedText)
+    parents = db.Column(MutableSet.as_mutable(SetType))
 
     # One-to-one
     last_post_id = db.Column(db.Integer, db.ForeignKey("posts.id"))

+ 36 - 12
flaskbb/utils/types.py

@@ -11,20 +11,16 @@
 from sqlalchemy import types
 from sqlalchemy.ext.mutable import Mutable
 import json
-import collections
 
 
-class DenormalizedText(Mutable, types.TypeDecorator):
+class SetType(types.TypeDecorator):
     """
-    Stores denormalized primary keys that can be
-    accessed as a set.
+    Represents an immutable set.
 
     :param coerce: coercion function that ensures correct
                    type is returned
 
     :param separator: separator character
-
-    Source: https://github.com/imwilsonxu/fbone/blob/master/fbone/user/models.py#L13-L45
     """
 
     impl = types.Text
@@ -34,7 +30,7 @@ class DenormalizedText(Mutable, types.TypeDecorator):
         self.coerce = coerce
         self.separator = separator
 
-        super(DenormalizedText, self).__init__(**kwargs)
+        super(SetType, self).__init__(**kwargs)
 
     def process_bind_param(self, value, dialect):
         if value is not None:
@@ -43,12 +39,40 @@ class DenormalizedText(Mutable, types.TypeDecorator):
         return value
 
     def process_result_value(self, value, dialect):
-        if not value:
-            return set()
-        return set(self.coerce(item) for item in value.split(self.separator))
+        if value is not None:
+            return set(self.coerce(item) for item in value.split(" "))
+        return set()
+
 
-    def copy_value(self, value):
-        return set(value)
+class MutableSet(Mutable, set):
+    @classmethod
+    def coerce(cls, key, value):
+        """
+        Convert plain sets to MutableSet.
+        """
+
+        if not isinstance(value, MutableSet):
+            if isinstance(value, set):
+                return MutableSet(value)
+
+            # this call will raise ValueError
+            return Mutable.coerce(key, value)
+        else:
+            return value
+
+    def add(self, value):
+        """
+        Detect set add events and emit change events.
+        """
+        set.add(self, value)
+        self.changed()
+
+    def remove(self, value):
+        """
+        Detect set remove events and emit change events.
+        """
+        set.remove(self, value)
+        self.changed()
 
 
 # http://docs.sqlalchemy.org/en/rel_0_9/orm/extensions/mutable.html