#14524: Decorator for methods requiring mutability or immutability
-----------------------------+----------------------------------------------
Reporter: SimonKing | Owner: jason
Type: PLEASE CHANGE | Status: new
Priority: major | Milestone: sage-5.10
Component: misc | Keywords: decorator mutability
Work issues: | Report Upstream: N/A
Reviewers: | Authors: Simon King
Merged in: | Dependencies:
Stopgaps: |
-----------------------------+----------------------------------------------
Some methods (most notably `__hash__`) require that an object is
immutable. Other methods (such as `add_vertex` of a graph) require that an
object is mutable.
I suggest to introduce a method decorator, such that (im)mutability is
automatically verified before calling the method. Note that the patch just
creates the decorator, but does not use it yet. In a second step, I plan
to use it on graphs.
The decorator tests immutability by the value of an attribute called
`_is_immutable`, which is used by `sage.structure.mutability.Mutability`
anyway (but I change this attribute into a public attribute).
Unfortunately, `sage.graphs.generic_graph.GenericGraph.__hash__` uses
another name, namely `_immutable`. But I think this can be changed in the
second step.
From the doctests:
{{{
sage: from sage.structure.mutability import require_mutable,
require_immutable
sage: class A:
... def __init__(self, val):
... self._m = val
... @require_mutable
... def change(self, new_val):
... 'change self'
... self._m = new_val
... @require_immutable
... def __hash__(self):
... 'implement hash'
... return hash(self._m)
sage: a = A(5)
sage: a.change(6)
sage: hash(a)
Traceback (most recent call last):
...
AssertionError: <type 'instance'> instance is mutable, <function
__hash__ at ...> must not be called
sage: a._is_immutable = True
sage: hash(a)
6
sage: a.change(7) # indirect doctest
Traceback (most recent call last):
...
AssertionError: <type 'instance'> instance is immutable, <function
change at ...> must not be called
sage: from sage.misc.sageinspect import sage_getdoc
sage: print sage_getdoc(a.change)
change self
}}}
As one can see, by default an object is supposed to be mutable. This may
be important during initialisation of the object. So, one would first
initialise it and then declare that it is (from now on) immutable.
__Questions__
- Is `AssertionError` the right thing to raise here? Usually, when hashing
does not work, a `TypeError` is raised.
- One could be more intrusive. For example, when calling a method
decorated by `require_immutable` on a mutable object, one could instead
''make'' it immutable (by assignment to `_is_immutable`. In that way,
after the first call to `hash`, the object can not be accidentally changed
(but of course, if the user wants so, `_is_immutable` can be deleted).
Good idea, or not pythonic?
--
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/14524>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica,
and MATLAB
--
You received this message because you are subscribed to the Google Groups
"sage-trac" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sage-trac?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.