Ticket #3738: 3738-11-constructor.patch

File 3738-11-constructor.patch, 6.5 KB (added by robertwb, 11 years ago)
  • sage/structure/parent.pyx

    # HG changeset patch
    # User Robert Bradshaw <robertwb@math.washington.edu>
    # Date 1217398211 25200
    # Node ID e45a2ed6fd79da18208e2eee5958f879879590f5
    # Parent  dc916c91e7909834c0173c5302e1b4fab96850cf
    Allow element_constructor to be passed in _populate_coercion_lists_ and look for _element_constructor_ as default.
    
    diff -r dc916c91e790 -r e45a2ed6fd79 sage/structure/parent.pyx
    a b def is_Parent(x): 
    9494        True   
    9595    """
    9696    return PY_TYPE_CHECK(x, Parent)
    97    
     97
     98cdef bint guess_pass_parent(parent, element_constructor):
     99    if PY_TYPE_CHECK(element_constructor, types.MethodType):
     100        return False
     101    elif PY_TYPE_CHECK(element_constructor, BuiltinMethodType):
     102        return element_constructor.__self__ is not parent
     103    else:
     104        return True
     105
    98106
    99107cdef object all_parents = [] #weakref.WeakKeyDictionary()
    100108
    cdef class Parent(category_object.Catego 
    133141        elif names is not None:
    134142            self._assign_names(names, normalize)
    135143        self._element_constructor = element_constructor
    136         if hasattr(element_constructor, 'init_no_parent'):
    137             self._element_init_pass_parent = not element_constructor.init_no_parent
    138         elif PY_TYPE_CHECK(element_constructor, types.MethodType):
    139             self._element_init_pass_parent = False
    140         elif PY_TYPE_CHECK(element_constructor, BuiltinMethodType):
    141             self._element_init_pass_parent = element_constructor.__self__ is not self
    142         else:
    143             self._element_init_pass_parent = True
     144        self._element_init_pass_parent = guess_pass_parent(self, element_constructor)
    144145        self._coerce_from_list = []
    145146        self._coerce_from_hash = {}
    146147        self._action_list = []
    cdef class Parent(category_object.Catego 
    206207        except KeyError:
    207208            version = 0
    208209        if version == 1:
    209             self._element_constructor = d['_element_constructor']
    210210            self.init_coerce(False) # Really, do we want to init this with the same initial data as before?
    211211            self._populate_coercion_lists_(coerce_list=d['_initial_coerce_list'] or [],
    212212                                           action_list=d['_initial_action_list'] or [],
    213213                                           convert_list=d['_initial_convert_list'] or [],
    214214                                           embedding=d['_embedding'],
    215215                                           convert_method_name=d['_convert_method_name'],
    216                                            init_no_parent=not d['_element_init_pass_parent'])
     216                                           element_constructor = d['_element_constructor'],
     217                                           init_no_parent=not d['_element_init_pass_parent'],
     218                                           unpickling=True)
    217219
    218220    def __call__(self, x=0, *args, **kwds):
    219221        """
    cdef class Parent(category_object.Catego 
    474476    # New New Coercion support functionality
    475477    #################################################################################
    476478   
    477     def _populate_coercion_lists_(self, coerce_list=[], action_list=[], convert_list=[], embedding=None, convert_method_name=None, init_no_parent=None):
     479    def _populate_coercion_lists_(self,
     480                                  coerce_list=[],
     481                                  action_list=[],
     482                                  convert_list=[],
     483                                  embedding=None,
     484                                  convert_method_name=None,
     485                                  element_constructor=None,
     486                                  init_no_parent=None,
     487                                  unpickling=False):
    478488        """
    479489        This function allows one to specify coercions, actions, conversions
    480490        and embeddings involving this parent.
    cdef class Parent(category_object.Catego 
    482492        IT SHOULD ONLY BE CALLED DURING THE __INIT__ method, often at the end.
    483493       
    484494        INPUT:
    485             coerce_list  -- a list of coercion Morphisms to self and
    486                             parents with cannonical coercions to self
    487             action_list  -- a list of actions on and by self
    488             convert_list -- a list of conversion Maps to self and
    489                             parents with conversions to self
    490             embedding    -- a single Morphism from self
     495            coerce_list    -- a list of coercion Morphisms to self and
     496                              parents with cannonical coercions to self
     497            action_list    -- a list of actions on and by self
     498            convert_list   -- a list of conversion Maps to self and
     499                              parents with conversions to self
     500            embedding      -- a single Morphism from self
    491501            convert_method_name -- a name to look for that other elements
    492                             can implement to create elements of self (e.g. _integer_)
     502                              can implement to create elements of self (e.g. _integer_)
     503            element_constructor -- A callable object used by the __call__ method to
     504                              construct new elements. Typically the element class or a
     505                              bound method (defaults to self._element_constructor_).
    493506            init_no_parent -- if True omit passing self in as the first
    494507                              argument of element_constructor for conversion. This is
    495508                              useful if parents are unique, or element_constructor is
    496                               a bound method.
     509                              a bound method (this latter case can be detected
     510                              automatically).
    497511        """
     512        self.init_coerce(False)
     513       
     514        if element_constructor is None and not unpickling:
     515            try:
     516                element_constructor = self._element_constructor_
     517            except AttributeError:
     518                raise RuntimeError, "element_constructor must be provided, either as an _element_constructor_ method or via the _populate_coercion_lists_ call"
     519        self._element_constructor = element_constructor
     520        self._element_init_pass_parent = guess_pass_parent(self, element_constructor)
     521       
    498522        if not PY_TYPE_CHECK(coerce_list, list):
    499523            raise ValueError, "%s_populate_coercion_lists_: coerce_list is type %s, must be list" % (type(coerce_list), type(self))
    500524        if not PY_TYPE_CHECK(action_list, list):