Re: Re: Trellis + Python 2.6

"Sergey Schetinin" <[email protected]> Thu, 20 Nov 2008 09:44:29 +0200
Newsgroups gmane.comp.python.peak
Message-ID <[email protected]>
Whoops, just that patch is a bit out of date (uses copy instead of copy.copy)

_______________________________________________
PEAK mailing list
[email protected]
http://www.eby-sarna.com/mailman/listinfo/peak
py26.patch (application/octet-stream, 10 KB)
Index: stm.py
===================================================================
--- stm.py	(revision 2595)
+++ stm.py	(working copy)
@@ -1,6 +1,6 @@
 """Software Transactional Memory and Observers"""

-import weakref, sys, heapq, UserList, UserDict, sets
+import weakref, sys, heapq, UserList, UserDict
 from peak.util.extremes import Max
 from peak.util import decorators
 try:
Index: trellis.py
===================================================================
--- trellis.py	(revision 2595)
+++ trellis.py	(working copy)
@@ -1,7 +1,7 @@
 from thread import get_ident
 from weakref import ref
 from peak.util import addons, decorators
-import sys, UserDict, UserList, sets, stm, types, new, weakref, copy
+import sys, UserDict, UserList, stm, types, new, weakref, copy
 from peak.util.extremes import Max
 from peak.util.symbols import Symbol, NOT_GIVEN

@@ -42,12 +42,13 @@
 try:
     set = set
 except NameError:
+    import sets
     set = sets.Set
     frozenset = sets.ImmutableSet
     set_like = sets.BaseSet
     dictlike = dict, sets.BaseSet
 else:
-    set_like = set, frozenset, sets.BaseSet
+    set_like = set, frozenset
     dictlike = (dict,) + set_like


@@ -141,7 +142,7 @@
         if value!=self._value:
             if self._set_by not in (ctrl.current_listener, self):
                 # already set by someone else
-                raise InputConflict(self._value, value) #self._set_by) #, value, ctrl.current_listener) # XXX
+                raise InputConflict(self._value, value, self._set_by, ctrl.current_listener) # XXX
             changed(self)

         change_attr(self, '_value', value)
@@ -292,8 +294,8 @@
     a rule, reads performed in the function will not become dependencies of the
     caller.
     """
-    def wrap(__func, __module):
-        """
+    def wrap(__func, __module): pass
+    wrap.__doc__ = """
         if not __module.ctrl.active:
             return __module.atomically(__func, $args)
         elif __module.ctrl.current_listener is None:
@@ -506,7 +508,7 @@
                 return ReadOnlyCell(rule, None, discrete)
             elif rule is None:
                 return Value(v, discrete)
-        return ReadOnlyCell.__new__(cls, rule, value, discrete)
+        return ReadOnlyCell.__new__(cls)#, rule, value, discrete)

     def _check_const(self):
         pass    # we can never become Constant
@@ -529,8 +531,9 @@
         super(Cell, self).set_value(value)
         if self._needs_init:
             schedule(self)
+        else:
+            cancel(self)

-
     value = property(get_value, set_value)

     def dirty(self):
@@ -552,7 +555,7 @@
         else:
             # It should be impossible to get here unless you run the cell
             # manually.  Don't do that.  :)
-            raise AssertionError("This should never happen!")
+            raise AssertionError("This should never happen!", self)


 class Effector(SensorBase, Cell):

@@ -748,6 +751,8 @@
         except KeyError:
             name = self.__name__
             cell = cells.setdefault(name, self.make_cell(typ, ob, name))
+            if ctrl.active:
+                on_undo(cells.pop, name)
         return cell.value

     def __repr__(self):
@@ -1240,6 +1245,9 @@
     strategy is used in each recalcultion that changes the list.  If what you
     really want is e.g. a sorted read-only view on a set, don't use this.
     """
+    if hasattr(UserList.UserList, '__metaclass__'):
+        class __metaclass__(Component.__metaclass__, UserList.UserList.__metaclass__):
+            pass

     updated = todo(lambda self: self.data[:])
     future  = updated.future
@@ -1348,10 +1356,7 @@



