# HG changeset patch
# User Nicolas M. Thiery <nthiery@users.sf.net>
# Date 1364338907 25200
# Node ID 6e94cd616e566d9ed4cdd3e8b1ab46c69eef8a5e
# Parent  d8ab39e69ac14ad5b75d01036554eb8922455591
#12894: Add classcall setter in ClasscallMetaclass (follow up to #12808)

diff --git a/sage/misc/classcall_metaclass.pyx b/sage/misc/classcall_metaclass.pyx
--- a/sage/misc/classcall_metaclass.pyx
+++ b/sage/misc/classcall_metaclass.pyx
@@ -58,10 +58,20 @@ cdef class ClasscallMetaclass(NestedClas
     and :meth:`__contains__` for the description of the respective
     protocols.
 
-    .. warning:: for technical reasons, ``__classcall__``,
+    .. WARNING::
+
+        For technical reasons, ``__classcall__``,
         ``__classcall_private__``, ``__classcontains__``, and
-        ``__classget__`` must be defined as :func:`staticmethod`'s, even
-        though they receive the class itself as their first argument.
+        ``__classget__`` must be defined as :func:`staticmethod`'s,
+        even though they receive the class itself as their first
+        argument.
+
+    .. WARNING::
+
+        For efficiency reasons, the resolution for the special methods
+        is done once for all, upon creation of the class. Thus, later
+        dynamic changes to those methods are ignored. But see also
+        :meth:`_set_classcall`.
 
     ``ClasscallMetaclass`` is an extension of the base :class:`type`.
 
@@ -109,6 +119,47 @@ cdef class ClasscallMetaclass(NestedClas
         self.classcontains = getattr(self, "__classcontains__", None)
         self.classget = getattr(self, "__classget__", None)
 
+    def _set_classcall(cls, function):
+        r"""
+        Change dynamically the classcall function for this class
+
+        EXAMPLES::
+
+            sage: from sage.misc.classcall_metaclass import ClasscallMetaclass
+            sage: class FOO(object):
+            ...       __metaclass__ = ClasscallMetaclass
+            sage: FOO()
+            <__main__.FOO object at ...>
+
+        For efficiency reason, the resolution of the ``__classcall__``
+        method is done once for all, upon creation of the class. Thus,
+        later dynamic changes to this method are ignored by FOO::
+
+            sage: FOO.__classcall__ = ConstantFunction(1)
+            sage: FOO()
+            <__main__.FOO object at ...>
+
+        but not by subclasses created later on::
+
+            sage: class BAR(FOO): pass
+            sage: BAR()
+            1
+
+        To update the ``classcall`` special function for FOO, one
+        should use this setter::
+
+            sage: FOO._set_classcall(ConstantFunction(2))
+            sage: FOO()
+            2
+
+        Note that it has no influence on subclasses::
+
+            sage: class BAR(FOO): pass
+            sage: BAR()
+            1
+        """
+        cls.classcall = function
+
     def __call__(cls, *args, **opts):
         r"""
         This method implements ``cls(<some arguments>)``.
@@ -263,7 +314,7 @@ cdef class ClasscallMetaclass(NestedClas
             sage: sys.getrefcount(NOCALL())
             1
 
-        We check that exception are correctly handled::
+        We check that exceptions are correctly handled::
 
             sage: class Exc(object):
             ...       __metaclass__ = ClasscallMetaclass
