# HG changeset patch
# User Nicolas M. Thiery <nthiery@users.sf.net>
# Date 1241455730 25200
# Node ID 9b261cc69cc74c6730d3a20a8aaf026784f1cde4
# Parent b2fb9f8a5e257c9b2e6f295025c3e6de8bac4d71
#5979 Parent: fixes broken (implicit) invariant between ._element_constructor and self._element_init_pass_parent
In Parent, there is a (previously implicit) invariant, namely that:
self._element_init_pass_parent == guess_pass_parent(between ._element_constructor)
This invariant was broken when self._element_constructor was set from
self._element_constructor_ by __call__. This made the parent not to be
passed properly to _element_constructor.
The category patch #5891 depends heavily on this one, as this way of
setting _element_constructor becomes the default one for simple
parents.
By the way, this patch makes a related trivial fix to a line that is
apparently never used in coerce_maps, and adds a comment about it.
diff --git a/sage/structure/coerce_maps.pyx b/sage/structure/coerce_maps.pyx
a
|
b
|
cdef class DefaultConvertMap(Map): |
44 | 44 | try: |
45 | 45 | if len(args) == 0: |
46 | 46 | if len(kwds) == 0: |
47 | | return self._codomain.__element_constructor(self._codomain, x) |
| 47 | # This line is apparently never used in any tests (hivert, 2009-04-28) |
| 48 | return self._codomain._element_constructor(self._codomain, x) |
48 | 49 | else: |
49 | 50 | return self._codomain._element_constructor(self._codomain, x, **kwds) |
50 | 51 | else: |
diff --git a/sage/structure/parent.pyx b/sage/structure/parent.pyx
a
|
b
|
cdef class Parent(category_object.Catego |
124 | 124 | """ |
125 | 125 | Parents are the Sage/mathematical analogues of container objects |
126 | 126 | in computer science. |
| 127 | |
| 128 | Internal invariants: |
| 129 | - self._element_init_pass_parent == guess_pass_parent(self, self._element_constructor) |
| 130 | Ensures that self.__call__ passes down the parent properly to self._element_constructor. |
| 131 | See #5979. |
| 132 | |
127 | 133 | """ |
128 | 134 | |
129 | 135 | def __init__(self, base=None, *, categories=[], element_constructor=None, gens=None, names=None, normalize=True, **kwds): |
… |
… |
cdef class Parent(category_object.Catego |
258 | 264 | By default this will dispatch as quickly as possible to |
259 | 265 | :meth:`_element_constructor_` though faster pathways are |
260 | 266 | possible if so desired. |
| 267 | |
| 268 | TESTS: |
| 269 | |
| 270 | We check that the invariant:: |
| 271 | |
| 272 | self._element_init_pass_parent == guess_pass_parent(self, self._element_constructor) |
| 273 | |
| 274 | is preserved (see #5979):: |
| 275 | |
| 276 | sage: class MyParent(Parent): |
| 277 | ... def _element_constructor_(self, x): |
| 278 | ... print self, x |
| 279 | ... return sage.structure.element.Element(parent = self) |
| 280 | ... def _repr_(self): |
| 281 | ... return "my_parent" |
| 282 | ... |
| 283 | sage: my_parent = MyParent() |
| 284 | sage: x = my_parent("bla") |
| 285 | my_parent bla |
| 286 | sage: x.parent() # indirect doctest |
| 287 | my_parent |
| 288 | |
| 289 | sage: x = my_parent() # shouldn't this one raise an error? |
| 290 | my_parent 0 |
| 291 | sage: x = my_parent(3) # todo: not implemented why does this one fail??? |
| 292 | my_parent 3 |
| 293 | |
| 294 | |
261 | 295 | """ |
262 | 296 | if self._element_constructor is None: |
263 | 297 | # Neither __init__ nor _populate_coercion_lists_ have been called... |
264 | 298 | try: |
265 | 299 | assert callable(self._element_constructor_) |
266 | 300 | self._element_constructor = self._element_constructor_ |
| 301 | self._element_init_pass_parent = guess_pass_parent(self, self._element_constructor) |
267 | 302 | except (AttributeError, AssertionError): |
268 | 303 | raise NotImplementedError |
269 | 304 | cdef Py_ssize_t i |
… |
… |
cdef class Parent(category_object.Catego |
675 | 710 | is useful if parents are unique, or element_constructor is a |
676 | 711 | bound method (this latter case can be detected |
677 | 712 | automatically). |
| 713 | |
| 714 | |
678 | 715 | """ |
679 | 716 | self.init_coerce(False) |
680 | 717 | |