Ticket #10651: trac_10651_fix_an_element_from_iterator-nb.patch

File trac_10651_fix_an_element_from_iterator-nb.patch, 7.7 KB (added by nborie, 10 years ago)
  • sage/categories/enumerated_sets.py

    # HG changeset patch
    # User Nicolas Borie <nicolas.borie at math.u-psud.fr>
    # Date 1300722251 -3600
    # Node ID 032e518ee6e6538630d79d4fb39ce82667cc301a
    # Parent  bbafc570013be0ea0c2002af9025f5394f2746d3
    10651 : Make a good use of the EmptySetError in EnumeratedSets and Parent
    
    diff --git a/sage/categories/enumerated_sets.py b/sage/categories/enumerated_sets.py
    a b Enumerated Sets 
    1111from sage.misc.cachefunc import cached_method
    1212from category_types import Category
    1313from sage.categories.sets_cat import Sets
     14from sage.categories.sets_cat import EmptySetError
    1415
    1516class EnumeratedSets(Category):
    1617    """
    class EnumeratedSets(Category): 
    448449                else:
    449450                    yield u
    450451
    451         # This @cached_method also allows for the temporary assignments
    452         # _an_element_ = EnumeratedSets.ParentMethods._an_element_
    453         # in parents in this category (see e.g. examples/FiniteEnumeratedSets)
    454         # until Parent won't override anymore the _an_element_ defined in categories
     452        # This @cached_method is not really needed, since the method
     453        # an_element itself is cached. We leave it for the moment, so
     454        # that Parents that do not yet inherit properly from categories
     455        # (e.g. Set([1,2,3]) can use the following trick:
     456        #    _an_element_ = EnumeratedSets.ParentMethods._an_element_
    455457        @cached_method
    456458        def _an_element_from_iterator(self):
    457459            """
    458             An element in ``self``.
     460            Returns the first element of ``self`` returned by :meth:`__iter__`
    459461
    460             ``self.an_element()`` returns a particular element of the set
    461             ``self``. This is a generic implementation from the category
    462             ``EnumeratedSets()`` which can be used when the method ``__iter__``
    463             is provided.
     462            If ``self`` is empty, the exception
     463            :class:`~sage.categories.sets_cat.EmptySetError` is raised instead.
     464
     465            This provides a generic implementation of the method
     466            :meth:`_an_element_` for all parents in :class:`EnumeratedSets`.
    464467
    465468            EXAMPLES::
    466469
    467                 sage: C = FiniteEnumeratedSets().example()
     470                sage: C = FiniteEnumeratedSets().example(); C
     471                An example of a finite enumerated set: {1,2,3}
    468472                sage: C.an_element() # indirect doctest
    469473                1
     474                sage: S = Set([])
     475                sage: S.an_element()
     476                Traceback (most recent call last):
     477                ...
     478                EmptySetError
     479
     480            TESTS::
     481
     482                sage: super(Parent, C)._an_element_
     483                Cached version of <function _an_element_from_iterator at ...>
    470484            """
    471485            it = self.__iter__()
    472             return it.next()
     486            try:
     487                return it.next()
     488            except StopIteration:
     489                raise EmptySetError
    473490
    474491        # Should this be implemented from first instead?
    475492        _an_element_ = _an_element_from_iterator
  • sage/categories/examples/finite_enumerated_sets.py

    diff --git a/sage/categories/examples/finite_enumerated_sets.py b/sage/categories/examples/finite_enumerated_sets.py
    a b class Example(UniqueRepresentation, Pare 
    104104        """
    105105        return iter(self._set)
    106106
    107     # temporarily needed because parent overloads it.
    108     an_element = EnumeratedSets.ParentMethods._an_element_
    109 
    110 
    111107class IsomorphicObjectOfFiniteEnumeratedSet(UniqueRepresentation, Parent):
    112108
    113109    def __init__(self, ambient = Example()):
  • sage/categories/sets_cat.py

    diff --git a/sage/categories/sets_cat.py b/sage/categories/sets_cat.py
    a b class Sets(Category): 
    581581                47
    582582                sage: S.some_elements()
    583583                [47]
     584                sage: S = Set([])
     585                sage: S.some_elements()
     586                []
    584587
    585588            This method should return an iterable, *not* an iterator.
    586589            """
    587             return [ self.an_element() ]
     590            try:
     591                return [ self.an_element() ]
     592            except EmptySetError:
     593                return []
    588594
    589595        def _test_some_elements(self, **options):
    590596            """
  • sage/sets/set.py

    diff --git a/sage/sets/set.py b/sage/sets/set.py
    a b def Set(X): 
    107107        {1, 2, 3}
    108108        sage: type(_)
    109109        <class 'sage.sets.set.Set_object_enumerated_with_category'>
     110        sage: S = Set([])
     111        sage: TestSuite(S).run()
    110112    """
    111113    if is_Set(X):
    112114        return X
  • sage/structure/parent.pyx

    diff --git a/sage/structure/parent.pyx b/sage/structure/parent.pyx
    a b cimport sage.categories.morphism as morp 
    7272cimport sage.categories.map as map
    7373from sage.structure.sage_object import SageObject
    7474from sage.misc.lazy_attribute import lazy_attribute
    75 from sage.categories.sets_cat import Sets
     75from sage.categories.sets_cat import Sets, EmptySetError
    7676from copy import copy
    7777from sage.misc.sage_itertools import unique_merge
    7878from sage.misc.lazy_format import LazyFormat
    cdef class Parent(category_object.Catego 
    21562156        """
    21572157        return None
    21582158
    2159 # Should be taken care of by the category Sets().
     2159    # TODO: remove once all parents in Sage will inherit properly from
     2160    # Sets().ParentMethods.an_element
    21602161    cpdef an_element(self):
    21612162        r"""
    2162         Implementation of a function that returns an element (often non-trivial)
    2163         of a parent object.  This is cached. Parent structures that are should
    2164         override :meth:`_an_element_` instead.
     2163        Returns a (preferably typical) element of this parent.
     2164
     2165        This is used both for illustration and testing purposes. If
     2166        the set ``self`` is empty, :meth:`an_element` raises the
     2167        exception :class:`EmptySetError`.
     2168
     2169        This calls :meth:`_an_element_` (which see), and caches the
     2170        result. Parent are thus encouraged to override :meth:`_an_element_`.
    21652171
    21662172        EXAMPLES::
    2167        
     2173
    21682174            sage: CDF.an_element()
    21692175            1.0*I
    21702176            sage: ZZ[['t']].an_element()
    21712177            t
     2178
     2179        In case the set is empty, an :class:`EmptySetError` is raised::
     2180
     2181            sage: Set([]).an_element()
     2182            Traceback (most recent call last):
     2183            ...
     2184            EmptySetError
    21722185        """
    21732186        if self.__an_element is None:
    21742187            self.__an_element = self._an_element_()
    cdef class Parent(category_object.Catego 
    21862199            1/2
    21872200            sage: ZZ['x,y,z']._an_element_()
    21882201            x
     2202
     2203        TESTS:
     2204
     2205        Since ``Parent`` comes before the parent classes provided by
     2206        categories in the hierarchy of classes, we make sure that this
     2207        default implementation of :meth:`_an_element_` does not
     2208        override some provided by the categories.  Eventually, this
     2209        default implementation should be moved into the categories to
     2210        avoid this workaround::
     2211
     2212            sage: S = FiniteEnumeratedSet([1,2,3])
     2213            sage: S.category()
     2214            Category of finite enumerated sets
     2215            sage: super(Parent, S)._an_element_
     2216            Cached version of <function _an_element_from_iterator at ...>
     2217            sage: S._an_element_()
     2218            1
     2219            sage: S = FiniteEnumeratedSet([])
     2220            sage: S._an_element_()
     2221            Traceback (most recent call last):
     2222            ...
     2223            EmptySetError
     2224
    21892225        """
    21902226        try:
    21912227            return super(Parent, self)._an_element_()
     2228        except EmptySetError:
     2229            raise
    21922230        except:
    21932231            _record_exception()
    21942232            pass