# HG changeset patch
# User Jean-Pierre Flori
# Date 1331128122 -3600
# Node ID 36c211dc61a6bf79dee93a227a37f23e9dd7de23
# Parent d3c9efea86f7440332b9c43d9dc3e4dafd38a73d
#715: Reviewer patch -- minor typos and additional doc
diff --git a/sage/categories/action.pyx b/sage/categories/action.pyx
--- a/sage/categories/action.pyx
+++ b/sage/categories/action.pyx
@@ -1,14 +1,48 @@
r"""
-Group, ring, etc. actions on objects.
+Group, ring, etc. actions on objects.
-The terminology and notation used is suggestive of groups
-acting on sets, but this framework can be used for modules,
-algebras, etc.
+The terminology and notation used is suggestive of groups acting on sets,
+but this framework can be used for modules, algebras, etc.
-A group action $G \times S \rightarrow S$ is a functor from $G$ to Sets.
+A group action $G \times S \rightarrow S$ is a functor from $G$ to Sets.
-AUTHORS:
- -- Robert Bradshaw: initial version
+.. WARNING::
+
+ An :class:`Action` object only keeps a weak reference to the underlying set
+ which is acted upon. This decision was made in :trac:`715` in order to
+ allow garbage collection within the coercion framework (this is where
+ actions are mainly used) and avoid memory leaks.
+
+ ::
+
+ sage: from sage.categories.action import Action
+ sage: class P: pass
+ sage: A = Action(P(),P())
+ sage: import gc
+ sage: _ = gc.collect()
+ sage: A
+ Traceback (most recent call last):
+ ...
+ RuntimeError: This action acted on a set that became garbage collected
+
+ To avoid garbage collection of the underlying set, it is sufficient to
+ create a strong reference to it before the action is created.
+
+ ::
+
+ sage: _ = gc.collect()
+ sage: from sage.categories.action import Action
+ sage: class P: pass
+ sage: q = P()
+ sage: A = Action(P(),q)
+ sage: gc.collect()
+ 0
+ sage: A
+ Left action by <__main__.P instance at ...> on <__main__.P instance at ...>
+
+AUTHOR:
+
+- Robert Bradshaw: initial version
"""
#*****************************************************************************
@@ -130,8 +164,8 @@
sage: A.left_domain() is R
True
- By trac ticket #715, there is only a weak reference to the underlying
- set. Hence, the underlying set may be garbage collected, even when the
+ By :trac:`715`, there is only a weak reference to the underlying set.
+ Hence, the underlying set may be garbage collected, even when the
action is still alive. This may result in a runtime error, as follows::
sage: from sage.categories.action import Action
@@ -143,7 +177,7 @@
Left action by <__main__.P instance at ...> on <__main__.P instance at ...>
sage: del q
sage: import gc
- sage: n = gc.collect()
+ sage: _ = gc.collect()
sage: A
Traceback (most recent call last):
...
diff --git a/sage/matrix/action.pyx b/sage/matrix/action.pyx
--- a/sage/matrix/action.pyx
+++ b/sage/matrix/action.pyx
@@ -1,8 +1,42 @@
"""
-These are the actions used by the coercion model for matrix and vector multiplications.
+These are the actions used by the coercion model for matrix and vector
+multiplications.
-AUTHORS:
- -- Robert Bradshaw (2007-09): Initial version.
+.. WARNING::
+
+ The class :class:`MatrixMulAction` and its descendants extends the class
+ :class:`Action`. As a cosnequence objects from these classes only keep weak
+ references to the underlying sets which are acted upon. This decision was
+ made in :trac:`715` in order to allow garbage collection within the coercion
+ framework, where actions are mainly used, and avoid memory leaks.
+
+ To ensure that the underlying set of such an object does not get garbage
+ collected, it is sufficient to explicitely create a strong reference to it
+ before creating the action.
+
+ ::
+
+ sage: MSQ = MatrixSpace(QQ, 2)
+ sage: MSZ = MatrixSpace(ZZ['x'], 2)
+ sage: A = MSQ.get_action(MSZ)
+ sage: A
+ Left action by Full MatrixSpace of 2 by 2 dense matrices over Rational Field on Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Integer Ring
+ sage: import gc
+ sage: _ = gc.collect()
+ sage: A
+ Left action by Full MatrixSpace of 2 by 2 dense matrices over Rational Field on Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Integer Ring
+
+.. NOTE::
+
+ The :func:`MatrixSpace` function caches the objects it creates. Therefore,
+ the underlying set ``MSZ`` in the above example will not be garbage
+ collected, even if it is not strongly ref'ed. Nonetheless, there is no
+ guarantee that the set that is acted upon will always be cached in such a
+ way, so that following the above example is good practice.
+
+AUTHOR:
+
+- Robert Bradshaw (2007-09): Initial version.
"""
#*****************************************************************************
@@ -40,10 +74,10 @@
"""
EXAMPLES:
- By trac ticket #715, there only is a weak reference on the underlying set,
- so that it can be garbage collected if only the action itself is explicitly
- referred to. Hence, we first assign the involved matrix spaces to a
- variable::
+ By :trac:`715`, there only is a weak reference on the underlying set,
+ so that it can be garbage collected if only the action itself is
+ explicitly referred to. Hence, we first assign the involved matrix
+ spaces to a variable::
sage: MSQ = MatrixSpace(QQ, 2)
sage: MSZ = MatrixSpace(ZZ['x'], 2)
@@ -55,6 +89,16 @@
Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Integer Ring
sage: A.codomain()
Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Rational Field
+
+ .. NOTE::
+
+ The :func:`MatrixSpace` function caches the object it creates.
+ Therefore, the underlying set ``MSZ`` in the above example will not
+ be garbage collected, even if it is not strongly ref'ed.
+ Nonetheless, there is no guarantee that the set that is acted upon
+ will always be cached in such a way, so that following the above
+ example is good practice.
+
"""
return self.underlying_set()
@@ -64,10 +108,10 @@
"""
EXAMPLES:
- By trac ticket #715, there only is a weak reference on the underlying set,
- so that it can be garbage collected if only the action itself is explicitly
- referred to. Hence, we first assign the involved matrix spaces to a
- variable::
+ By :trac:`715`, there only is a weak reference on the underlying set,
+ so that it can be garbage collected if only the action itself is
+ explicitly referred to. Hence, we first assign the involved matrix
+ spaces to a variable::
sage: R. = ZZ[]
sage: MSR = MatrixSpace(R, 3, 3)
@@ -81,6 +125,16 @@
[ 0 x]
[2*x 3*x]
[4*x 5*x]
+
+ .. NOTE::
+
+ The :func:`MatrixSpace` function caches the object it creates.
+ Therefore, the underlying set ``MSZ`` in the above example will not
+ be garbage collected, even if it is not strongly ref'ed.
+ Nonetheless, there is no guarantee that the set that is acted upon
+ will always be cached in such a way, so that following the above
+ example is good practice.
+
"""
if not is_MatrixSpace(S):
raise TypeError, "Not a matrix space: %s" % S
@@ -90,10 +144,10 @@
"""
EXAMPLES:
- By trac ticket #715, there only is a weak reference on the underlying set,
- so that it can be garbage collected if only the action itself is explicitly
- referred to. Hence, we first assign the involved matrix spaces to a
- variable::
+ By :trac:`715`, there only is a weak reference on the underlying set,
+ so that it can be garbage collected if only the action itself is
+ explicitly referred to. Hence, we first assign the involved matrix
+ spaces to a variable::
sage: from sage.matrix.action import MatrixMatrixAction
sage: R. = ZZ[]
@@ -103,6 +157,16 @@
Left action by Full MatrixSpace of 3 by 3 dense matrices over Univariate Polynomial Ring in x over Integer Ring on Full MatrixSpace of 3 by 2 dense matrices over Rational Field
sage: A.codomain()
Full MatrixSpace of 3 by 2 dense matrices over Univariate Polynomial Ring in x over Rational Field
+
+ .. NOTE::
+
+ The :func:`MatrixSpace` function caches the object it creates.
+ Therefore, the underlying set ``MSZ`` in the above example will not
+ be garbage collected, even if it is not strongly ref'ed.
+ Nonetheless, there is no guarantee that the set that is acted upon
+ will always be cached in such a way, so that following the above
+ example is good practice.
+
"""
if self.G.ncols() != self.underlying_set().nrows():
raise TypeError, "incompatible dimensions %s, %s" % (self.G.ncols(), self.underlying_set().nrows())
diff --git a/sage/structure/coerce_dict.pyx b/sage/structure/coerce_dict.pyx
--- a/sage/structure/coerce_dict.pyx
+++ b/sage/structure/coerce_dict.pyx
@@ -24,8 +24,8 @@
"""
Erases items from a :class:`TripleDict` when a weak reference becomes invalid.
- This is of internal use only. Instances of this class will be passed as a callback
- function when creating a weak reference.
+ This is of internal use only. Instances of this class will be passed as a
+ callback function when creating a weak reference.
EXAMPLES::
@@ -46,7 +46,7 @@
AUTHOR:
- Simon King (2012-01)
+ - Simon King (2012-01)
"""
def __init__(self, D):
@@ -64,15 +64,16 @@
"""
self.D = D
+
def __call__(self, r):
"""
INPUT:
A weak reference with key.
- When this is called with a weak reference ``r``, then each item containing ``r``
- is removed from the associated :class:`TripleDict`. Normally, this only happens
- when a weak reference becomes invalid.
+ When this is called with a weak reference ``r``, then each item
+ containing ``r`` is removed from the associated :class:`TripleDict`.
+ Normally, this only happens when a weak reference becomes invalid.
EXAMPLES::
@@ -195,8 +196,8 @@
Note that this kind of dictionary is also used for caching actions
and coerce maps. In previous versions of Sage, the cache was by
strong references and resulted in a memory leak in the following
- example. However, this leak was fixed by trac ticket #715, using
- weak references::
+ example. However, this leak was fixed by trac ticket :trac:`715`,
+ using weak references::
sage: K = GF(1<<55,'t')
sage: for i in range(50):
@@ -211,9 +212,10 @@
sage: len(LE) # indirect doctest
1
- AUTHOR::
+ AUTHORS:
- Robert Bradshaw, 2007-08
+
- Simon King, 2012-01
"""
@@ -261,7 +263,7 @@
"""
The distribution of items in buckets.
- OUTPUT::
+ OUTPUT:
- (min, avg, max)
@@ -300,7 +302,7 @@
OUTPUT:
- A list of how many items are in each bucket.
+ A list of how many items are in each bucket.
EXAMPLES::