Ticket #7921: trac_7921-categories_for_extension_types-nt.patch

File trac_7921-categories_for_extension_types-nt.patch, 82.7 KB (added by nthiery, 12 years ago)

Rebased and updated one doctest for 4.3.1 + micro fix in the primer. Apply only this one.

  • doc/en/tutorial/programming.rst

    # HG changeset patch
    # User Nicolas M. Thiery <nthiery@users.sf.net>
    # Date 1264197209 -3600
    # Node ID b086ab514386d0b6eda981aed0e05108b6d89b7e
    # Parent  eb27a39a6df43f557bdc8bc838c30f3b5c41e925
    #7921: Categories for extension types via __getattr___
    
     - As of now, only parents which declare their category in their
       constructor (or the constructor of some super class) inherit code
       from their category (see _is_category_initialized). On the other
       hand, all elements inherit code from the category of their
       parents. On the other hand, __dir__ always looks up the category.
    
       This is achieved by inheritance for usual classes, and by getattr
       for extension types. Caveat: getattr does not play well with
       conditional lazy attributes.
    
     - Many parents had a category method such as:
    
       def category(self): return Blah(self.truc())
    
       where truc was a method using an attribute _truc as cache.
    
       This caused a recursive loop, since the attribute lookup triggered
       a call to self.category() which ...
    
       To fix this, this patch removes most category methods implemented
       in parents, and replace them by category declarations in the
       constructors of:
    
        - ModularAbelianVariety_abstract, AmbientSpace, Scheme
        - HeckeModules_generic
        - GroupAlgebra
        - SteenrodAlgebra
        - WeylCharacterRing_class, WeightRing
        - Group, CommutativeAlgebra
        - FreeModule_generic
        - NumberField_generic, ResidueField_generic
    
       As a side effect, parents in non extension types deriving from the
       classes above now inherits from categories by standard inheritance.
    
       A couple generic `def category(self)` were left as a temporary
       measure (see e.g. `Modules`). In case of ambiguity, category
       declarations in the constructor take priority.
    
       Hopefully no parent was downgraded into a lower category in the
       process.
    
     - Upgrades ZZ to EuclideanDomains
    
     - RootSystem is an abstract parent; it does not have elements of its
       own. There is a design discussion to be run to know whether such
       parents should inherit from Parent, what to do with an_element. In
       the meantime, RootSystem now inherits from SageObject instead of
       Parent, so that _test_an_element does not complain (so far
       RootSystem did not inherit from those because it did not declare
       explicitly its category).
    
     - Sets explicitly the category in WeylCharacters
    
     - Downgrades PoorManMap's from Element into SageObjects, since they
       have no parent.
    
     - Removes reflections attribute in WeylGroup to avoid a
       long-to-explain doctest failure (it was not used much, deprecated
       in #4326, and will be replaced soonish)
    
     - Uses ZZ(1) instead of ZZ as basic example for TestSuite (makes for
       a shorter verbose list of tests)
    
     - Adds a couple TestSuite to make sure things did not get wrong.
    
     - Detected broken _test_element_pickling in WeylCharacters (see
       #7922) and residue fields (see #7929); this patch temporarily skips
       those tests.
    
     - AttributeErrors raised by getattr sometimes don't emulate the exact
       same message as the standard Python message; updates some doctests
       accordingly
    
     - Use __dir__ for tab completion/... in infinite polynomials,
       instead of __members__ _getAttributeNames.
    
     - Adds sage.misc.sage_itertools.unique_merge
    
     - Simplify the logic of SageObject._test_not_implemented_methods.
       As a side effect, conditional lazy attributes that break for
       extension types are better handled.
    
    diff --git a/doc/en/tutorial/programming.rst b/doc/en/tutorial/programming.rst
    a b To this, Sage adds many other types. E.g 
    242242    sage: V = VectorSpace(QQ, 1000000); V
    243243    Vector space of dimension 1000000 over Rational Field
    244244    sage: type(V)
    245     <class 'sage.modules.free_module.FreeModule_ambient_field'>
     245    <class 'sage.modules.free_module.FreeModule_ambient_field_with_category'>
    246246
    247247Only certain
    248248functions can be called on ``V``. In other math software
  • doc/fr/tutorial/programming.rst

    diff --git a/doc/fr/tutorial/programming.rst b/doc/fr/tutorial/programming.rst
    a b vectoriels : 
    254254    sage: V = VectorSpace(QQ, 1000000); V
    255255    Vector space of dimension 1000000 over Rational Field
    256256    sage: type(V)
    257     <class 'sage.modules.free_module.FreeModule_ambient_field'>
     257    <class 'sage.modules.free_module.FreeModule_ambient_field_with_category'>
    258258
    259259Seules certaines fonctions peuvent être appelées sur ``V``. Dans
    260260d'autres logiciels mathématiques, cela se fait en notation
  • sage/algebras/group_algebra.py

    diff --git a/sage/algebras/group_algebra.py b/sage/algebras/group_algebra.py
    a b AUTHOR: 
    2323#                  http://www.gnu.org/licenses/
    2424#*****************************************************************************
    2525
     26
     27from sage.categories.all import GroupAlgebras
     28from sage.structure.parent_gens import ParentWithGens
    2629from sage.algebras.algebra import Algebra
    2730from sage.algebras.algebra_element import AlgebraElement
    2831from sage.rings.all import IntegerRing
    class GroupAlgebra(Algebra): 
    4144        OUTPUT:
    4245            -- a GroupAlgebra instance.
    4346
    44         EXAMPLES:
     47        EXAMPLES::
     48
    4549            sage: GroupAlgebra(GL(3, GF(7)))
    4650            Group algebra of group "General Linear Group of degree 3 over Finite
    4751            Field of size 7" over base ring Integer Ring
    class GroupAlgebra(Algebra): 
    4953            Traceback (most recent call last):
    5054            ...
    5155            TypeError: "1" is not a group
     56
     57            sage: GroupAlgebra(SU(2, GF(4, 'a')), IntegerModRing(12)).category()
     58            Category of group algebras over Ring of integers modulo 12
     59
    5260        """
    5361        if not base_ring.is_commutative():
    5462            raise NotImplementedError, "Base ring must be commutative"
    class GroupAlgebra(Algebra): 
    5664        if not isinstance(group, Group):
    5765            raise TypeError, '"%s" is not a group' % group
    5866
    59         Algebra.__init__(self, base_ring)
     67        ParentWithGens.__init__(self, base_ring, category = GroupAlgebras(base_ring))
     68
    6069        self._formal_sum_module = FormalSums(base_ring)
    6170        self._group = group
    6271
    class GroupAlgebra(Algebra): 
    285294        return GroupAlgebraElement
    286295
    287296
    288     def category(self):
    289         r"""
    290         The category to which self belongs, which is the category of group algebras over self.base_ring().
    291 
    292         EXAMPLES:
    293             sage: GroupAlgebra(SU(2, GF(4, 'a')), IntegerModRing(12)).category()
    294             Category of group algebras over Ring of integers modulo 12
    295         """
    296         from sage.categories.all import GroupAlgebras
    297         return GroupAlgebras(self.base_ring())
    298 
    299 
    300 
    301297class GroupAlgebraElement(AlgebraElement):
    302298   
    303299    def __init__(self, parent, x, check):
  • sage/algebras/steenrod_algebra.py

    diff --git a/sage/algebras/steenrod_algebra.py b/sage/algebras/steenrod_algebra.py
    a b REFERENCES: 
    6565#  Distributed under the terms of the GNU General Public License (GPL)
    6666#*****************************************************************************
    6767
     68from sage.categories.algebras import Algebras
    6869from sage.rings.ring import Algebra
    6970from sage.algebras.algebra_element import AlgebraElement
    7071from sage.structure.parent_gens import ParentWithGens
    class SteenrodAlgebra_generic(Algebra): 
    114115            Sq(0,1)
    115116            sage: SteenrodAlgebra(2, 'adem').Sq(0,1)
    116117            Sq^{2} Sq^{1} + Sq^{3}
     118
     119            sage: A = SteenrodAlgebra(3)
     120            sage: A.category()
     121            Category of algebras over Finite Field of size 3
     122            sage: TestSuite(A).run()
    117123        """
    118124        from sage.rings.arith import is_prime
    119         if is_prime(p):
    120             self.prime = p
    121             ParentWithGens.__init__(self, GF(p))
    122             self._basis_name = basis
    123         else:
     125        if not is_prime(p):
    124126            raise ValueError, "%s is not prime." % p
    125 
     127        self.prime = p
     128        base_ring = GF(p)
     129        # NT: maybe AlgebrasWithBasis?
     130        ParentWithGens.__init__(self, base_ring, category = Algebras(base_ring))
     131        self._basis_name = basis
    126132
    127133    def _repr_(self):
    128134        """
    class SteenrodAlgebra_generic(Algebra): 
    434440            False
    435441        """
    436442        return False
    437        
    438 
    439     def category(self):
    440         """
    441         The Steenrod algebra is an algebra over `F_p`.
    442        
    443         EXAMPLES::
    444        
    445             sage: A = SteenrodAlgebra(3)
    446             sage: A.category()
    447             Category of algebras over Finite Field of size 3
    448         """
    449         from sage.categories.all import Algebras
    450         return Algebras(GF(self.prime))
    451443
    452444
    453445    def basis(self, n):
  • sage/categories/morphism.pyx

    diff --git a/sage/categories/morphism.pyx b/sage/categories/morphism.pyx
    a b cdef class Morphism(Map): 
    6161        return s
    6262
    6363    def category(self):
    64         return self.parent().category()
     64        return self.parent().category() # Shouln't it be Category of elements of ...?
    6565
    6666    def is_endomorphism(self):
    6767        return self.parent().is_endomorphism_set()
  • sage/categories/poor_man_map.py

    diff --git a/sage/categories/poor_man_map.py b/sage/categories/poor_man_map.py
    a b Poor Man's map 
    77#  Distributed under the terms of the GNU General Public License (GPL)
    88#                  http://www.gnu.org/licenses/
    99#*****************************************************************************
    10 import sage.structure.element
     10import sage.structure.sage_object
    1111
    12 class PoorManMap(sage.structure.element.Element):
     12class PoorManMap(sage.structure.sage_object.SageObject):
    1313    """
    14     A class for maps between sets which are not (yet) modelled by parents
     14    A class for maps between sets which are not (yet) modeled by parents
    1515
    1616    Could possibly disapear when all combinatorial classes / enumerated sets will be parents
    1717    """
  • sage/categories/primer.py

    diff --git a/sage/categories/primer.py b/sage/categories/primer.py
    a b Example of mathematical information:: 
    110110        Integer Ring
    111111
    112112        sage: i.parent().category()
    113         Category of commutative rings
     113        Category of euclidean domains
    114114
    115115        sage: i.parent().categories()
    116         [Category of commutative rings,
     116        [Category of euclidean domains,
     117         Category of principal ideal domains,
     118         Category of gcd domains,
     119         Category of integral domains,
     120         Category of commutative rings,
     121         Category of domains,
    117122         Category of rings,
    118123         Category of rngs,
    119124         Category of commutative additive groups,
    Example of mathematical information:: 
    124129         Category of sets,
    125130         Category of objects]
    126131
    127         sage: CommutativeRings().category_graph().plot(talk = True)
     132        sage: EuclideanDomains().category_graph().plot(talk = True)
    128133
    129134This illustrates the following relations between mathematical objects:
    130135
  • sage/categories/sets_cat.py

    diff --git a/sage/categories/sets_cat.py b/sage/categories/sets_cat.py
    a b class Sets(Category): 
    190190                17
    191191                sage: S(17) # indirect doctest
    192192                17
     193
     194            Caveat: for some parents, element_class is a method, and
     195            not an attribute. We do not provide a default
     196            implementation of _element_constructor for those.
     197
     198                sage: FreeModule(QQ,3).element_class
     199                <bound method FreeModule_ambient_field_with_category.element_class of Vector space of dimension 3 over Rational Field>
     200                sage: FreeModule(QQ,3)._element_constructor
    193201            """
    194             if hasattr(self, "element_class"):
     202            if hasattr(self, "element_class") and issubclass(self.element_class, object):
    195203                return self._element_constructor_from_element_class
    196204            else:
    197205                return NotImplemented
  • sage/combinat/root_system/root_system.py

    diff --git a/sage/combinat/root_system/root_system.py b/sage/combinat/root_system/root_system.py
    a b See also 
    3737#                  http://www.gnu.org/licenses/
    3838#*****************************************************************************
    3939# Design largely inspired from MuPAD-Combinat
    40 from sage.structure.parent import Parent
     40from sage.structure.sage_object import SageObject
    4141from sage.structure.unique_representation import UniqueRepresentation
    4242from cartan_type import CartanType
    4343from sage.rings.all import ZZ, QQ
    from sage.misc.all import cached_method 
    4545from root_space import RootSpace
    4646from weight_space import WeightSpace
    4747
    48 class RootSystem(UniqueRepresentation, Parent):
     48class RootSystem(UniqueRepresentation, SageObject):
    4949    r"""
    5050    A class for root systems.
    5151   
  • sage/combinat/root_system/weyl_characters.py

    diff --git a/sage/combinat/root_system/weyl_characters.py b/sage/combinat/root_system/weyl_characters.py
    a b Weyl Characters 
    1616#                  http://www.gnu.org/licenses/
    1717#*****************************************************************************
    1818import cartan_type
     19from sage.categories.commutative_algebras import Algebras
    1920from sage.combinat.root_system.root_system import RootSystem
    2021from sage.combinat.root_system.dynkin_diagram import DynkinDiagram
    2122from sage.combinat.root_system.cartan_type import CartanType
    class WeylCharacterRing_class(Algebra): 
    622623            sage: R = WeylCharacterRing(['A',3])
    623624            sage: TestSuite(R).run()
    624625        """
    625         sage.structure.parent_base.ParentWithBase.__init__(self, base_ring)
     626        sage.structure.parent_base.ParentWithBase.__init__(self, base_ring, category = Algebras(base_ring))
    626627
    627628        self._cartan_type = ct
    628629        self._rank = ct.rank()
    class WeightRingElement(AlgebraElement): 
    22142215       
    22152216            sage: A2 = WeylCharacterRing(['A',2])
    22162217            sage: a2 = WeightRing(A2)
    2217             sage: TestSuite(a2).run()
     2218            sage: TestSuite(a2).run(skip = ["_test_element_pickling"]) # see #7922
    22182219        """
    22192220        AlgebraElement.__init__(self, A)
    22202221        self._mdict = mdict
    class WeightRing(Algebra): 
    25022503       
    25032504            sage: R = WeylCharacterRing(['G',2], prefix = "R", base_ring = QQ)
    25042505            sage: S = WeightRing(R, prefix = "S")
    2505             sage: TestSuite(S).run()
     2506            sage: TestSuite(S).run(skip = ["_test_element_pickling"]) # see #7922
    25062507        """
    25072508        self._parent = A
    25082509        self._cartan_type = self._parent._cartan_type
    class WeightRing(Algebra): 
    25172518        self._space = self._parent._space
    25182519        self._origin = self._parent._origin
    25192520        self._prefix = prefix
     2521        sage.structure.parent_base.ParentWithBase.__init__(self, self._base_ring, category = Algebras(self._base_ring))
    25202522
    25212523    def __call__(self, *args):
    25222524        """
  • sage/combinat/root_system/weyl_group.py

    diff --git a/sage/combinat/root_system/weyl_group.py b/sage/combinat/root_system/weyl_group.py
    a b class WeylGroup_gens(ClearCacheOnPickle, 
    229229        """
    230230        return self.lattice().simple_reflections().map(self.from_morphism)
    231231
    232     @lazy_attribute
    233     def reflections(self):
    234         import sage
    235         return sage.misc.misc.deprecation("reflections deprecated; use simple_reflections instead")
     232    #@lazy_attribute
     233    #def reflections(self):
     234    #    import sage
     235    #    return sage.misc.misc.deprecation("reflections deprecated; use simple_reflections instead")
    236236
    237237    def gens(self):
    238238        """
  • sage/groups/group.pyx

    diff --git a/sage/groups/group.pyx b/sage/groups/group.pyx
    a b cdef class Group(sage.structure.parent_g 
    5555        sage.structure.parent_gens.ParentWithGens.__init__(self,
    5656                sage.rings.integer_ring.ZZ, category = category)
    5757   
    58     def __call__(self, x):
     58    def __call__(self, x): # NT: doesn't this get in the way of the coercion mechanism?
    5959        """
    6060        Coerce x into this group.
    6161        """
  • sage/libs/pari/gen.pyx

    diff --git a/sage/libs/pari/gen.pyx b/sage/libs/pari/gen.pyx
    a b cdef class PariInstance(sage.structure.p 
    83608360            sage: v.pari()
    83618361            Traceback (most recent call last):
    83628362            ...
    8363             AttributeError: 'sage.modules.free_module_element.FreeModuleElement' object has no attribute 'pari'
     8363            AttributeError: 'sage.modules.free_module_element.FreeModuleElement_generic_dense' object has no attribute 'pari'
    83648364            sage: b = pari(list(v)); b,b.type()
    83658365            ([1.20000000000000, 3.40000000000000, 5.60000000000000], 't_VEC')
    83668366       
  • sage/libs/pari/gen_py.py

    diff --git a/sage/libs/pari/gen_py.py b/sage/libs/pari/gen_py.py
    a b def pari(x): 
    4444        sage: v.pari()
    4545        Traceback (most recent call last):
    4646        ...
    47         AttributeError: 'sage.modules.free_module_element.FreeModuleElement' object has no attribute 'pari'
     47        AttributeError: 'sage.modules.free_module_element.FreeModuleElement_generic_dense' object has no attribute 'pari'
    4848        sage: b = pari(list(v)); b,b.type()
    4949        ([1.20000000000000, 3.40000000000000, 5.60000000000000], 't_VEC')
    5050
  • new file sage/misc/sage_itertools.py

    diff --git a/sage/misc/sage_itertools.py b/sage/misc/sage_itertools.py
    new file mode 100644
    - +  
     1"""
     2Miscellaneous functions which should eventually be moved upstream into
     3Python's standard itertools module.
     4"""
     5#*****************************************************************************
     6#  Copyright (C) 2010     Nicolas M. Thiery <nthiery at users.sf.net>
     7#
     8#  Distributed under the terms of the GNU General Public License (GPL)
     9#                  http://www.gnu.org/licenses/
     10#******************************************************************************
     11
     12import itertools, heapq
     13
     14def unique_merge(*lists):
     15    """
     16    INPUT:
     17
     18     - ``lists``: sorted lists (or iterables)
     19
     20    Return an iterator over the elements of each list in ``lists``, in
     21    sorted order, with duplicates removed.
     22
     23        sage: from sage.misc.sage_itertools import unique_merge
     24        sage: list(unique_merge([1,2,2,3,4,7,9], [0,2,4], [2,5]))
     25        [0, 1, 2, 3, 4, 5, 7, 9]
     26
     27    Inspired from: http://rosettacode.org/wiki/Create_a_Sequence_of_unique_elements#Python
     28    """
     29    return (k for k,g in itertools.groupby(heapq.merge(*lists)))
     30
  • sage/misc/sage_unittest.py

    diff --git a/sage/misc/sage_unittest.py b/sage/misc/sage_unittest.py
    a b class TestSuite(object): 
    2626    In practice this calls all the methods ``._test_*`` of this
    2727    object, in alphabetic order::
    2828
    29         sage: TestSuite(ZZ).run(verbose = True)
     29        sage: TestSuite(1).run(verbose = True)
    3030        running ._test_not_implemented_methods() . . . pass
    3131        running ._test_pickling() . . . pass
    3232
    class TestSuite(object): 
    141141
    142142        We now use the ``verbose`` option::
    143143
    144             sage: TestSuite(ZZ).run(verbose = True)
     144            sage: TestSuite(1).run(verbose = True)
    145145            running ._test_not_implemented_methods() . . . pass
    146146            running ._test_pickling() . . . pass
    147147
    148148        Some tests may be skipped using the ``skip`` option::
    149149
    150             sage: TestSuite(ZZ).run(verbose = True, skip ="_test_pickling")
     150            sage: TestSuite(1).run(verbose = True, skip ="_test_pickling")
    151151            running ._test_not_implemented_methods() . . . pass
    152             sage: TestSuite(ZZ).run(verbose = True, skip =["_test_pickling"])
     152            sage: TestSuite(1).run(verbose = True, skip =["_test_pickling"])
    153153            running ._test_not_implemented_methods() . . . pass
    154154
     155        We now show (and test) some standard error reports::
     156
    155157            sage: class Blah(SageObject):
    156158            ...       def _test_a(self, tester): pass
    157159            ...       def _test_b(self, tester): tester.fail()
  • sage/modular/abvar/abvar.py

    diff --git a/sage/modular/abvar/abvar.py b/sage/modular/abvar/abvar.py
    a b class ModularAbelianVariety_abstract(Par 
    107107       
    108108       
    109109        EXAMPLES: One should not create an instance of this class, but we
    110         do so anyways here as an example.
    111        
    112         ::
     110        do so anyways here as an example::
    113111       
    114112            sage: A = sage.modular.abvar.abvar.ModularAbelianVariety_abstract((Gamma0(37),), QQ)
    115113            sage: type(A)
    116             <class 'sage.modular.abvar.abvar.ModularAbelianVariety_abstract'>
     114            <class 'sage.modular.abvar.abvar.ModularAbelianVariety_abstract_with_category'>
     115
    117116       
    118117        All hell breaks loose if you try to do anything with `A`::
    119118       
    class ModularAbelianVariety_abstract(Par 
    121120            Traceback (most recent call last):
    122121            ...
    123122            NotImplementedError: BUG -- lattice method must be defined in derived class
     123
     124
     125        All instances of this class are in the category of modular
     126        abelian varieties::
     127
     128            sage: A.category()
     129            Category of modular abelian varieties over Rational Field
     130            sage: J0(23).category()
     131            Category of modular abelian varieties over Rational Field
    124132        """
    125133        if check:
    126134            if not isinstance(groups, tuple):
    class ModularAbelianVariety_abstract(Par 
    139147            self.__isogeny_number = isogeny_number
    140148        if check and not is_Ring(base_field) and base_field.is_field():
    141149            raise TypeError, "base_field must be a field"
    142         ParentWithBase.__init__(self, base_field)
     150        ParentWithBase.__init__(self, base_field, category = ModularAbelianVarieties(base_field))
    143151
    144152    def groups(self):
    145153        r"""
    class ModularAbelianVariety_abstract(Par 
    16981706        """
    16991707        return ModularAbelianVariety(self.groups(), self.lattice(), R, check=False)
    17001708
    1701     def category(self):
    1702         """
    1703         Return the category of modular abelian varieties that contains this
    1704         modular abelian variety.
    1705        
    1706         EXAMPLES::
    1707        
    1708             sage: J0(23).category()
    1709             Category of modular abelian varieties over Rational Field
    1710         """
    1711         try:
    1712             return self.__category
    1713         except AttributeError:
    1714             C = ModularAbelianVarieties(self.base_ring())
    1715             self.__category = C
    1716             return C
    1717 
    17181709    def level(self):
    17191710        """
    17201711        Return the level of this modular abelian variety, which is an
    class ModularAbelianVariety(ModularAbeli 
    35093500            sage: A = (J0(11) * J0(37))[1]; A
    35103501            Simple abelian subvariety 37a(1,37) of dimension 1 of J0(11) x J0(37)
    35113502            sage: type(A)
    3512             <class 'sage.modular.abvar.abvar.ModularAbelianVariety'>
     3503            <class 'sage.modular.abvar.abvar.ModularAbelianVariety_with_category'>
    35133504            sage: A.lattice()
    35143505            Free module of degree 6 and rank 2 over Integer Ring
    35153506            Echelon basis matrix:
    class ModularAbelianVariety_modsym_abstr 
    35983589            sage: A.groups()
    35993590            (Congruence Subgroup Gamma0(33),)       
    36003591            sage: type(A)
    3601             <class 'sage.modular.abvar.abvar.ModularAbelianVariety_modsym'>
     3592            <class 'sage.modular.abvar.abvar.ModularAbelianVariety_modsym_with_category'>
    36023593        """
    36033594        return (self._modular_symbols().group(), )
    36043595
    class ModularAbelianVariety_modsym_abstr 
    36203611            [ 1  0  0 -1  0  0]
    36213612            [ 0  0  1  0  1 -1]       
    36223613            sage: type(A)
    3623             <class 'sage.modular.abvar.abvar.ModularAbelianVariety_modsym'>
     3614            <class 'sage.modular.abvar.abvar.ModularAbelianVariety_modsym_with_category'>
    36243615        """
    36253616        try:
    36263617            return self.__lattice
    class ModularAbelianVariety_modsym_abstr 
    38903881            sage: A.is_ambient()
    38913882            True
    38923883            sage: type(A)
    3893             <class 'sage.modular.abvar.abvar.ModularAbelianVariety_modsym'>
     3884            <class 'sage.modular.abvar.abvar.ModularAbelianVariety_modsym_with_category'>
    38943885            sage: A = ModularSymbols(43).cuspidal_subspace()[1].abelian_variety(); A
    38953886            Abelian subvariety of dimension 2 of J0(43)
    38963887            sage: A.is_ambient()
  • sage/modular/abvar/abvar_ambient_jacobian.py

    diff --git a/sage/modular/abvar/abvar_ambient_jacobian.py b/sage/modular/abvar/abvar_ambient_jacobian.py
    a b class ModAbVar_ambient_jacobian_class(Mo 
    8080            sage: A = J0(37); A
    8181            Abelian variety J0(37) of dimension 2
    8282            sage: type(A)
    83             <class 'sage.modular.abvar.abvar_ambient_jacobian.ModAbVar_ambient_jacobian_class'>
     83            <class 'sage.modular.abvar.abvar_ambient_jacobian.ModAbVar_ambient_jacobian_class_with_category'>
    8484            sage: A.group()
    8585            Congruence Subgroup Gamma0(37)
    8686        """
  • sage/modular/abvar/homology.py

    diff --git a/sage/modular/abvar/homology.py b/sage/modular/abvar/homology.py
    a b class Homology_abvar(Homology): 
    9999       
    100100            sage: H = J0(43).integral_homology()
    101101            sage: type(H)
    102             <class 'sage.modular.abvar.homology.IntegralHomology'>
     102            <class 'sage.modular.abvar.homology.IntegralHomology_with_category'>
    103103       
    104104        TESTS::
    105105       
    class IntegralHomology(Homology_abvar): 
    347347            sage: H = J0(23).integral_homology(); H
    348348            Integral Homology of Abelian variety J0(23) of dimension 2
    349349            sage: type(H)
    350             <class 'sage.modular.abvar.homology.IntegralHomology'>
     350            <class 'sage.modular.abvar.homology.IntegralHomology_with_category'>
    351351       
    352352        TESTS::
    353353       
    class Homology_over_base(Homology_abvar) 
    512512            sage: H = J0(23).homology(GF(5)); H
    513513            Homology with coefficients in Finite Field of size 5 of Abelian variety J0(23) of dimension 2
    514514            sage: type(H)
    515             <class 'sage.modular.abvar.homology.Homology_over_base'>
     515            <class 'sage.modular.abvar.homology.Homology_over_base_with_category'>
    516516       
    517517        TESTS::
    518518       
  • sage/modular/hecke/module.py

    diff --git a/sage/modular/hecke/module.py b/sage/modular/hecke/module.py
    a b import sage.rings.all 
    2121import sage.rings.arith as arith
    2222import sage.misc.misc as misc
    2323import sage.modules.module
    24 import sage.categories.all
    2524import sage.structure.factorization
    2625from sage.structure.all import Sequence
    2726import sage.matrix.matrix_space as matrix_space
    class HeckeModule_generic(sage.modules.m 
    6766    operators `T_m` for `m` not assumed to be coprime to the level, and
    6867    *anemic* Hecke modules, for which this does not hold.
    6968    """
    70     def __init__(self, base_ring, level):
     69    def __init__(self, base_ring, level, category = None):
    7170        r"""
    7271        Create a Hecke module. Not intended to be called directly.
    7372
    class HeckeModule_generic(sage.modules.m 
    7574
    7675            sage: CuspForms(Gamma0(17),2) # indirect doctest
    7776            Cuspidal subspace of dimension 1 of Modular Forms space of dimension 2 for Congruence Subgroup Gamma0(17) of weight 2 over Rational Field
     77            sage: ModularForms(3, 3).category()
     78            Category of Hecke modules over Rational Field
    7879        """
    7980        if not sage.rings.all.is_CommutativeRing(base_ring):
    8081            raise TypeError, "base_ring must be commutative ring"
    81         ParentWithGens.__init__(self, base_ring)
    82        
     82
     83        from sage.categories.hecke_modules import HeckeModules
     84        default_category = HeckeModules(base_ring)
     85        if category is None:
     86            category = default_category
     87        else:
     88            assert category.is_subcategory(default_category), "%s is not a subcategory of %s"%(category, default_category)
     89
     90        ParentWithGens.__init__(self, base_ring, category = category)
     91
    8392        level = sage.rings.all.ZZ(level)
    8493        if level <= 0:
    8594            raise ValueError, "level (=%s) must be positive"%level
    class HeckeModule_generic(sage.modules.m 
    262271            return self.__anemic_hecke_algebra
    263272        except AttributeError:
    264273            self.__anemic_hecke_algebra = algebra.AnemicHeckeAlgebra(self)
    265             return self.__anemic_hecke_algebra           
    266 
    267     def category(self):
    268         r"""
    269         Return the category to which this module belongs, i.e. the category of
    270         Hecke modules over the given base ring.
    271 
    272         EXAMPLE::
    273 
    274             sage: ModularForms(3, 3).category()
    275             Category of Hecke modules over Rational Field
    276         """
    277         return sage.categories.all.HeckeModules(self.base_ring())
     274            return self.__anemic_hecke_algebra
    278275
    279276    def character(self):
    280277        r"""
    class HeckeModule_free_module(HeckeModul 
    470467        r"""
    471468        Initialise a module.
    472469
    473         EXAMPLE::
     470        EXAMPLES::
    474471
    475             sage: sage.modular.hecke.module.HeckeModule_free_module(QQ, 12, -4)
    476             <class 'sage.modular.hecke.module.HeckeModule_free_module'>
     472            sage: M = sage.modular.hecke.module.HeckeModule_free_module(QQ, 12, -4); M
     473            <class 'sage.modular.hecke.module.HeckeModule_free_module_with_category'>
     474            sage: TestSuite(M).run(skip = ["_test_additive_associativity", "_test_an_element", "_test_element_pickling", "_test_pickling", "_test_some_elements", "_test_zero"]) # is this supposed to be an abstract parent without elements?
    477475        """
    478476        HeckeModule_generic.__init__(self, base_ring, level)
    479477        self.__weight = weight
  • sage/modular/modform/ambient.py

    diff --git a/sage/modular/modform/ambient.py b/sage/modular/modform/ambient.py
    a b quadratic. 
    1414    sage: n = ModularForms(chi,2); n
    1515    Modular Forms space of dimension 6, character [-1] and weight 2 over Rational Field
    1616    sage: type(n)
    17     <class 'sage.modular.modform.ambient_eps.ModularFormsAmbient_eps'>
     17    <class 'sage.modular.modform.ambient_eps.ModularFormsAmbient_eps_with_category'>
    1818
    1919Compute a basis::
    2020
    TESTS:: 
    5252    sage: m = ModularForms(GammaH(11,[2]), 2); m
    5353    Modular Forms space of dimension 2 for Congruence Subgroup Gamma_H(11) with H generated by [2] of weight 2 over Rational Field
    5454    sage: type(m)
    55     <class 'sage.modular.modform.ambient.ModularFormsAmbient'>
     55    <class 'sage.modular.modform.ambient.ModularFormsAmbient_with_category'>
    5656"""
    5757
    5858#########################################################################
  • sage/modular/modform/ambient_R.py

    diff --git a/sage/modular/modform/ambient_R.py b/sage/modular/modform/ambient_R.py
    a b class ModularFormsAmbient_R(ambient.Modu 
    7171
    7272            sage: C = CuspForms(7, 4, base_ring=CyclotomicField(5)) # indirect doctest
    7373            sage: type(C)
    74             <class 'sage.modular.modform.cuspidal_submodule.CuspidalSubmodule_R'>
     74            <class 'sage.modular.modform.cuspidal_submodule.CuspidalSubmodule_R_with_category'>
    7575        """
    7676        return CuspidalSubmodule_R(self)
  • sage/modular/modform/ambient_eps.py

    diff --git a/sage/modular/modform/ambient_eps.py b/sage/modular/modform/ambient_eps.py
    a b TESTS:: 
    6363    sage: m == loads(dumps(m))
    6464    True
    6565    sage: type(m)
    66     <class 'sage.modular.modform.ambient_eps.ModularFormsAmbient_eps'>
     66    <class 'sage.modular.modform.ambient_eps.ModularFormsAmbient_eps_with_category'>
    6767"""
    6868
    6969#########################################################################
    class ModularFormsAmbient_eps(ambient.Mo 
    113113            sage: m = ModularForms(DirichletGroup(11).0,3); m
    114114            Modular Forms space of dimension 3, character [zeta10] and weight 3 over Cyclotomic Field of order 10 and degree 4
    115115            sage: type(m)
    116             <class 'sage.modular.modform.ambient_eps.ModularFormsAmbient_eps'>
     116            <class 'sage.modular.modform.ambient_eps.ModularFormsAmbient_eps_with_category'>
    117117        """
    118118        if not dirichlet.is_DirichletCharacter(character):
    119119            raise TypeError, "character (=%s) must be a Dirichlet character"%character
  • sage/modular/modform/ambient_g0.py

    diff --git a/sage/modular/modform/ambient_g0.py b/sage/modular/modform/ambient_g0.py
    a b class ModularFormsAmbient_g0_Q(ambient.M 
    3939            sage: m = ModularForms(Gamma0(11),4); m
    4040            Modular Forms space of dimension 4 for Congruence Subgroup Gamma0(11) of weight 4 over Rational Field
    4141            sage: type(m)
    42             <class 'sage.modular.modform.ambient_g0.ModularFormsAmbient_g0_Q'>
     42            <class 'sage.modular.modform.ambient_g0.ModularFormsAmbient_g0_Q_with_category'>
    4343        """
    4444        ambient.ModularFormsAmbient.__init__(self, arithgroup.Gamma0(level), weight, rings.QQ)
    4545
    class ModularFormsAmbient_g0_Q(ambient.M 
    5757            sage: s = m.cuspidal_submodule(); s
    5858            Cuspidal subspace of dimension 10 of Modular Forms space of dimension 14 for Congruence Subgroup Gamma0(33) of weight 4 over Rational Field
    5959            sage: type(s)
    60             <class 'sage.modular.modform.cuspidal_submodule.CuspidalSubmodule_g0_Q'>
     60            <class 'sage.modular.modform.cuspidal_submodule.CuspidalSubmodule_g0_Q_with_category'>
    6161        """
    6262        try:
    6363            return self.__cuspidal_submodule
  • sage/modular/modform/ambient_g1.py

    diff --git a/sage/modular/modform/ambient_g1.py b/sage/modular/modform/ambient_g1.py
    a b class ModularFormsAmbient_g1_Q(ambient.M 
    5151            sage: m = ModularForms(Gamma1(100),5); m
    5252            Modular Forms space of dimension 1270 for Congruence Subgroup Gamma1(100) of weight 5 over Rational Field
    5353            sage: type(m)
    54             <class 'sage.modular.modform.ambient_g1.ModularFormsAmbient_g1_Q'>
     54            <class 'sage.modular.modform.ambient_g1.ModularFormsAmbient_g1_Q_with_category'>
    5555        """
    5656        ambient.ModularFormsAmbient.__init__(self, arithgroup.Gamma1(level), weight, rings.QQ)
    5757
  • sage/modular/modsym/ambient.py

    diff --git a/sage/modular/modsym/ambient.py b/sage/modular/modsym/ambient.py
    a b class ModularSymbolsAmbient_wtk_gamma_h( 
    32463246
    32473247            sage: M = ModularSymbols(GammaH(15,[4]),2)
    32483248            sage: M._compute_hecke_matrix_prime_power
    3249             <bound method ModularSymbolsAmbient_wtk_gamma_h._compute_hecke_matrix_prime_power of Modular Symbols space of dimension 9 for Congruence Subgroup Gamma_H(15) with H generated by [4] of weight 2 with sign 0 and over Rational Field>
     3249            <bound method ModularSymbolsAmbient_wtk_gamma_h_with_category._compute_hecke_matrix_prime_power of Modular Symbols space of dimension 9 for Congruence Subgroup Gamma_H(15) with H generated by [4] of weight 2 with sign 0 and over Rational Field>
    32503250            sage: M._compute_hecke_matrix_prime_power(1,2,3)
    32513251            Traceback (most recent call last):
    32523252            ...
  • sage/modular/modsym/boundary.py

    diff --git a/sage/modular/modsym/boundary.py b/sage/modular/modsym/boundary.py
    a b class BoundarySpace_wtk_g0(BoundarySpace 
    649649       
    650650            sage: B = ModularSymbols(Gamma0(2), 5).boundary_space()
    651651            sage: type(B)
    652             <class 'sage.modular.modsym.boundary.BoundarySpace_wtk_g0'>
     652            <class 'sage.modular.modsym.boundary.BoundarySpace_wtk_g0_with_category'>
    653653            sage: B == loads(dumps(B))
    654654            True
    655655        """
    class BoundarySpace_wtk_eps(BoundarySpac 
    12151215            sage: B = ModularSymbols(DirichletGroup(6).0, 4).boundary_space() ; B
    12161216            Boundary Modular Symbols space of level 6, weight 4, character [-1] and dimension 0 over Rational Field
    12171217            sage: type(B)
    1218             <class 'sage.modular.modsym.boundary.BoundarySpace_wtk_eps'>
     1218            <class 'sage.modular.modsym.boundary.BoundarySpace_wtk_eps_with_category'>
    12191219            sage: B == loads(dumps(B))
    12201220            True
    12211221        """           
  • sage/modular/modsym/modsym.py

    diff --git a/sage/modular/modsym/modsym.py b/sage/modular/modsym/modsym.py
    a b def ModularSymbols(group = 1, 
    278278        {}
    279279        sage: M = ModularSymbols(11,use_cache=True)
    280280        sage: sage.modular.modsym.modsym._cache
    281         {(Congruence Subgroup Gamma0(11), 2, 0, Rational Field): <weakref at ...; to 'ModularSymbolsAmbient_wt2_g0' at ...>}
     281        {(Congruence Subgroup Gamma0(11), 2, 0, Rational Field): <weakref at ...; to 'ModularSymbolsAmbient_wt2_g0_with_category' at ...>}
    282282        sage: M is ModularSymbols(11,use_cache=True)
    283283        True
    284284        sage: M is ModularSymbols(11,use_cache=False)
  • sage/modules/free_module.py

    diff --git a/sage/modules/free_module.py b/sage/modules/free_module.py
    a b Basis vectors are immutable:: 
    118118    ...
    119119    ValueError: vector is immutable; please change a copy instead (use copy())
    120120
    121 We can save and load submodules and elements::
     121Among other things, this tests that we can save and load submodules
     122and elements::
    122123
    123124    sage: M = ZZ^3
    124     sage: M == loads(M.dumps())
    125     True
     125    sage: TestSuite(M).run()
    126126    sage: W = M.span_of_basis([[1,2,3],[4,5,19]])
    127     sage: W == loads(W.dumps())
    128     True
     127    sage: TestSuite(W).run()
    129128    sage: v = W.0 + W.1
    130     sage: v == loads(v.dumps())
    131     True           
     129    sage: TestSuite(v).run()
    132130
    133131AUTHORS:
    134132
    class FreeModuleFactory(UniqueFactory): 
    317315    def create_key(self, base_ring, rank, sparse=False, inner_product_matrix=None):
    318316        """
    319317        TESTS::
    320        
     318
    321319            sage: loads(dumps(ZZ^6)) is ZZ^6
    322320            True
    323321            sage: loads(dumps(RDF^3)) is RDF^3
    324322            True
     323
     324        TODO: replace the above by ``TestSuite(...).run()``, once
     325        :meth:`_test_pickling` will test unique representation and not
     326        only equality.
    325327        """
    326328        rank = int(rank)
    327329
    class FreeModule_generic(module.Module): 
    540542       
    541543            sage: PolynomialRing(QQ,3,'x')^3
    542544            Ambient free module of rank 3 over the integral domain Multivariate Polynomial Ring in x0, x1, x2 over Rational Field
     545
     546        If ``base_ring`` is a field, then the constructed module is in
     547        the category of vector spaces over that field; otherwise it is
     548        in the category of all free modules over that ring::
     549
     550            sage: FreeModule(GF(7),3).category()
     551            Category of vector spaces over Finite Field of size 7
     552            sage: V = QQ^4; V.category()
     553            Category of vector spaces over Rational Field
     554            sage: V = GF(5)**20; V.category()
     555            Category of vector spaces over Finite Field of size 5
     556            sage: FreeModule(ZZ,3).category()
     557            Category of modules with basis over Integer Ring
     558
    543559        """
    544560        if not isinstance(base_ring, commutative_ring.CommutativeRing):
    545561            raise TypeError, "base_ring (=%s) must be a commutative ring"%base_ring
    class FreeModule_generic(module.Module): 
    549565        degree = sage.rings.integer.Integer(degree)
    550566        if degree < 0:
    551567            raise ValueError, "degree (=%s) must be nonnegative"%degree
    552        
    553         ParentWithGens.__init__(self, base_ring)     # names aren't used anywhere.
     568        from sage.categories.all import Fields, FreeModules, VectorSpaces
     569        if base_ring in Fields():
     570            category = VectorSpaces(base_ring)
     571        else:
     572            category = FreeModules(base_ring)
     573
     574        ParentWithGens.__init__(self, base_ring, category = category)     # names aren't used anywhere.
    554575        self.__uses_ambient_inner_product = True
    555576        self.__rank = rank
    556577        self.__degree = degree
    class FreeModule_generic(module.Module): 
    11911212            NotImplementedError
    11921213        """
    11931214        raise NotImplementedError
    1194      
    1195     def category(self):
    1196         """
    1197         Return the category to which this free module belongs. This is the
    1198         category of all free modules over the base ring.
    1199        
    1200         EXAMPLES::
    1201        
    1202             sage: FreeModule(GF(7),3).category()
    1203             Category of vector spaces over Finite Field of size 7
    1204         """
    1205         import sage.categories.all       
    1206         return sage.categories.all.FreeModules(self.base_ring())
    12071215
    12081216    def matrix(self):
    12091217        """
    class FreeModule_generic_field(FreeModul 
    29122920            raise ArithmeticError, "self and other must have the same ambient space"
    29132921        return V.span(self.basis() + other.basis())
    29142922
    2915     def category(self):
    2916         """
    2917         Return the category to which this vector space belongs.
    2918        
    2919         EXAMPLES::
    2920        
    2921             sage: V = QQ^4; V.category()
    2922             Category of vector spaces over Rational Field
    2923             sage: V = GF(5)**20; V.category()
    2924             Category of vector spaces over Finite Field of size 5
    2925         """
    2926         import sage.categories.all
    2927         return sage.categories.all.VectorSpaces(self.base_field())
    2928 
    29292923    def echelonized_basis_matrix(self):
    29302924        """
    29312925        Return basis matrix for self in row echelon form.
    class FreeModule_generic_field(FreeModul 
    34283422            [ 1.0  0.0 -1.0]
    34293423            [ 0.0  1.0 -1.0]
    34303424            sage: type(Q)
    3431             <class 'sage.modules.quotient_module.FreeModule_ambient_field_quotient'>
     3425            <class 'sage.modules.quotient_module.FreeModule_ambient_field_quotient_with_category'>
    34323426            sage: V([1,2,3])
    34333427            (1.0, 2.0, 3.0)
    34343428            sage: Q == V.quotient(W)
    class FreeModule_submodule_pid(FreeModul 
    54275421        User basis matrix:
    54285422        [ 1  2  3]
    54295423        [ 4  5 19]
    5430    
    5431     We can save and load submodules and elements.
    5432    
    5433     ::
    5434    
    5435         sage: loads(W.dumps()) == W
    5436         True
     5424
     5425    Generic tests, including saving and loading submodules and elements::
     5426
     5427        sage: TestSuite(W).run()
    54375428        sage: v = W.0 + W.1
    5438         sage: loads(v.dumps()) == v
    5439         True
     5429        sage: TestSuite(v).run()
    54405430    """
    54415431    def __init__(self, ambient, gens, check=True, already_echelonized=False):
    54425432        """
    class FreeModule_submodule_with_basis_fi 
    55825572        sage: vector(QQ, W.coordinates(v)) * W.basis_matrix()
    55835573        (1, 5, 9)
    55845574   
    5585     We can load and save submodules::
    5586    
    5587         sage: loads(W.dumps()) == W
    5588         True
    5589    
    5590     ::
    5591    
     5575    Generic tests, including saving and loading submodules and elements::
     5576
     5577        sage: TestSuite(W).run()
     5578
    55925579        sage: K.<x> = FractionField(PolynomialRing(QQ,'x'))
    55935580        sage: M = K^3; W = M.span_of_basis([[1,1,x]])
    5594         sage: loads(W.dumps()) == W
    5595         True
     5581        sage: TestSuite(W).run()
    55965582    """
    55975583    def __init__(self, ambient, basis, check=True,
    55985584        echelonize=False, echelonized_basis=None, already_echelonized=False):
  • sage/modules/free_quadratic_module.py

    diff --git a/sage/modules/free_quadratic_module.py b/sage/modules/free_quadratic_module.py
    a b EXAMPLES: 
    2020    sage: M = Matrix(QQ,[[2,1,0],[1,2,1],[0,1,2]])
    2121    sage: V = VectorSpace(QQ,3,inner_product_matrix=M)
    2222    sage: type(V)
    23     <class 'sage.modules.free_quadratic_module.FreeQuadraticModule_ambient_field'>
     23    <class 'sage.modules.free_quadratic_module.FreeQuadraticModule_ambient_field_with_category'>
    2424    sage: V.inner_product_matrix()
    2525    [2 1 0]
    2626    [1 2 1]
    2727    [0 1 2]
    2828    sage: W = V.subspace([[1,2,7], [1,1,0]])
    2929    sage: type(W)
    30     <class 'sage.modules.free_quadratic_module.FreeQuadraticModule_submodule_field'>
     30    <class 'sage.modules.free_quadratic_module.FreeQuadraticModule_submodule_field_with_category'>
    3131    sage: W
    3232    Quadratic space of degree 3 and dimension 2 over Rational Field
    3333    Basis matrix:
  • sage/modules/module.pyx

    diff --git a/sage/modules/module.pyx b/sage/modules/module.pyx
    a b cdef class Module(sage.structure.parent_ 
    2828#        Coerce x into the ring.
    2929#        """
    3030#        raise NotImplementedError
    31     # Should be deprecated as soon as all modules declare their
    32     # category properly at initialization
     31
    3332    def category(self):
    3433        """
    3534        Return the category to which this module belongs.
    3635        """
    37         category = sage.structure.category_object.CategoryObject.category(self)
    38         from sage.categories.all import Objects, Modules
    39         if category == Objects():
    40             return Modules(self.base_ring())
    41         else:
    42             return category
     36        # Defining a category method is deprecated for parents.
     37        # Instead, the category should be specified in the constructor.
     38        # See: http://sagetrac.org/sage_trac/wiki/CategoriesRoadMap
     39        if self._is_category_initialized():
     40            from sage.structure.parent import Parent
     41            return Parent.category(self)
     42        from sage.categories.modules import Modules
     43        return Modules(self.base_ring())
    4344
    4445    def endomorphism_ring(self):
    4546        """
  • sage/modules/quotient_module.py

    diff --git a/sage/modules/quotient_module.py b/sage/modules/quotient_module.py
    a b class FreeModule_ambient_field_quotient( 
    6666        sage: loads(dumps(U)) == U
    6767        True
    6868        sage: type(loads(dumps(U)) )
    69         <class 'sage.modules.quotient_module.FreeModule_ambient_field_quotient'>
     69        <class 'sage.modules.quotient_module.FreeModule_ambient_field_quotient_with_category'>
    7070    """
    7171    def __init__(self, domain, sub, quotient_matrix, lift_matrix, inner_product_matrix = None):
    7272        """
    class FreeModule_ambient_field_quotient( 
    8888
    8989        Behold the type of Q:
    9090            sage: type(Q)
    91             <class 'sage.modules.quotient_module.FreeModule_ambient_field_quotient'>
     91            <class 'sage.modules.quotient_module.FreeModule_ambient_field_quotient_with_category'>
    9292           
    9393        We do some consistency checks on the extra quotient and
    9494        lifting structure of Q.
    class FreeModule_ambient_field_quotient( 
    122122
    123123        Note the type:
    124124            sage: type(Q)
    125             <class 'sage.modules.quotient_module.FreeModule_ambient_field_quotient'>
     125            <class 'sage.modules.quotient_module.FreeModule_ambient_field_quotient_with_category'>
    126126
    127127        The string representation mentions that this is a quotient V/W, that the quotient
    128128        has dimension 1 and is over a finite field, and also describes V and W:
  • sage/monoids/monoid.py

    diff --git a/sage/monoids/monoid.py b/sage/monoids/monoid.py
    a b def is_Monoid(x): 
    99
    1010class Monoid_class(ParentWithGens):
    1111    def category(self):
     12        # Defining a category method is deprecated for parents.
     13        # Instead, the category should be specified in the constructor.
     14        # See: http://sagetrac.org/sage_trac/wiki/CategoriesRoadMap
     15        if self._is_category_initialized():
     16            return Parent.category(self)
     17
    1218        # Import this locally, rather than at the top level, to avoid
    1319        # a circular import chain
    1420        # (category_types -> sage.algebras.all -> sage.algebras.free_algebra ->
    1521        # sage.monoids.free_monoid -> sage.monoids.monoid ->
    1622        # sage.categories.all -> category_types)
    17         import sage.categories.all
    18         return sage.categories.all.Monoids()
     23        from sage.categories.monoids import Monoids
     24        return Monoids()
  • sage/rings/integer_ring.pyx

    diff --git a/sage/rings/integer_ring.pyx b/sage/rings/integer_ring.pyx
    a b import sage.rings.ideal 
    6969import sage.structure.factorization as factorization
    7070import sage.libs.pari.all
    7171import sage.rings.ideal
     72from sage.categories.basic import EuclideanDomains
    7273from sage.structure.parent_gens import ParentWithGens
    7374from sage.structure.parent cimport Parent
    7475
    cdef class IntegerRing_class(PrincipalId 
    117118        0
    118119        sage: Z.is_field()
    119120        False
    120    
     121
     122        sage: Z.category()
     123        Category of euclidean domains
     124
    121125    We next illustrate basic arithmetic in `\ZZ`::
    122126   
    123127        sage: a = Z(1234); b = Z(5678); print a, b
    cdef class IntegerRing_class(PrincipalId 
    194198    """
    195199
    196200    def __init__(self):
    197         ParentWithGens.__init__(self, self, ('x',), normalize=False)
     201        ParentWithGens.__init__(self, self, ('x',), normalize=False, category = EuclideanDomains())
    198202        self._populate_coercion_lists_(element_constructor=integer.Integer,
    199203                                       init_no_parent=True,
    200204                                       convert_method_name='_integer_')
  • sage/rings/number_field/number_field.py

    diff --git a/sage/rings/number_field/number_field.py b/sage/rings/number_field/number_field.py
    a b def QuadraticField(D, names, check=True, 
    660660   
    661661        sage: from sage.rings.number_field.number_field import is_NumberField
    662662        sage: type(K)
    663         <class 'sage.rings.number_field.number_field.NumberField_quadratic'>
     663        <class 'sage.rings.number_field.number_field.NumberField_quadratic_with_category'>
    664664        sage: is_NumberField(K)
    665665        True
    666666   
    def CyclotomicField(n, names=None, embed 
    766766    ::
    767767   
    768768        sage: type(k)
    769         <class 'sage.rings.number_field.number_field.NumberField_cyclotomic'>
     769        <class 'sage.rings.number_field.number_field.NumberField_cyclotomic_with_category'>
    770770   
    771771    We can specify a different generator name as follows.
    772772   
    class NumberField_generic(number_field_b 
    886886        True
    887887    """
    888888    def __init__(self, polynomial, name,
    889                  latex_name=None, check=True, embedding=None):
     889                 latex_name=None, check=True, embedding=None,
     890                 category = None):
    890891        """
    891892        Create a number field.
    892893       
    class NumberField_generic(number_field_b 
    913914       
    914915            sage: (a-1)*(a+1)
    915916            0
    916        
     917
     918        The constructed object is in the category of number fields::
     919
     920            sage: NumberField(x^2 + 3, 'a').category()
     921            Category of number fields
     922            sage: category(NumberField(x^2 + 3, 'a'))
     923            Category of number fields
     924       
     925        The special types of number fields, e.g., quadratic fields, do
     926        not have (yet?) their own category::
     927       
     928            sage: QuadraticField(2,'d').category()
     929            Category of number fields
     930
    917931        TESTS::
    918932       
    919933            sage: NumberField(ZZ['x'].0^4 + 23, 'a')
    class NumberField_generic(number_field_b 
    925939            ...
    926940            TypeError: polynomial must be defined over rational field
    927941        """
    928         ParentWithGens.__init__(self, QQ, name)
     942
     943        from sage.categories.number_fields import NumberFields
     944        default_category = NumberFields()
     945        if category is None:
     946            category = default_category
     947        else:
     948            assert category.is_subcategory(default_category), "%s is not a subcategory of %s"%(category, default_category)
     949
     950        ParentWithGens.__init__(self, QQ, name, category = category)
    929951        if not isinstance(polynomial, polynomial_element.Polynomial):
    930952            raise TypeError, "polynomial (=%s) must be a polynomial"%repr(polynomial)
    931953       
    class NumberField_generic(number_field_b 
    16621684        return "%s[%s]/(%s)"%(latex(QQ), self.latex_variable_name(),
    16631685                              self.polynomial()._latex_(self.latex_variable_name()))
    16641686
    1665     def category(self):
    1666         """
    1667         Return the category of number fields.
    1668        
    1669         EXAMPLES::
    1670        
    1671             sage: NumberField(x^2 + 3, 'a').category()
    1672             Category of number fields
    1673             sage: category(NumberField(x^2 + 3, 'a'))
    1674             Category of number fields
    1675        
    1676         The special types of number fields, e.g., quadratic fields, don't
    1677         have their own category::
    1678        
    1679             sage: QuadraticField(2,'d').category()
    1680             Category of number fields
    1681         """
    1682         from sage.categories.number_fields import NumberFields
    1683         return NumberFields()
    1684 
    16851687    def __cmp__(self, other):
    16861688        """
    16871689        Compare a number field with something else.
    class NumberField_cyclotomic(NumberField 
    60966098       
    60976099            sage: k = CyclotomicField(3)
    60986100            sage: type(k)
    6099             <class 'sage.rings.number_field.number_field.NumberField_cyclotomic'>
    6100 
    6101         TESTS:
     6101            <class 'sage.rings.number_field.number_field.NumberField_cyclotomic_with_category'>
     6102
     6103        TESTS::
     6104
     6105            sage: TestSuite(k).run()
    61026106            sage: type(CyclotomicField(4).zero_element())
    61036107            <type 'sage.rings.number_field.number_field_element_quadratic.NumberFieldElement_quadratic'>
    61046108            sage: type(CyclotomicField(6).one_element())
  • sage/rings/number_field/number_field_rel.py

    diff --git a/sage/rings/number_field/number_field_rel.py b/sage/rings/number_field/number_field_rel.py
    a b class NumberField_relative(NumberField_g 
    209209            sage: W
    210210            Number Field in a with defining polynomial x^2 + 1 over its base field
    211211            sage: type(W)
    212             <class 'sage.rings.number_field.number_field_rel.NumberField_relative'>
     212            <class 'sage.rings.number_field.number_field_rel.NumberField_relative_with_category'>
    213213
    214214        Test that check=False really skips the test::
    215215
  • sage/rings/polynomial/infinite_polynomial_element.py

    diff --git a/sage/rings/polynomial/infinite_polynomial_element.py b/sage/rings/polynomial/infinite_polynomial_element.py
    a b class InfinitePolynomial_sparse(RingElem 
    335335            res = self.parent()(res)
    336336        return res
    337337
    338     def _getAttributeNames(self):
     338    def __dir__(self):
    339339        """
    340340        This method implements tab completion, see ticket #6854.
    341341
    class InfinitePolynomial_sparse(RingElem 
    370370            True
    371371
    372372        """
    373         if s=='__members__':
    374             return dir(self._p)
    375373        try:
    376374            return getattr(self._p,s)
    377375        except AttributeError:
  • sage/rings/residue_field.pyx

    diff --git a/sage/rings/residue_field.pyx b/sage/rings/residue_field.pyx
    a b This module implements residue fields fo 
    33
    44We can take the residue field of prime ideals in maximal order of number fields:
    55
    6 EXAMPLES:
     6EXAMPLES::
     7
    78    sage: K.<a> = NumberField(x^3-7)
    89    sage: P = K.ideal(29).factor()[0][0]
    910    sage: k = K.residue_field(P)
    Calculating Groebner bases over various  
    5657    sage: reduct_id = F1.factor(47)[0][0]
    5758    sage: Rf = F1.residue_field(reduct_id)
    5859    sage: type(Rf)
    59     <class 'sage.rings.residue_field.ResidueFiniteField_ext_pari'>
     60    <class 'sage.rings.residue_field.ResidueFiniteField_ext_pari_with_category'>
    6061    sage: Rf.cardinality().factor()
    6162    47^3
    6263    sage: R.<X, Y> = PolynomialRing(Rf)
    And now over a large prime field: 
    7273    sage: reduct_id = F1.prime_above(next_prime(2^42))
    7374    sage: Rf = F1.residue_field(reduct_id)
    7475    sage: type(Rf)
    75     <class 'sage.rings.residue_field.ResidueFiniteField_prime_modn'>
     76    <class 'sage.rings.residue_field.ResidueFiniteField_prime_modn_with_category'>
    7677    sage: Rf.cardinality().factor()
    7778    4398046511119
    7879    sage: S.<X, Y, Z> = PolynomialRing(Rf, order='lex')
    class ResidueField_generic(Field): 
    282283        sage: k = I.residue_field(); k
    283284        Residue field of Fractional ideal (I + 1)
    284285        sage: type(k)
    285         <class 'sage.rings.residue_field.ResidueFiniteField_prime_modn'>
     286        <class 'sage.rings.residue_field.ResidueFiniteField_prime_modn_with_category'>
    286287    """
    287288    def __init__(self, p, f, intp):
    288289        """
    class ResidueField_generic(Field): 
    291292           f -- the morphism from the order to self.
    292293           intp -- the rational prime that p lives over.
    293294
    294         EXAMPLES:
     295        EXAMPLES::
     296
    295297            sage: K.<a> = NumberField(x^3-17)
    296298            sage: P = K.ideal(29).factor()[0][0]
    297299            sage: k = K.residue_field(P) # indirect doctest
    298300            sage: F = ZZ.residue_field(17)  # indirect doctest
     301            sage: k.category()
     302            Category of fields
     303            sage: F.category()
     304            Category of fields
     305
     306        TESTS::
     307
     308            sage: TestSuite(k).run(skip = ["_test_element_pickling", "_test_pickling"]) # see #7929
     309            sage: TestSuite(F).run(skip = ["_test_element_pickling", "_test_pickling"]) # see #7929
    299310        """
    300311        self.p = p
    301312        self.f = f
    302313        lst = [ self._generic_convert_map(self.base_ring()) ]
    303314        if self.f is not None:
    304315            lst.append(f)
    305         ParentWithBase.__init__(self, GF(intp), coerce_from = lst)
     316        ParentWithBase.__init__(self, GF(intp), coerce_from = lst, category = Fields())
    306317
    307318    def ideal(self):
    308319        r"""
    class ResidueFiniteField_prime_modn(Resi 
    815826            sage: K.<i> = QuadraticField(-1)
    816827            sage: kk = ResidueField(K.factor(5)[0][0])
    817828            sage: type(kk)
    818             <class 'sage.rings.residue_field.ResidueFiniteField_prime_modn'>       
     829            <class 'sage.rings.residue_field.ResidueFiniteField_prime_modn_with_category'>
    819830        """
    820831        self.p = p # Here because we have to create a NFResidueFieldHomomorphism before calling ResidueField_generic.__init__(self,...)
    821832        if im_gen is None:
    class ResidueFiniteField_ext_pari(Residu 
    880891            sage: K.<a> = NumberField(x^3-7)
    881892            sage: P = K.ideal(923478923).factor()[0][0]
    882893            sage: type(P.residue_field())
    883             <class 'sage.rings.residue_field.ResidueFiniteField_ext_pari'>
     894            <class 'sage.rings.residue_field.ResidueFiniteField_ext_pari_with_category'>
    884895        """
    885896        FiniteField_ext_pari.__init__(self, q, name, g)
    886897        self.p = p
    class ResidueFiniteField_ext_pari(Residu 
    899910            sage: ff.<alpha> = P.residue_field(); ff
    900911            Residue field in alpha of Fractional ideal (-12*aa^2 + 189*aa - 475)
    901912            sage: type(ff)
    902             <class 'sage.rings.residue_field.ResidueFiniteField_ext_pari'>
     913            <class 'sage.rings.residue_field.ResidueFiniteField_ext_pari_with_category'>
    903914            sage: ff(alpha^2 + 1)
    904915            7521*alpha + 4131
    905916            sage: ff(17/3)
  • sage/rings/ring.pyx

    diff --git a/sage/rings/ring.pyx b/sage/rings/ring.pyx
    a b cdef class Ring(ParentWithGens): 
    280280            sage: FreeAlgebra(QQ, 3, 'x').category() # todo: use a ring which is not an algebra!
    281281            Category of rings
    282282        """
     283        # Defining a category method is deprecated for parents.
     284        # Instead, the category should be specified in the constructor.
     285        # See: http://sagetrac.org/sage_trac/wiki/CategoriesRoadMap
     286        if self._is_category_initialized():
     287            return Parent.category(self)
    283288        from sage.categories.rings import Rings
    284289        return Rings()
    285290
    cdef class CommutativeRing(Ring): 
    954959            sage: QQ['x,y'].category()
    955960            Category of commutative rings
    956961        """
     962        # Defining a category method is deprecated for parents.
     963        # Instead, the category should be specified in the constructor.
     964        # See: http://sagetrac.org/sage_trac/wiki/CategoriesRoadMap
     965        if self._is_category_initialized():
     966            return Parent.category(self)
    957967        from sage.categories.commutative_rings import CommutativeRings
    958968        return CommutativeRings()
    959969   
    cdef class Field(PrincipalIdealDomain): 
    15721582            sage: F.category()
    15731583            Category of number fields
    15741584        """
     1585        # Defining a category method is deprecated for parents.
     1586        # Instead, the category should be specified in the constructor.
     1587        # See: http://sagetrac.org/sage_trac/wiki/CategoriesRoadMap
     1588        if self._is_category_initialized():
     1589            return Parent.category(self)
    15751590        from sage.categories.fields import Fields
    15761591        return Fields()
    1577        
     1592
    15781593    def fraction_field(self):
    15791594        """
    15801595        Return the fraction field of self.
    cdef class CommutativeAlgebra(Commutativ 
    25152530    """
    25162531    Generic commutative algebra
    25172532    """
    2518     def __init__(self, base_ring, names=None, normalize=True):
     2533    def __init__(self, base_ring, names=None, normalize=True, category = None):
    25192534        r"""
    25202535        Standard init function. This just checks that the base is a commutative
    25212536        ring and then passes the buck.
    cdef class CommutativeAlgebra(Commutativ 
    25322547        """
    25332548        if not isinstance(base_ring, CommutativeRing):
    25342549            raise TypeError, "base ring must be a commutative ring"
    2535         ParentWithGens.__init__(self, base_ring, names=names, normalize=normalize)
     2550
     2551        from sage.categories.algebras import Algebras
     2552        default_category = Algebras(base_ring)
     2553        if category is None:
     2554            category = default_category
     2555        else:
     2556            assert category.is_subcategory(default_category), "%s is not a subcategory of %s"%(category, default_category)
     2557
     2558        ParentWithGens.__init__(self, base_ring, names=names, normalize=normalize, category = category)
    25362559
    25372560    def is_commutative(self):
    25382561        """
  • sage/schemes/elliptic_curves/heegner.py

    diff --git a/sage/schemes/elliptic_curves/heegner.py b/sage/schemes/elliptic_curves/heegner.py
    a b class HeegnerPoint(SageObject): 
    17801780            sage: P.quadratic_field() is P.quadratic_field()
    17811781            True
    17821782            sage: type(P.quadratic_field())
    1783             <class 'sage.rings.number_field.number_field.NumberField_quadratic'>
     1783            <class 'sage.rings.number_field.number_field.NumberField_quadratic_with_category'>
    17841784        """
    17851785        return self.ring_class_field().quadratic_field()
    17861786
  • sage/schemes/generic/affine_space.py

    diff --git a/sage/schemes/generic/affine_space.py b/sage/schemes/generic/affine_space.py
    a b class AffineSpace_generic(ambient_space. 
    121121        Spectrum of Rational Field
    122122        sage: X.base_ring()
    123123        Rational Field
     124        sage: X.category()
     125        Category of schemes over Spectrum of Rational Field
    124126        sage: X.structure_morphism ()
    125127        Scheme morphism:
    126128          From: Affine Space of dimension 3 over Rational Field
  • sage/schemes/generic/ambient_space.py

    diff --git a/sage/schemes/generic/ambient_space.py b/sage/schemes/generic/ambient_space.py
    a b class AmbientSpace(scheme.Scheme, Parent 
    5151
    5252            sage: from sage.schemes.generic.ambient_space import AmbientSpace
    5353            sage: A = AmbientSpace(5, ZZ)
     54            sage: TestSuite(A).run() # not tested (abstract scheme with no elements?)
    5455        """
    5556        if not is_CommutativeRing(R):
    5657            raise TypeError, "R (=%s) must be a commutative ring"%R
    class AmbientSpace(scheme.Scheme, Parent 
    5960            raise ValueError, "n (=%s) must be nonnegative"%n
    6061        self.__n = n
    6162        self._base_ring = R
    62        
     63        # NT: this seems to set improperly self._base_scheme to X instead of Spec(X)????
     64        # scheme.Scheme.__init__(self, R)
     65        # This should be cleaned up by someone who knows about schemes (not me!)
     66        from sage.categories.schemes import Schemes
     67        from sage.structure.parent_base import ParentWithBase
     68        ParentWithBase.__init__(self, R, category = Schemes(self.base_scheme()))
     69
    6370    #######################################################################
    6471    # Derived classes must overload all of the following functions
    6572    #######################################################################
  • sage/schemes/generic/scheme.py

    diff --git a/sage/schemes/generic/scheme.py b/sage/schemes/generic/scheme.py
    a b AUTHORS: 
    1818#                  http://www.gnu.org/licenses/
    1919#*******************************************************************************
    2020
     21from sage.misc.cachefunc import cached_method
    2122from sage.structure.parent_base import ParentWithBase
    2223from sage.rings.all import (IntegerRing, is_CommutativeRing, is_Field,
    2324                            ZZ, is_RingHomomorphism, GF, PowerSeriesRing,
    def is_Scheme(x): 
    4950# the base defaults to Spec(Z) with the canonical morphism.
    5051
    5152class Scheme(ParentWithBase):
    52     def __init__(self,X):
     53    def __init__(self, X, category = None):
    5354        """
    5455        A scheme.
    5556       
    class Scheme(ParentWithBase): 
    5960            sage: I = (x^2 - y^2)*R
    6061            sage: RmodI = R.quotient(I)
    6162            sage: X = Spec(RmodI)
    62             sage: X == loads(dumps(X))
    63             True
     63            sage: TestSuite(X).run(skip = ["_test_an_element", "_test_element_pickling", "_test_some_elements"])
     64
     65        A scheme is in the category of all schemes over the base scheme of self::
     66
     67            sage: ProjectiveSpace(4, QQ).category()
     68            Category of schemes over Spectrum of Rational Field
    6469        """
    6570        if spec.is_Spec(X):
    6671            self._base_ring = X.coordinate_ring()
    67             ParentWithBase.__init__(self, self._base_ring)
     72            base = self._base_ring
    6873        else:
    6974            self._base_scheme = X
    70             ParentWithBase.__init__(self, self._base_scheme)
     75            base = self._base_scheme
     76
     77        from sage.categories.schemes import Schemes
     78        default_category = Schemes(self.base_scheme())
     79        if category is None:
     80            category = default_category
     81        else:
     82            assert category.is_subcategory(default_category), "%s is not a subcategory of %s"%(category, default_category)
     83
     84        ParentWithBase.__init__(self, base, category = category)
    7185
    7286    def __cmp__(self, X):
    7387        """
    class Scheme(ParentWithBase): 
    363377
    364378    structure_morphism = base_morphism
    365379
    366     def category(self):
    367         """
    368         Return the category to which this scheme belongs. This is the
    369         category of all schemes over the base scheme of self.
    370        
    371         EXAMPLES::
    372        
    373             sage: ProjectiveSpace(4, QQ).category()
    374             Category of schemes over Spectrum of Rational Field
    375         """
    376         from sage.categories.schemes import Schemes
    377         return Schemes(self.base_scheme())
    378 
    379380    def coordinate_ring(self):
    380381        """
    381382        Return the coordinate ring of this scheme, if defined. Otherwise
  • sage/schemes/jacobians/abstract_jacobian.py

    diff --git a/sage/schemes/jacobians/abstract_jacobian.py b/sage/schemes/jacobians/abstract_jacobian.py
    a b class Jacobian_generic(Scheme): 
    7171            sage: J = Jacobian_generic(C); J
    7272            Jacobian of Projective Curve over Rational Field defined by x^3 + y^3 + z^3           
    7373            sage: type(J)
    74             <class 'sage.schemes.jacobians.abstract_jacobian.Jacobian_generic'>
    75             sage: J == loads(dumps(J))
    76             True
     74            <class 'sage.schemes.jacobians.abstract_jacobian.Jacobian_generic_with_category'>
     75
     76        Note: this is an abstract parent, so we skip element tests::
     77
     78            sage: TestSuite(J).run(skip =["_test_an_element", "_test_element_pickling", "_test_some_elements"])
    7779
    7880        ::
    7981
  • sage/structure/category_object.pyx

    diff --git a/sage/structure/category_object.pyx b/sage/structure/category_object.pyx
    a b cdef class CategoryObject(sage_object.Sa 
    151151                category = JoinCategory(category)
    152152        self._category = category
    153153
     154    def _is_category_initialized(self):
     155        return self._category is not None
     156
    154157    def category(self):
    155158        if self._category is None:
    156159            # COERCE TODO: we shouldn't need this
  • sage/structure/element.pyx

    diff --git a/sage/structure/element.pyx b/sage/structure/element.pyx
    a b import sage.misc.sageinspect as sageinsp 
    185185cdef MethodType
    186186from types import MethodType
    187187
     188from sage.categories.sets_cat   import Sets
    188189from sage.structure.parent      cimport Parent
    189190
    190191# This classes uses element.pxd.  To add data members, you
    cdef class Element(sage_object.SageObjec 
    260261    def _make_new_with_parent_c(self, Parent parent):
    261262        self._parent = parent
    262263        return self
    263    
     264
     265
     266    def __getattr__(self, name):
     267        """
     268        Let cat be the category of the parent of ``self``.  This
     269        method emulates ``self`` being an instance of both ``Element``
     270        and ``cat.element_class``, in that order, for attribute
     271        lookup.
     272
     273        EXAMPLES:
     274
     275        We test that ``1`` (an instance of the extension type
     276        ``Integer``) inherits the methods from the categories of
     277        ``ZZ``, that is from ``CommutativeRings().element_class``::
     278
     279            sage: 1.is_idempotent(), 2.is_idempotent()
     280            (True, False)
     281
     282        This method is actually provided by the ``Semigroups()`` super
     283        category of ``CommutativeRings()``::
     284
     285            sage: 1.is_idempotent
     286            <bound method EuclideanDomains.element_class.is_idempotent of 1>
     287            sage: 1.is_idempotent.__module__
     288            'sage.categories.semigroups'
     289
     290        TESTS::
     291
     292            sage: 1.blah_blah
     293            Traceback (most recent call last):
     294            ...
     295            AttributeError: 'sage.rings.integer.Integer' object has no attribute 'blah_blah'
     296            sage: Semigroups().example().an_element().is_idempotent
     297            <bound method LeftZeroSemigroup_with_category.element_class.is_idempotent of 42>
     298            sage: Semigroups().example().an_element().blah_blah
     299            Traceback (most recent call last):
     300            ...
     301            AttributeError: 'LeftZeroSemigroup_with_category.element_class' object has no attribute 'blah_blah'
     302        """
     303        from sage.structure.parent import getattr_from_other_class
     304        return getattr_from_other_class(self, self.parent().category().element_class, name)
     305
     306    def __dir__(self):
     307        """
     308        Let cat be the category of the parent of ``self``. This method
     309        emulates ``self`` being an instance of both ``Element`` and
     310        ``cat.element_class``, in that order, for attribute directory.
     311
     312        EXAMPLES::
     313
     314            sage: dir(1/2)
     315            ['__abs__', ..., 'is_idempotent', 'is_integral', ...]
     316
     317        Caveat: dir on Integer's and some other extension types seem to ignore __dir__::
     318
     319            sage: 1.__dir__()
     320            ['__abs__', ..., 'is_idempotent', 'is_integral', ...]
     321            sage: dir(1)         # todo: not implemented
     322            ['__abs__', ..., 'is_idempotent', 'is_integral', ...]
     323        """
     324        from sage.structure.parent import dir_with_other_class
     325        return dir_with_other_class(self, self.parent().category().element_class)
     326
    264327    def _repr_(self):
    265328        return "Generic element of a structure"
    266329
  • sage/structure/parent.pyx

    diff --git a/sage/structure/parent.pyx b/sage/structure/parent.pyx
    a b cimport sage.categories.map as map 
    7373from sage.misc.lazy_attribute import lazy_attribute
    7474from sage.categories.sets_cat import Sets
    7575from copy import copy
     76from sage.misc.sage_itertools import unique_merge
    7677
    7778cdef int bad_parent_warnings = 0
    7879cdef int unique_parent_warnings = 0
    def is_extension_type(cls): 
    143144    # Robert B claims that this should be robust
    144145    return hasattr(cls, "__dictoffset__") and cls.__dictoffset__ == 0
    145146
     147class A(object):
     148    pass
     149methodwrapper = type(A.__call__)
     150
     151def raise_attribute_error(self, name):
     152    """
     153    Tries to emulate the standard Python AttributeError exception
     154
     155    EXAMPLES::
     156
     157        sage: sage.structure.parent.raise_attribute_error(1, "bla")
     158        Traceback (most recent call last):
     159        ...
     160        AttributeError: 'sage.rings.integer.Integer' object has no attribute 'bla'
     161        sage: sage.structure.parent.raise_attribute_error(QQ[x].gen(), "bla")
     162        Traceback (most recent call last):
     163        ...
     164        AttributeError: 'Polynomial_rational_dense' object has no attribute 'bla'
     165    """
     166    cls = type(self)
     167    if is_extension_type(cls):
     168        raise AttributeError, "'%s.%s' object has no attribute '%s'"%(cls.__module__, cls.__name__, name)
     169    else:
     170        raise AttributeError, "'%s' object has no attribute '%s'"%(cls.__name__, name)
     171
     172def getattr_from_other_class(self, cls, name):
     173    """
     174    INPUT::
     175
     176     - ``self``: some object
     177     - ``cls``: a class
     178     - ``name``: a string
     179
     180    Emulates ``getattr(self, name)``, as if self was an instance of ``cls``.
     181
     182    If self is an instance of cls, raises an ``AttributeError``, to
     183    avoid a double lookup. This function is intended to be called from
     184    __getattr__, and so should not be called if name is an attribute
     185    of self.
     186
     187    TODO: lookup if such a function readilly exists in Python, and if
     188    not triple check this specs and make this implementation
     189    rock-solid.
     190
     191    Caveat: this is pretty hacky, does not handle caching. There is no
     192    guarantee of robustness with super calls and lazy attributes, ...
     193
     194    EXAMPLES::
     195
     196        sage: from sage.structure.parent import getattr_from_other_class
     197        sage: class A(object):
     198        ...        def inc(self):
     199        ...            return self + 1
     200        ...        @lazy_attribute
     201        ...        def lazy_attribute(self):
     202        ...            return repr(self)
     203        sage: getattr_from_other_class(1, A, "inc")
     204        <bound method A.inc of 1>
     205        sage: getattr_from_other_class(1, A, "inc")()
     206        2
     207
     208    Caveat: lazy attributes don't work currently with extension types,
     209    with or without a __dict__:
     210
     211        sage: getattr_from_other_class(1, A, "lazy_attribute")
     212        Traceback (most recent call last):
     213        ...
     214        AttributeError: 'sage.rings.integer.Integer' object has no attribute 'lazy_attribute'
     215        sage: getattr_from_other_class(ZZ, A, "lazy_attribute")
     216        Traceback (most recent call last):
     217        ...
     218        AttributeError: 'sage.rings.integer_ring.IntegerRing_class' object has no attribute 'lazy_attribute'
     219        sage: getattr_from_other_class(QQ[x].one(), A, "lazy_attribute")
     220        '1'
     221
     222    Caveat: When __call__ is not defined for instances, using
     223    A.__call__ gives the method __call__ of the class. We use a
     224    workaround but there is no guarantee for robustness.
     225
     226        sage: getattr_from_other_class(1, A, "__call__")
     227        Traceback (most recent call last):
     228        ...
     229        AttributeError: 'sage.rings.integer.Integer' object has no attribute '__call__'
     230    """
     231    if isinstance(self, cls):
     232        raise_attribute_error(self, name)
     233    try:
     234        attribute = getattr(cls, name)
     235    except AttributeError:
     236        raise_attribute_error(self, name)
     237    if isinstance(attribute, methodwrapper):
     238        raise_attribute_error(self, name)
     239    if isinstance(attribute, lazy_attribute):
     240        # Conditionally defined lazy_attributes don't work well with fake subclasses
     241        # (a TypeError is raised if the lazy attribute is not defined)
     242        # For the moment, we ignore that when this occurs
     243        try:
     244            return attribute.__get__(self, cls)
     245        except TypeError:
     246            raise_attribute_error(self, name)
     247    if hasattr(attribute, "__get__"):
     248        return attribute.__get__(self, cls)
     249    else:
     250        return attribute
     251
     252def dir_with_other_class(self, cls):
     253    """
     254    Emulates ``dir(self)``, as if self was also an instance ``cls``,
     255    right after ``caller_class`` in the method resolution order
     256    (``self.__class__.mro()``)
     257
     258    EXAMPLES::
     259
     260        sage: class A(object):
     261        ...      a = 1
     262        ...      b = 2
     263        ...      c = 3
     264        sage: class B(object):
     265        ...      b = 2
     266        ...      c = 3
     267        ...      d = 4
     268        sage: x = A()
     269        sage: x.c = 1; x.e = 1
     270        sage: sage.structure.parent.dir_with_other_class(x, B)
     271        [..., 'a', 'b', 'c', 'd', 'e']
     272
     273
     274    """
     275    # This tries to emulate the standard dir function
     276    # Is there a better way to call dir on self, while ignoring this
     277    # __dir__? Using dir(super(A, self)) does not work since the
     278    # attributes coming from subclasses of A will be ignored
     279    iterator = unique_merge(self.__dict__.keys(), dir(self.__class__))
     280    if not isinstance(self, cls):
     281        iterator = unique_merge(iterator, dir(cls))
     282    return list(iterator)
     283
     284
    146285###############################################################################
    147286#   Sage: System for Algebra and Geometry Experimentation   
    148287#       Copyright (C) 2009 Robert Bradshaw <robertwb@math.washington.edu>
    cdef class Parent(category_object.Catego 
    362501        EXAMPLES::
    363502
    364503            sage: ZZ.categories()
    365             [Category of commutative rings,
     504            [Category of euclidean domains,
     505             Category of principal ideal domains,
     506             Category of gcd domains,
     507             Category of integral domains,
     508             Category of commutative rings,
     509             Category of domains,
    366510             Category of rings,
    367511             Category of rngs,
    368512             Category of commutative additive groups,
    cdef class Parent(category_object.Catego 
    390534            self._convert_from_list = []
    391535            self._convert_from_hash = {}
    392536            self._embedding = None
    393            
     537
     538    def __getattr__(self, name):
     539        """
     540        Let cat be the category of ``self``. This method emulates
     541        ``self`` being an instance of both ``Parent`` and
     542        ``cat.parent_class``, in that order, for attribute lookup.
     543
     544        EXAMPLES:
     545
     546        We test that ZZ (an extension type) inherits the methods from
     547        its categories, that is from ``EuclideanDomains().parent_class``::
     548
     549            sage: ZZ._test_associativity
     550            <bound method EuclideanDomains.parent_class._test_associativity of Integer Ring>
     551            sage: ZZ._test_associativity(verbose = True)
     552            sage: TestSuite(ZZ).run(verbose = True)
     553            running ._test_additive_associativity() . . . pass
     554            running ._test_an_element() . . . pass
     555            running ._test_associativity() . . . pass
     556            running ._test_element_pickling() . . . pass
     557            running ._test_not_implemented_methods() . . . pass
     558            running ._test_one() . . . pass
     559            running ._test_pickling() . . . pass
     560            running ._test_prod() . . . pass
     561            running ._test_some_elements() . . . pass
     562            running ._test_zero() . . . pass
     563
     564            sage: Sets().example().sadfasdf
     565            Traceback (most recent call last):
     566            ...
     567            AttributeError: 'PrimeNumbers_with_category' object has no attribute 'sadfasdf'
     568        """
     569        if self._is_category_initialized():
     570            return getattr_from_other_class(self, self.category().parent_class, name)
     571        else:
     572            raise_attribute_error(self, name)
     573
     574    def __dir__(self):
     575        """
     576        Let cat be the category of ``self``. This method emulates
     577        ``self`` being an instance of both ``Parent`` and
     578        ``cat.parent_class``, in that order, for attribute directory.
     579
     580        EXAMPLES::
     581
     582            sage: [s for s in dir(ZZ) if s[:6] == "_test_"]
     583            ['_test_additive_associativity',
     584             '_test_an_element',
     585             '_test_associativity',
     586             '_test_element_pickling',
     587             '_test_not_implemented_methods',
     588             '_test_one',
     589             '_test_pickling',
     590             '_test_prod',
     591             '_test_some_elements',
     592             '_test_zero']
     593        """
     594        return dir_with_other_class(self, self.category().parent_class)
     595
    394596    def _introspect_coerce(self):
    395597        """
    396598        Used for debugging the coercion model.
  • sage/structure/parent_old.pyx

    diff --git a/sage/structure/parent_old.pyx b/sage/structure/parent_old.pyx
    a b cdef class Parent(parent.Parent): 
    7777        self._has_coerce_map_from = {}
    7878        if category is not None:
    7979            self._init_category_(category)
    80         else:
    81             # Do not use sage.categories.all here to avoid initialization loop
    82             # See e-mail on sage-combinat-devel by S. Labbe, 15 Jan 2009 17:14:37
    83             from sage.categories.sets_cat import Sets
    84             self._category = Sets()
    8580
    8681    cdef int init_coerce(self, bint warn=False) except -1:
    8782        parent.Parent.init_coerce(self, warn)
    cdef class Parent(parent.Parent): 
    405400        sage: DirichletGroup(3).list()
    406401        [[1], [-1]]
    407402        sage: K = GF(7^6,'a')
    408         sage: K.list()[:10]
     403        sage: K.list()[:10] # long time
    409404        [0, 1, 2, 3, 4, 5, 6, a, a + 1, a + 2]
    410405        sage: K.<a> = GF(4)
    411406        sage: K.list()
  • sage/structure/sage_object.pyx

    diff --git a/sage/structure/sage_object.pyx b/sage/structure/sage_object.pyx
    a b cdef class SageObject: 
    221221        Checks that all required methods for this object are implemented
    222222
    223223        TESTS::
    224            
     224
    225225            sage: class Abstract(SageObject):
    226226            ...       @abstract_method
    227227            ...       def bla(self):
    cdef class SageObject: 
    240240            AssertionError: Not implemented method: bla
    241241
    242242        """
    243         from sage.misc.abstract_method import AbstractMethod
    244243        tester = self._tester(**options)
    245244        for name in dir(self):
    246             # This tries to reduce the occasions to trigger the
    247             # calculation of a lazy attribute
    248             # This won't work for classes using the getattr trick
    249             # to pseudo inherit from category
    250             if hasattr(self.__class__, name):
    251                 f = getattr(self.__class__, name)
    252                 if not isinstance(f, AbstractMethod):
    253                     continue
    254245            try:
    255                 # self.name may have been set explicitly in self.__dict__
    256246                getattr(self, name)
    257             except AttributeError:
     247            except NotImplementedError:
     248                # It would be best to make sure that this NotImplementedError was triggered by AbstractMethod
     249                tester.fail("Not implemented method: %s"%name)
     250            except:
    258251                pass
    259             except NotImplementedError:
    260                 tester.fail("Not implemented method: %s"%name)
    261252
    262253    def _test_pickling(self, **options):
    263254        """