Ticket #715: test_orphan_functor

File test_orphan_functor, 5.0 KB (added by SimonKing, 8 years ago)

Experimental patch using weak references on domain and codomain of functors

Line 
1# HG changeset patch
2# User Simon King <simon.king@uni-jena.de>
3# Date 1325605696 -3600
4# Node ID e556733b8d4c7c4198dfaa3759b3b25332400fae
5# Parent  634489af2f27ac285708c991309b0dd5d38f9854
6[mq]: test_orphan_functor
7
8diff --git a/sage/categories/functor.pxd b/sage/categories/functor.pxd
9--- a/sage/categories/functor.pxd
10+++ b/sage/categories/functor.pxd
11@@ -1,6 +1,7 @@
12 from sage.structure.sage_object cimport SageObject
13 
14 cdef class Functor(SageObject):
15-    cdef __weakref__
16     cdef object __domain
17     cdef object __codomain
18+    cpdef domain(self)
19+    cpdef codomain(self)
20diff --git a/sage/categories/functor.pyx b/sage/categories/functor.pyx
21--- a/sage/categories/functor.pyx
22+++ b/sage/categories/functor.pyx
23@@ -34,6 +34,7 @@
24 #*****************************************************************************
25 
26 import category
27+from weakref import ref
28 
29 def _Functor_unpickle(Cl, D, domain, codomain):
30     """
31@@ -178,8 +179,8 @@
32             raise TypeError, "domain (=%s) must be a category"%domain
33         if not category.is_Category(codomain):
34             raise TypeError, "codomain (=%s) must be a category"%codomain
35-        self.__domain = domain
36-        self.__codomain = codomain
37+        self.__domain = ref(domain)
38+        self.__codomain = ref(codomain)
39 
40     def __reduce__(self):
41         """
42@@ -199,7 +200,8 @@
43             Category of rings
44 
45         """
46-        return _Functor_unpickle, (self.__class__, self.__dict__.items(), self.__domain, self.__codomain)
47+        return _Functor_unpickle, (self.__class__, self.__dict__.items(),
48+                                   self.domain(), self.codomain())
49 
50     def _apply_functor(self, x):
51         """
52@@ -219,7 +221,7 @@
53             Rational Field
54 
55         """
56-        return self.__codomain(x)
57+        return self.codomain()(x)
58 
59     def _apply_functor_to_morphism(self, f):
60         """
61@@ -281,8 +283,9 @@
62             TypeError: x (=Integer Ring) is not in Category of fields
63 
64         """
65-        if not (x in  self.__domain):
66-            raise TypeError, "x (=%s) is not in %s"%(x, self.__domain)
67+        D = self.domain()
68+        if x not in D:
69+            raise TypeError, "x (=%s) is not in %s"%(x, D)
70         return x
71 
72     def __repr__(self):
73@@ -294,7 +297,7 @@
74             Functor from Category of rings to Category of fields
75 
76         """
77-        return "Functor from %s to %s"%(self.__domain, self.__codomain)
78+        return "Functor from %s to %s"%(self.domain(), self.codomain())
79 
80     def __call__(self, x):
81         """
82@@ -360,11 +363,12 @@
83         if is_Morphism(x):
84             return self._apply_functor_to_morphism(x)
85         y = self._apply_functor(self._coerce_into_domain(x))
86-        if not ((y in self.__codomain) or (y in self.__codomain.hom_category())):
87-            raise TypeError, "%s is ill-defined, since it sends x (=%s) to something that is not in %s."%(repr(self), x, self.__codomain)
88+        C = self.codomain()
89+        if not ((y in C) or (y in C.hom_category())):
90+            raise TypeError, "%s is ill-defined, since it sends x (=%s) to something that is not in %s."%(repr(self), x, C)
91         return y
92 
93-    def domain(self):
94+    cpdef domain(self):
95         """
96         The domain of self
97 
98@@ -375,9 +379,12 @@
99             Category of finite fields
100 
101         """
102-        return self.__domain
103+        D = self.__domain()
104+        if D is None:
105+            raise RuntimeError, "BUG in coercion model: There did not remain a strong reference to the domain of this functor"
106+        return D
107 
108-    def codomain(self):
109+    cpdef codomain(self):
110         """
111         The codomain of self
112 
113@@ -388,7 +395,10 @@
114             Category of fields
115 
116         """
117-        return self.__codomain
118+        D = self.__codomain()
119+        if D is None:
120+            raise RuntimeError, "BUG in coercion model: There did not remain a strong reference to the codomain of this functor"
121+        return D
122     
123 
124 def is_Functor(x):
125diff --git a/sage/structure/coerce.pyx b/sage/structure/coerce.pyx
126--- a/sage/structure/coerce.pyx
127+++ b/sage/structure/coerce.pyx
128@@ -91,9 +91,6 @@
129 import sys, traceback
130 
131 from coerce_actions import LeftModuleAction, RightModuleAction, IntegerMulAction
132-from weakref import ref
133-from sage.misc.constant_function import ConstantFunction
134-NoneFunction = ConstantFunction(False)
135 
136 cpdef py_scalar_parent(py_type):
137     """
138@@ -1208,19 +1205,12 @@
139 
140         """
141         try:
142-            action = self._action_maps.get(R, S, op)()
143-            if action is False:
144-                return None
145-            if action is not None:
146-                return action
147+            return self._action_maps.get(R, S, op)
148         except KeyError:
149             pass
150         action = self.discover_action(R, S, op)
151         action = self.verify_action(action, R, S, op)
152-        if action is None:
153-            self._action_maps.set(R, S, op, NoneFunction)
154-        else:
155-            self._action_maps.set(R, S, op, ref(action))
156+        self._action_maps.set(R, S, op, action)
157         return action
158             
159     cpdef verify_action(self, action, R, S, op, bint fix=True):