# HG changeset patch
# User Jean-Pierre Flori <jean-pierre.flori@ssi.gouv.fr>
# Date 1328873427 -3600
# Node ID 25f1f8fd58bad620faf9f4351f8d6e48eb4fbef8
# Parent e602d29f510d92e2cf84ffa859930ad8929143dc
#12357: Reviewer patch
diff --git a/sage/categories/groupoid.pyx b/sage/categories/groupoid.pyx
a
|
b
|
|
35 | 35 | def __classcall__(cls, S): |
36 | 36 | """ |
37 | 37 | In contrast to usual instances of |
38 | | :class:`~sage.structure.unique_representation.UniqueRepresentation`, |
39 | | the cache is implemented in the given argument. |
40 | | |
| 38 | :class:`~sage.structure.unique_representation.UniqueRepresentation` |
| 39 | for which :meth:`__classcall__` is a |
| 40 | :class:`~sage.misc.cachefunc.cached_function`, |
| 41 | here the cache is implemented in the given argument. |
| 42 | |
41 | 43 | In that way, no "external" strong references to the groupoid are created |
42 | 44 | by caching -- there only is a reference from ``Groupoid(G)`` to ``G`` |
43 | | and from ``G`` to ``Groupoid(G)``, but Python's garbage collection can |
| 45 | and from ``G`` to ``Groupoid(G)``, and Python's garbage collection can |
44 | 46 | easily deal with those circular references. |
45 | 47 | |
46 | 48 | EXAMPLES:: |
… |
… |
|
73 | 75 | sage: Groupoid(1) |
74 | 76 | Traceback (most recent call last): |
75 | 77 | ... |
76 | | TypeError: 1 must either allow attribute assignment or be instances of <type 'sage.structure.parent.Parent'> |
| 78 | TypeError: 1 must either allow attribute assignment or be an instance of <type 'sage.structure.parent.Parent'> |
77 | 79 | sage: class A: pass |
78 | 80 | sage: a = A() |
79 | 81 | sage: Groupoid(a) |
… |
… |
|
82 | 84 | True |
83 | 85 | |
84 | 86 | """ |
| 87 | # First try the cache |
85 | 88 | try: |
86 | 89 | return getattr(S, '_cached_'+cls.__name__) |
87 | 90 | except AttributeError: |
88 | 91 | pass |
89 | | cdef Parent G |
90 | | cdef dict D |
| 92 | |
91 | 93 | if S is None: |
92 | 94 | raise TypeError, "Groupoid of None is not defined" |
93 | 95 | |
| 96 | # Make sure pickling works |
| 97 | # Copied from UniqueRepresentation.__classcall__ |
94 | 98 | instance = type.__call__(cls, S) |
95 | 99 | assert(isinstance(instance,cls)) |
96 | 100 | if instance.__class__.__reduce__ == UniqueRepresentation.__reduce__: |
97 | 101 | instance._reduction = (cls, (S,), {}) |
| 102 | |
| 103 | # Now try to store the Groupoid as an attribute |
98 | 104 | try: |
99 | 105 | setattr(S, '_cached_'+cls.__name__, instance) |
100 | 106 | return instance |
101 | 107 | except AttributeError: |
102 | 108 | pass |
103 | | if S is not None: |
104 | | try: |
105 | | # Parents have a cpdef dict __cached_methods attribute, by #11115 |
106 | | G = S |
107 | | if G is None: |
108 | | raise ValueError |
109 | | D = G.__cached_methods |
110 | | if D is None: |
111 | | D = G.__cached_methods = {} |
112 | | D['_cached_'+cls.__name__] = instance |
113 | | return instance |
114 | | except TypeError: |
115 | | pass |
116 | | raise TypeError, "%s must either allow attribute assignment or be instances of %s"%(S, Parent) |
| 109 | |
| 110 | # Last try: S should be a Parent |
| 111 | cdef Parent G |
| 112 | cdef dict D |
| 113 | try: |
| 114 | # Parents have a cpdef dict __cached_methods attribute, by #11115 |
| 115 | G = S |
| 116 | if G is None: |
| 117 | raise ValueError |
| 118 | D = G.__cached_methods |
| 119 | if D is None: |
| 120 | D = G.__cached_methods = {} |
| 121 | D['_cached_'+cls.__name__] = instance |
| 122 | return instance |
| 123 | except TypeError: |
| 124 | pass |
| 125 | raise TypeError, "%s must either allow attribute assignment or be an instance of %s"%(S, Parent) |
117 | 126 | |
118 | 127 | def __init__(self, G = None): |
119 | 128 | """ |