-
-
-
-class Set(sets.Set, Component):
+class _SetBase(Component):
     """Mutable set that recalculates observers when it's changed

     The ``added`` and ``removed`` attributes can be watched for changes, but
@@ -1364,28 +1369,6 @@
     to_add = _added.future
     to_remove = _removed.future

-    def __init__(self, iterable=None, **kw):
-        """Construct a set from an optional iterable."""
-        Component.__init__(self, **kw)
-        if iterable is not None:
-            # we can update self._data in place, since no-one has seen it yet
-            sets.Set._update(self, iterable)
-
-    maintain(make=dict)
-    def _data(self):
-        """The dictionary containing the set data."""
-        data = self._data
-        pop = data.pop
-        if self.removed:
-            mark_dirty()
-            for item in self.removed: pop(item, None)
-            on_undo(data.update, dict.fromkeys(self.removed, True))
-        if self.added:
-            mark_dirty()
-            data.update(dict.fromkeys(self.added, True))
-            for item in self.added: on_undo(pop, item, None)
-        return data
-
     def __setstate__(self, data):
         self.__init__(data[0])

@@ -1490,28 +1473,157 @@
             else:
                 to_add.add(elt)         # Don't got it; add it

-def to_dict_or_set(ob):
-    """Return the most basic set or dict-like object for ob
-    If ob is a sets.BaseSet, return its ._data; if it's something we can tell
-    is dictlike, return it as-is.  Otherwise, make a dict using .fromkeys()
-    """
-    if isinstance(ob, sets.BaseSet):
-        return ob._data
-    elif not isinstance(ob, dictlike):
-        return dict.fromkeys(ob)
-    return ob






+if sys.version >= '2.6':
+    from itertools import ifilter, ifilterfalse
+    MutableSet = getattr(__import__('collections', level=0), 'MutableSet') # absolute import

+    class Set(_SetBase, MutableSet):
+        class __metaclass__(_SetBase.__metaclass__, MutableSet.__metaclass__):
+            pass

+        def __init__(self, iterable=None, **kw):
+            """Construct a set from an optional iterable."""
+            Component.__init__(self, **kw)
+            if iterable is not None:
+                # we can update self._data in place, since no-one has seen it yet
+                self._data.update(iterable)

+        __hash__ = None

+        maintain(make=set)
+        def _data(self):
+            """The dictionary containing the set data."""
+            data = self._data
+            if self.removed:
+                mark_dirty()
+                data -= self.removed
+                on_undo(data.update, copy.copy(self.removed))
+            if self.added:
+                mark_dirty()
+                data.update(self.added)
+                on_undo(data.difference_update, copy.copy(self.added))
+            return data

+        def __getstate__(self):
+            return self._data,

+        def discard(self, item):
+            try:
+                self.remove(item)
+            except KeyError:
+                pass

+        def __len__(self):
+            return len(self._data)

+        def __iter__(self):
+            return iter(self._data)

+        def __contains__(self, item):
+            return item in self._data
+
+        def update(self, iterable):
+            self._update(iterable)
+
+        def union(self, other):
+            result = self.__class__(self._data)
+            result._data.update(other)
+            return result
+
+        def intersection(self, other):
+            other = to_dict_or_set(other)
+            if len(self) <= len(other):
+                little, big = self, other
+            else:
+                little, big = other, self
+            common = ifilter(big.__contains__, little)
+            return self.__class__(common)
+
+        def difference(self, other):
+            other = to_dict_or_set(other)
+            return self.__class__(ifilterfalse(other.__contains__, self))
+
+        def symmetric_difference(self, other):
+            other = to_dict_or_set(other)
+            result = self.__class__()
+            result._data.update(ifilterfalse(other.__contains__, self._data))
+            result._data.update(ifilterfalse(self._data.__contains__, other))
+            return result
+
+        __or__ = union
+        __xor__ = symmetric_difference
+        __and__ = intersection
+        __sub__ = difference
+
+        issubset = MutableSet.__le__
+        issuperset = MutableSet.__ge__
+
+        def __ixor__(self, other):
+            """Update a set with the symmetric difference of itself and another."""
+            self._binary_sanity_check(other)
+            self.symmetric_difference_update(other)
+            return self
+
+        def __isub__(self, other):
+            """Remove all elements of another set from this set."""
+            self._binary_sanity_check(other)
+            self.difference_update(other)
+            return self
+
+
+
+    def to_dict_or_set(ob):
+        if isinstance(ob, Set):
+            return ob._data
+        elif isinstance(ob, dictlike):
+            return ob
+        else:
+            return frozenset(ob)
+
+
+
+
+
+else:
+    import sets
+
+    class Set(_SetBase, sets.Set):
+        def __init__(self, iterable=None, **kw):
+            """Construct a set from an optional iterable."""
+            Component.__init__(self, **kw)
+            if iterable is not None:
+                # we can update self._data in place, since no-one has seen it yet
+                sets.Set._update(self, iterable)
+
+        maintain(make=dict)
+        def _data(self):
+            """The dictionary containing the set data."""
+            data = self._data
+            pop = data.pop
+            if self.removed:
+                mark_dirty()
+                for item in self.removed: pop(item, None)
+                on_undo(data.update, dict.fromkeys(self.removed, True))
+            if self.added:
+                mark_dirty()
+                data.update(dict.fromkeys(self.added, True))
+                for item in self.added: on_undo(pop, item, None)
+            return data
+
+
+    def to_dict_or_set(ob):
+        """Return the most basic set or dict-like object for ob
+        If ob is a sets.BaseSet, return its ._data; if it's something we can tell
+        is dictlike, return it as-is.  Otherwise, make a dict using .fromkeys()
+        """
+        if isinstance(ob, sets.BaseSet):
+            return ob._data
+        elif not isinstance(ob, dictlike):
+            return dict.fromkeys(ob)
+        return ob