# HG changeset patch
# User Robert Bradshaw <robertwb@gmail.com>
# Date 1360058161 28800
# Node ID 4c451c85cec37528a9fb8761eb882ba0da12c983
# Parent b936e7334beb18eafcfc2e5533be7836da061900
Remove strong references to parents used in binary operations in the coercion model.
diff --git a/sage/structure/coerce.pyx b/sage/structure/coerce.pyx
a
|
b
|
|
80 | 80 | |
81 | 81 | import operator |
82 | 82 | |
| 83 | from cpython.weakref cimport PyWeakref_GetObject, PyWeakref_NewRef |
| 84 | |
83 | 85 | from sage_object cimport SageObject |
84 | 86 | from sage.categories.map cimport Map |
85 | 87 | import sage.categories.morphism |
… |
… |
|
92 | 94 | |
93 | 95 | from coerce_actions import LeftModuleAction, RightModuleAction, IntegerMulAction |
94 | 96 | |
| 97 | cdef object coerce_to_left = "coerce_to_left" |
| 98 | cdef object coerce_to_right = "coerce_to_right" |
| 99 | |
95 | 100 | cpdef py_scalar_parent(py_type): |
96 | 101 | """ |
97 | 102 | Returns the Sage equivalent of the given python type, if one exists. |
… |
… |
|
228 | 233 | Now lets see what happens when we do a binary operations with |
229 | 234 | an integer and a rational:: |
230 | 235 | |
231 | | sage: left_morphism, right_morphism = maps[ZZ, QQ] |
232 | | sage: print left_morphism |
233 | | Natural morphism: |
234 | | From: Integer Ring |
235 | | To: Rational Field |
236 | | sage: print right_morphism |
237 | | None |
| 236 | sage: maps[ZZ, QQ] |
| 237 | 'coerce_to_right' |
238 | 238 | |
239 | 239 | We can see that it coerces the left operand from an integer to a |
240 | 240 | rational, and doesn't do anything to the right. |
… |
… |
|
1063 | 1063 | True |
1064 | 1064 | """ |
1065 | 1065 | try: |
1066 | | return self._coercion_maps.get(R, S, None) |
| 1066 | result = self._coercion_maps.get(R, S, None) |
| 1067 | if result is None: |
| 1068 | return None |
| 1069 | elif result is coerce_to_left: |
| 1070 | return None, R.coerce_map_from(S) |
| 1071 | elif result is coerce_to_right: |
| 1072 | return S.coerce_map_from(R), None |
| 1073 | else: |
| 1074 | codomain = <object>PyWeakref_GetObject(result) |
| 1075 | if codomain is not None: |
| 1076 | return codomain.coerce_map_from(R), codomain.coerce_map_from(S) |
1067 | 1077 | except KeyError: |
1068 | | homs = self.discover_coercion(R, S) |
1069 | | if 0: |
1070 | | # This breaks too many things that are going to change |
1071 | | # in the new coercion model anyways. |
1072 | | # COERCE TODO: Enable it then. |
1073 | | homs = self.verify_coercion_maps(R, S, homs) |
| 1078 | pass |
| 1079 | homs = self.discover_coercion(R, S) |
| 1080 | if 0: |
| 1081 | # This breaks too many things that are going to change |
| 1082 | # in the new coercion model anyways. |
| 1083 | # COERCE TODO: Enable it then. |
| 1084 | homs = self.verify_coercion_maps(R, S, homs) |
| 1085 | else: |
| 1086 | if homs is not None: |
| 1087 | x_map, y_map = homs |
| 1088 | if x_map is not None and not isinstance(x_map, Map): |
| 1089 | raise RuntimeError, "BUG in coercion model: coerce_map_from must return a Map" |
| 1090 | if y_map is not None and not isinstance(y_map, Map): |
| 1091 | raise RuntimeError, "BUG in coercion model: coerce_map_from must return a Map" |
| 1092 | if homs is None: |
| 1093 | result = None |
| 1094 | swap = None |
| 1095 | else: |
| 1096 | R_map, S_map = homs |
| 1097 | if R_map is None: |
| 1098 | result = coerce_to_left |
| 1099 | if PY_TYPE_CHECK(S, Parent) and (<Parent>S).has_coerce_map_from(R): |
| 1100 | swap = coerce_to_left |
| 1101 | else: |
| 1102 | swap = coerce_to_right |
| 1103 | elif S_map is None: |
| 1104 | result = coerce_to_right |
| 1105 | swap = coerce_to_left |
1074 | 1106 | else: |
1075 | | if homs is not None: |
1076 | | x_map, y_map = homs |
1077 | | if x_map is not None and not isinstance(x_map, Map): |
1078 | | raise RuntimeError, "BUG in coercion model: coerce_map_from must return a Map" |
1079 | | if y_map is not None and not isinstance(y_map, Map): |
1080 | | raise RuntimeError, "BUG in coercion model: coerce_map_from must return a Map" |
1081 | | if homs is None: |
1082 | | swap = None |
1083 | | else: |
1084 | | R_map, S_map = homs |
1085 | | if R_map is None and PY_TYPE_CHECK(S, Parent) and (<Parent>S).has_coerce_map_from(R): |
1086 | | swap = None, (<Parent>S).coerce_map_from(R) |
1087 | | else: |
1088 | | swap = S_map, R_map |
1089 | | self._coercion_maps.set(R, S, None, homs) |
1090 | | self._coercion_maps.set(S, R, None, swap) |
| 1107 | result = swap = PyWeakref_NewRef(R_map.codomain(), None) |
| 1108 | self._coercion_maps.set(R, S, None, result) |
| 1109 | self._coercion_maps.set(S, R, None, swap) |
1091 | 1110 | return homs |
1092 | 1111 | |
1093 | 1112 | cpdef verify_coercion_maps(self, R, S, homs, bint fix=False): |