1 | # -*- coding: utf-8 -*- |
---|
2 | |
---|
3 | # This file was generated by 'sage-doctest' from |
---|
4 | # '/scratch/sking/sage-5.4.beta0/devel/sage-main/sage/misc/cachefunc.pyx'. |
---|
5 | |
---|
6 | from sage.all_cmdline import *; |
---|
7 | import sage.plot.plot; sage.plot.plot.DOCTEST_MODE=True |
---|
8 | |
---|
9 | def warning_function(f): |
---|
10 | import warnings |
---|
11 | |
---|
12 | def doctest_showwarning(message, category, filename, lineno, file=f, line=None): |
---|
13 | try: |
---|
14 | file.write(warnings.formatwarning(message, category, 'doctest', lineno, line)) |
---|
15 | except IOError: |
---|
16 | pass # the file (probably stdout) is invalid |
---|
17 | return doctest_showwarning |
---|
18 | |
---|
19 | def change_warning_output(file): |
---|
20 | import warnings |
---|
21 | warnings.showwarning = warning_function(file) |
---|
22 | |
---|
23 | import re |
---|
24 | float_pattern = re.compile('[+-]?((\d*\.?\d+)|(\d+\.?))([eE][+-]?\d+)?') |
---|
25 | |
---|
26 | def check_with_tolerance(expected, actual, epsilon, rel_or_abs=None): |
---|
27 | if actual is Exception: |
---|
28 | return # error computing actual |
---|
29 | else: |
---|
30 | actual = str(actual) |
---|
31 | expected = re.sub('\n +', '\n', expected) |
---|
32 | actual = re.sub('\n +', '\n', actual) |
---|
33 | assert float_pattern.sub('#', expected.strip()) == float_pattern.sub('#', actual.strip()), \ |
---|
34 | "Expected '" + expected + "' got '" + actual + "'" |
---|
35 | for expected_value, actual_value in zip(float_pattern.finditer(expected), float_pattern.finditer(actual)): |
---|
36 | expected_value = float(expected_value.group()) |
---|
37 | actual_value = float(actual_value.group()) |
---|
38 | if rel_or_abs == 'abs' or expected_value == 0: |
---|
39 | assert abs(expected_value - actual_value) < epsilon, "Out of tolerance %s vs %s" % (expected_value, actual_value) |
---|
40 | else: |
---|
41 | assert abs((expected_value - actual_value) / expected_value) < epsilon, "Out of tolerance %s vs %s" % (expected_value, actual_value) |
---|
42 | def example_0(): r""">>> set_random_seed(0L) |
---|
43 | |
---|
44 | >>> change_warning_output(sys.stdout) |
---|
45 | |
---|
46 | |
---|
47 | Cached Functions and Methods |
---|
48 | |
---|
49 | AUTHORS: |
---|
50 | |
---|
51 | - William Stein (inspired by conversation with Justin Walker). |
---|
52 | - Mike Hansen (added doctests and made it work with class methods). |
---|
53 | - Willem Jan Palenstijn (add CachedMethodCaller for binding cached |
---|
54 | methods to instances). |
---|
55 | - Tom Boothby (added DiskCachedFunction). |
---|
56 | - Simon King (improved performance, more doctests, cython version, |
---|
57 | added CachedMethodCallerNoArgs). |
---|
58 | |
---|
59 | EXAMPLES: |
---|
60 | |
---|
61 | By trac ticket #11115, cached functions and methods are now also |
---|
62 | available in Cython code. The following examples cover various ways |
---|
63 | of usage. |
---|
64 | |
---|
65 | Python functions:: |
---|
66 | |
---|
67 | >>> @cached_function###line 22:_sage_ >>> @cached_function |
---|
68 | ... def test_pfunc(x): |
---|
69 | ... ''' |
---|
70 | ... Some documentation |
---|
71 | ... ''' |
---|
72 | ... return -x |
---|
73 | ... |
---|
74 | >>> test_pfunc(Integer(5)) is test_pfunc(Integer(5))###line 29:_sage_ >>> test_pfunc(5) is test_pfunc(5) |
---|
75 | True |
---|
76 | |
---|
77 | Unfortunately, cython functions do not allow arbitrary |
---|
78 | decorators. However, one can wrap a Cython function and |
---|
79 | turn it into a cached function, by trac ticket #11115. |
---|
80 | We need to provide the name that the wrapped method or |
---|
81 | function should have, since otherwise the name of the |
---|
82 | original function would be used:: |
---|
83 | |
---|
84 | >>> cython('''cpdef test_funct(x): return -x''')###line 39:_sage_ >>> cython('''cpdef test_funct(x): return -x''') |
---|
85 | >>> wrapped_funct = cached_function(test_funct, name='wrapped_funct')###line 40:_sage_ >>> wrapped_funct = cached_function(test_funct, name='wrapped_funct') |
---|
86 | >>> wrapped_funct###line 41:_sage_ >>> wrapped_funct |
---|
87 | Cached version of <built-in function test_funct> |
---|
88 | >>> wrapped_funct.__name__###line 43:_sage_ >>> wrapped_funct.__name__ |
---|
89 | 'wrapped_funct' |
---|
90 | >>> wrapped_funct(Integer(5))###line 45:_sage_ >>> wrapped_funct(5) |
---|
91 | -5 |
---|
92 | >>> wrapped_funct(Integer(5)) is wrapped_funct(Integer(5))###line 47:_sage_ >>> wrapped_funct(5) is wrapped_funct(5) |
---|
93 | True |
---|
94 | |
---|
95 | We can proceed similarly for cached methods of Cython classes, |
---|
96 | provided that they allow attribute assignment or have a public |
---|
97 | attribute ``__cached_methods`` of type ``<dict>``. Since trac ticket |
---|
98 | #11115, this is the case for all classes inheriting from |
---|
99 | :class:`~sage.structure.parent.Parent`:: |
---|
100 | |
---|
101 | >>> cython_code = ['cpdef test_meth(self,x):',###line 56:_sage_ >>> cython_code = ['cpdef test_meth(self,x):', |
---|
102 | ... ' "some doc for a wrapped cython method"', |
---|
103 | ... ' return -x', |
---|
104 | ... 'from sage.all import cached_method', |
---|
105 | ... 'from sage.structure.parent cimport Parent', |
---|
106 | ... 'cdef class MyClass(Parent):', |
---|
107 | ... ' wrapped_method = cached_method(test_meth,name="wrapped_method")'] |
---|
108 | >>> cython('\n'.join(cython_code))###line 63:_sage_ >>> cython('\n'.join(cython_code)) |
---|
109 | >>> O = MyClass()###line 64:_sage_ >>> O = MyClass() |
---|
110 | >>> O.wrapped_method###line 65:_sage_ >>> O.wrapped_method |
---|
111 | Cached version of <built-in function test_meth> |
---|
112 | >>> O.wrapped_method.__name__###line 67:_sage_ >>> O.wrapped_method.__name__ |
---|
113 | 'wrapped_method' |
---|
114 | >>> O.wrapped_method(Integer(5))###line 69:_sage_ >>> O.wrapped_method(5) |
---|
115 | -5 |
---|
116 | >>> O.wrapped_method(Integer(5)) is O.wrapped_method(Integer(5))###line 71:_sage_ >>> O.wrapped_method(5) is O.wrapped_method(5) |
---|
117 | True |
---|
118 | |
---|
119 | By trac ticket #11115, even if a parent does not allow attribute |
---|
120 | assignment, it can inherit a cached method from the parent class of a |
---|
121 | category (previously, the cache would have been broken):: |
---|
122 | |
---|
123 | >>> cython_code = ["from sage.all import cached_method, cached_in_parent_method, Category, Objects",###line 78:_sage_ >>> cython_code = ["from sage.all import cached_method, cached_in_parent_method, Category, Objects", |
---|
124 | ... "class MyCategory(Category):", |
---|
125 | ... " @cached_method", |
---|
126 | ... " def super_categories(self):", |
---|
127 | ... " return [Objects()]", |
---|
128 | ... " class ElementMethods:", |
---|
129 | ... " @cached_method", |
---|
130 | ... " def element_cache_test(self):", |
---|
131 | ... " return -self", |
---|
132 | ... " @cached_in_parent_method", |
---|
133 | ... " def element_via_parent_test(self):", |
---|
134 | ... " return -self", |
---|
135 | ... " class ParentMethods:", |
---|
136 | ... " @cached_method", |
---|
137 | ... " def one(self):", |
---|
138 | ... " return self.element_class(self,1)", |
---|
139 | ... " @cached_method", |
---|
140 | ... " def invert(self, x):", |
---|
141 | ... " return -x"] |
---|
142 | >>> cython('\n'.join(cython_code))###line 97:_sage_ >>> cython('\n'.join(cython_code)) |
---|
143 | >>> C = MyCategory()###line 98:_sage_ >>> C = MyCategory() |
---|
144 | |
---|
145 | In order to keep the memory footprint of elements small, it was |
---|
146 | decided to not support the same freedom of using cached methods |
---|
147 | for elements: If an instance of a class derived from |
---|
148 | :class:`~sage.structure.element.Element` does not allow attribute |
---|
149 | assignment, then a cached method inherited from the category of |
---|
150 | its parent will break, as in the class ``MyBrokenElement`` below. |
---|
151 | |
---|
152 | However, there is a class :class:`~sage.structure.element.ElementWithCachedMethod` |
---|
153 | that has generally a slower attribute access, but fully supports |
---|
154 | cached methods. We remark, however, that cached methods are |
---|
155 | *much* faster if attribute access works. So, we expect that |
---|
156 | :class:`~sage.structure.element.ElementWithCachedMethod` will |
---|
157 | hardly by used. |
---|
158 | :: |
---|
159 | |
---|
160 | >>> cython_code = ["from sage.structure.element cimport Element, ElementWithCachedMethod",###line 115:_sage_ >>> cython_code = ["from sage.structure.element cimport Element, ElementWithCachedMethod", |
---|
161 | ... "cdef class MyBrokenElement(Element):", |
---|
162 | ... " cdef public object x", |
---|
163 | ... " def __init__(self,P,x):", |
---|
164 | ... " self.x=x", |
---|
165 | ... " Element.__init__(self,P)", |
---|
166 | ... " def __neg__(self):", |
---|
167 | ... " return MyBrokenElement(self.parent(),-self.x)", |
---|
168 | ... " def _repr_(self):", |
---|
169 | ... " return '<%s>'%self.x", |
---|
170 | ... " def __hash__(self):", |
---|
171 | ... " return hash(self.x)", |
---|
172 | ... " def __cmp__(left, right):", |
---|
173 | ... " return (<Element>left)._cmp(right)", |
---|
174 | ... " def __richcmp__(left, right, op):", |
---|
175 | ... " return (<Element>left)._richcmp(right,op)", |
---|
176 | ... " cdef int _cmp_c_impl(left, Element right) except -2:", |
---|
177 | ... " return cmp(left.x,right.x)", |
---|
178 | ... " def raw_test(self):", |
---|
179 | ... " return -self", |
---|
180 | ... "cdef class MyElement(ElementWithCachedMethod):", |
---|
181 | ... " cdef public object x", |
---|
182 | ... " def __init__(self,P,x):", |
---|
183 | ... " self.x=x", |
---|
184 | ... " ElementWithCachedMethod.__init__(self,P)", |
---|
185 | ... " def __neg__(self):", |
---|
186 | ... " return MyElement(self.parent(),-self.x)", |
---|
187 | ... " def _repr_(self):", |
---|
188 | ... " return '<%s>'%self.x", |
---|
189 | ... " def __hash__(self):", |
---|
190 | ... " return hash(self.x)", |
---|
191 | ... " def __cmp__(left, right):", |
---|
192 | ... " return (<Element>left)._cmp(right)", |
---|
193 | ... " def __richcmp__(left, right, op):", |
---|
194 | ... " return (<Element>left)._richcmp(right,op)", |
---|
195 | ... " cdef int _cmp_c_impl(left, Element right) except -2:", |
---|
196 | ... " return cmp(left.x,right.x)", |
---|
197 | ... " def raw_test(self):", |
---|
198 | ... " return -self", |
---|
199 | ... "from sage.structure.parent cimport Parent", |
---|
200 | ... "cdef class MyParent(Parent):", |
---|
201 | ... " Element = MyElement"] |
---|
202 | >>> cython('\n'.join(cython_code))###line 157:_sage_ >>> cython('\n'.join(cython_code)) |
---|
203 | >>> P = MyParent(category=C)###line 158:_sage_ >>> P = MyParent(category=C) |
---|
204 | >>> ebroken = MyBrokenElement(P,Integer(5))###line 159:_sage_ >>> ebroken = MyBrokenElement(P,5) |
---|
205 | >>> e = MyElement(P,Integer(5))###line 160:_sage_ >>> e = MyElement(P,5) |
---|
206 | |
---|
207 | The cached methods inherited by the parent works:: |
---|
208 | |
---|
209 | >>> P.one()###line 164:_sage_ >>> P.one() |
---|
210 | <1> |
---|
211 | >>> P.one() is P.one()###line 166:_sage_ >>> P.one() is P.one() |
---|
212 | True |
---|
213 | >>> P.invert(e)###line 168:_sage_ >>> P.invert(e) |
---|
214 | <-5> |
---|
215 | >>> P.invert(e) is P.invert(e)###line 170:_sage_ >>> P.invert(e) is P.invert(e) |
---|
216 | True |
---|
217 | |
---|
218 | The cached methods inherited by ``MyElement`` works:: |
---|
219 | |
---|
220 | >>> e.element_cache_test()###line 175:_sage_ >>> e.element_cache_test() |
---|
221 | <-5> |
---|
222 | >>> e.element_cache_test() is e.element_cache_test()###line 177:_sage_ >>> e.element_cache_test() is e.element_cache_test() |
---|
223 | True |
---|
224 | >>> e.element_via_parent_test()###line 179:_sage_ >>> e.element_via_parent_test() |
---|
225 | <-5> |
---|
226 | >>> e.element_via_parent_test() is e.element_via_parent_test()###line 181:_sage_ >>> e.element_via_parent_test() is e.element_via_parent_test() |
---|
227 | True |
---|
228 | |
---|
229 | The other element class can only inherit a ``cached_in_parent_method``, since |
---|
230 | the cache is stored in the parent. In fact, equal elements share the cache, |
---|
231 | even if they are of different types:: |
---|
232 | |
---|
233 | >>> e == ebroken###line 188:_sage_ >>> e == ebroken |
---|
234 | True |
---|
235 | >>> type(e) == type(ebroken)###line 190:_sage_ >>> type(e) == type(ebroken) |
---|
236 | False |
---|
237 | >>> ebroken.element_via_parent_test() is e.element_via_parent_test()###line 192:_sage_ >>> ebroken.element_via_parent_test() is e.element_via_parent_test() |
---|
238 | True |
---|
239 | |
---|
240 | However, the cache of the other inherited method breaks, although the method |
---|
241 | as such works:: |
---|
242 | |
---|
243 | >>> ebroken.element_cache_test()###line 198:_sage_ >>> ebroken.element_cache_test() |
---|
244 | <-5> |
---|
245 | >>> ebroken.element_cache_test() is ebroken.element_cache_test()###line 200:_sage_ >>> ebroken.element_cache_test() is ebroken.element_cache_test() |
---|
246 | False |
---|
247 | |
---|
248 | The cache can be emptied:: |
---|
249 | |
---|
250 | >>> a = test_pfunc(Integer(5))###line 205:_sage_ >>> a = test_pfunc(5) |
---|
251 | >>> test_pfunc.clear_cache()###line 206:_sage_ >>> test_pfunc.clear_cache() |
---|
252 | >>> a is test_pfunc(Integer(5))###line 207:_sage_ >>> a is test_pfunc(5) |
---|
253 | False |
---|
254 | >>> a = P.one()###line 209:_sage_ >>> a = P.one() |
---|
255 | >>> P.one.clear_cache()###line 210:_sage_ >>> P.one.clear_cache() |
---|
256 | >>> a is P.one()###line 211:_sage_ >>> a is P.one() |
---|
257 | False |
---|
258 | |
---|
259 | Since ``e`` and ``ebroken`` share the cache, when we empty it for one element |
---|
260 | it is empty for the other as well:: |
---|
261 | |
---|
262 | >>> b = ebroken.element_via_parent_test()###line 217:_sage_ >>> b = ebroken.element_via_parent_test() |
---|
263 | >>> e.element_via_parent_test.clear_cache()###line 218:_sage_ >>> e.element_via_parent_test.clear_cache() |
---|
264 | >>> b is ebroken.element_via_parent_test()###line 219:_sage_ >>> b is ebroken.element_via_parent_test() |
---|
265 | False |
---|
266 | |
---|
267 | Introspection works:: |
---|
268 | |
---|
269 | >>> from sage.misc.edit_module import file_and_line###line 224:_sage_ >>> from sage.misc.edit_module import file_and_line |
---|
270 | >>> from sage.misc.sageinspect import sage_getdoc, sage_getfile, sage_getsource###line 225:_sage_ >>> from sage.misc.sageinspect import sage_getdoc, sage_getfile, sage_getsource |
---|
271 | >>> print sage_getdoc(test_pfunc)###line 226:_sage_ >>> print sage_getdoc(test_pfunc) |
---|
272 | Some documentation |
---|
273 | >>> print sage_getdoc(O.wrapped_method)###line 228:_sage_ >>> print sage_getdoc(O.wrapped_method) |
---|
274 | some doc for a wrapped cython method |
---|
275 | <BLANKLINE> |
---|
276 | >>> print sage_getsource(O.wrapped_method)###line 231:_sage_ >>> print sage_getsource(O.wrapped_method) |
---|
277 | cpdef test_meth(self,x): |
---|
278 | "some doc for a wrapped cython method" |
---|
279 | return -x |
---|
280 | |
---|
281 | It is a very common special case to cache a method that has no |
---|
282 | arguments. In that special case, the time needed to access the cache |
---|
283 | can be drastically reduced by using a special implementation. The |
---|
284 | cached method decorator automatically determines which implementation |
---|
285 | ought to be chosen. A typical example is |
---|
286 | :meth:`sage.rings.polynomial.multi_polynomial_ideal.MPolynomialIdeal.gens` |
---|
287 | (no arguments) versus |
---|
288 | :meth:`sage.rings.polynomial.multi_polynomial_ideal.MPolynomialIdeal.groebner_basis` |
---|
289 | (several arguments):: |
---|
290 | |
---|
291 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 246:_sage_ >>> P.<a,b,c,d> = QQ[] |
---|
292 | >>> I = P*[a,b]###line 247:_sage_ >>> I = P*[a,b] |
---|
293 | >>> I.gens()###line 248:_sage_ >>> I.gens() |
---|
294 | [a, b] |
---|
295 | >>> I.gens() is I.gens()###line 250:_sage_ >>> I.gens() is I.gens() |
---|
296 | True |
---|
297 | >>> I.groebner_basis()###line 252:_sage_ >>> I.groebner_basis() |
---|
298 | [a, b] |
---|
299 | >>> I.groebner_basis() is I.groebner_basis()###line 254:_sage_ >>> I.groebner_basis() is I.groebner_basis() |
---|
300 | True |
---|
301 | >>> type(I.gens)###line 256:_sage_ >>> type(I.gens) |
---|
302 | <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'> |
---|
303 | >>> type(I.groebner_basis)###line 258:_sage_ >>> type(I.groebner_basis) |
---|
304 | <type 'sage.misc.cachefunc.CachedMethodCaller'> |
---|
305 | |
---|
306 | |
---|
307 | >>> sig_on_count() |
---|
308 | 0 |
---|
309 | """ |
---|
310 | |
---|
311 | def example_1(): r""">>> set_random_seed(0L) |
---|
312 | |
---|
313 | >>> change_warning_output(sys.stdout) |
---|
314 | |
---|
315 | |
---|
316 | Unpickling of cached functions. |
---|
317 | |
---|
318 | NOTE: |
---|
319 | |
---|
320 | Pickling and unpickling of cached functions is by importing |
---|
321 | from the module in which the function is defined. |
---|
322 | |
---|
323 | INPUT: |
---|
324 | |
---|
325 | - ``module``: A string, describing the module to import the |
---|
326 | function from. |
---|
327 | - ``name``: A string, name of the to-be-imported cached function. |
---|
328 | |
---|
329 | EXAMPLE:: |
---|
330 | |
---|
331 | >>> type(cunningham_prime_factors)###line 292:_sage_ >>> type(cunningham_prime_factors) |
---|
332 | <type 'sage.misc.cachefunc.CachedFunction'> |
---|
333 | >>> loads(dumps(cunningham_prime_factors)) is cunningham_prime_factors #indirect doctest###line 294:_sage_ >>> loads(dumps(cunningham_prime_factors)) is cunningham_prime_factors #indirect doctest |
---|
334 | True |
---|
335 | |
---|
336 | |
---|
337 | >>> sig_on_count() |
---|
338 | 0 |
---|
339 | """ |
---|
340 | |
---|
341 | def example_2(): r""">>> set_random_seed(0L) |
---|
342 | |
---|
343 | >>> change_warning_output(sys.stdout) |
---|
344 | |
---|
345 | |
---|
346 | Create a cached version of a function, which only recomputes |
---|
347 | values it hasn't already computed. Synonyme: ``cached_function`` |
---|
348 | |
---|
349 | INPUT: |
---|
350 | |
---|
351 | - ``f`` -- a function |
---|
352 | - ``name`` (optional string) -- name that the cached version |
---|
353 | of ``f`` should be provided with. |
---|
354 | |
---|
355 | If ``f`` is a function, do either ``g = CachedFunction(f)`` |
---|
356 | or ``g = cached_function(f)`` to make a cached version of ``f``, |
---|
357 | or put ``@cached_function`` right before the definition of ``f`` |
---|
358 | (i.e., use Python decorators):: |
---|
359 | |
---|
360 | @cached_function |
---|
361 | def f(...): |
---|
362 | .... |
---|
363 | |
---|
364 | The inputs to the function must be hashable. |
---|
365 | |
---|
366 | EXAMPLES:: |
---|
367 | |
---|
368 | >>> @cached_function###line 324:_sage_ >>> @cached_function |
---|
369 | ... def mul(x, y=Integer(2)): |
---|
370 | ... return x*y |
---|
371 | ... |
---|
372 | >>> mul(Integer(3))###line 328:_sage_ >>> mul(3) |
---|
373 | 6 |
---|
374 | |
---|
375 | We demonstrate that the result is cached, and that, moreover, |
---|
376 | the cache takes into account the various ways of providing |
---|
377 | default arguments:: |
---|
378 | |
---|
379 | >>> mul(Integer(3)) is mul(Integer(3),Integer(2))###line 335:_sage_ >>> mul(3) is mul(3,2) |
---|
380 | True |
---|
381 | >>> mul(Integer(3),y=Integer(2)) is mul(Integer(3),Integer(2))###line 337:_sage_ >>> mul(3,y=2) is mul(3,2) |
---|
382 | True |
---|
383 | |
---|
384 | The user can clear the cache:: |
---|
385 | |
---|
386 | >>> a = mul(Integer(4))###line 342:_sage_ >>> a = mul(4) |
---|
387 | >>> mul.clear_cache()###line 343:_sage_ >>> mul.clear_cache() |
---|
388 | >>> a is mul(Integer(4))###line 344:_sage_ >>> a is mul(4) |
---|
389 | False |
---|
390 | |
---|
391 | It is also possible to explicitly override the cache with |
---|
392 | a different value:: |
---|
393 | |
---|
394 | >>> mul.set_cache('foo',Integer(5))###line 350:_sage_ >>> mul.set_cache('foo',5) |
---|
395 | >>> mul(Integer(5),Integer(2))###line 351:_sage_ >>> mul(5,2) |
---|
396 | 'foo' |
---|
397 | |
---|
398 | |
---|
399 | >>> sig_on_count() |
---|
400 | 0 |
---|
401 | """ |
---|
402 | |
---|
403 | def example_3(): r""">>> set_random_seed(0L) |
---|
404 | |
---|
405 | >>> change_warning_output(sys.stdout) |
---|
406 | |
---|
407 | |
---|
408 | Create a cached version of a function, which only recomputes |
---|
409 | values it hasn't already computed. A custom name can be |
---|
410 | provided by an optional argument "name". |
---|
411 | |
---|
412 | If f is a function, do either g = CachedFunction(f) to make |
---|
413 | a cached version of f, or put @CachedFunction right before |
---|
414 | the definition of f (i.e., use Python decorators, but then |
---|
415 | the optional argument ``name`` can not be used):: |
---|
416 | |
---|
417 | @CachedFunction |
---|
418 | def f(...): |
---|
419 | .... |
---|
420 | |
---|
421 | The inputs to the function must be hashable. |
---|
422 | |
---|
423 | TESTS:: |
---|
424 | |
---|
425 | >>> g = CachedFunction(number_of_partitions)###line 374:_sage_ >>> g = CachedFunction(number_of_partitions) |
---|
426 | >>> g.__name__###line 375:_sage_ >>> g.__name__ |
---|
427 | 'number_of_partitions' |
---|
428 | >>> 'partitions' in sage.misc.sageinspect.sage_getdoc(g)###line 377:_sage_ >>> 'partitions' in sage.misc.sageinspect.sage_getdoc(g) |
---|
429 | True |
---|
430 | >>> g(Integer(5))###line 379:_sage_ >>> g(5) |
---|
431 | 7 |
---|
432 | >>> g.cache###line 381:_sage_ >>> g.cache |
---|
433 | {((5, None, 'default'), ()): 7} |
---|
434 | >>> def f(t=Integer(1)): print(t)###line 383:_sage_ >>> def f(t=1): print(t) |
---|
435 | >>> h = CachedFunction(f)###line 384:_sage_ >>> h = CachedFunction(f) |
---|
436 | >>> w = walltime()###line 385:_sage_ >>> w = walltime() |
---|
437 | >>> h(); h(Integer(1)); h(t=Integer(1))###line 386:_sage_ >>> h(); h(1); h(t=1) |
---|
438 | 1 |
---|
439 | >>> walltime(w) < Integer(2)###line 388:_sage_ >>> walltime(w) < 2 |
---|
440 | True |
---|
441 | |
---|
442 | |
---|
443 | >>> sig_on_count() |
---|
444 | 0 |
---|
445 | """ |
---|
446 | |
---|
447 | def example_4(): r""">>> set_random_seed(0L) |
---|
448 | |
---|
449 | >>> change_warning_output(sys.stdout) |
---|
450 | |
---|
451 | |
---|
452 | Perform initialization common to CachedFunction and CachedMethodCaller. |
---|
453 | |
---|
454 | TESTS:: |
---|
455 | |
---|
456 | >>> @cached_function###line 401:_sage_ >>> @cached_function |
---|
457 | ... def test_cache(x): |
---|
458 | ... return -x |
---|
459 | >>> test_cache._fix_to_pos is not None # indirect doctest###line 404:_sage_ >>> test_cache._fix_to_pos is not None # indirect doctest |
---|
460 | True |
---|
461 | |
---|
462 | |
---|
463 | >>> sig_on_count() |
---|
464 | 0 |
---|
465 | """ |
---|
466 | |
---|
467 | def example_5(): r""">>> set_random_seed(0L) |
---|
468 | |
---|
469 | >>> change_warning_output(sys.stdout) |
---|
470 | |
---|
471 | |
---|
472 | Pickling of cached functions. |
---|
473 | |
---|
474 | TEST:: |
---|
475 | |
---|
476 | >>> type(cunningham_prime_factors)###line 426:_sage_ >>> type(cunningham_prime_factors) |
---|
477 | <type 'sage.misc.cachefunc.CachedFunction'> |
---|
478 | >>> loads(dumps(cunningham_prime_factors)) is cunningham_prime_factors #indirect doctest###line 428:_sage_ >>> loads(dumps(cunningham_prime_factors)) is cunningham_prime_factors #indirect doctest |
---|
479 | True |
---|
480 | |
---|
481 | |
---|
482 | >>> sig_on_count() |
---|
483 | 0 |
---|
484 | """ |
---|
485 | |
---|
486 | def example_6(): r""">>> set_random_seed(0L) |
---|
487 | |
---|
488 | >>> change_warning_output(sys.stdout) |
---|
489 | |
---|
490 | |
---|
491 | Provide documentation for the cached function. |
---|
492 | |
---|
493 | A cached function shall inherit the documentation |
---|
494 | from the function that is wrapped, not from the |
---|
495 | documentation of the wrapper. |
---|
496 | |
---|
497 | TEST:: |
---|
498 | |
---|
499 | >>> P = QQ['x, y']; (x, y,) = P._first_ngens(2)###line 450:_sage_ >>> P.<x,y> = QQ[] |
---|
500 | >>> I = P*[x,y]###line 451:_sage_ >>> I = P*[x,y] |
---|
501 | >>> from sage.misc.sageinspect import sage_getdoc###line 452:_sage_ >>> from sage.misc.sageinspect import sage_getdoc |
---|
502 | >>> print sage_getdoc(I.groebner_basis) # indirect doctest###line 453:_sage_ >>> print sage_getdoc(I.groebner_basis) # indirect doctest |
---|
503 | Return the reduced Groebner basis of this ideal. |
---|
504 | ... |
---|
505 | ALGORITHM: Uses Singular, Magma (if available), Macaulay2 (if |
---|
506 | available), or a toy implementation. |
---|
507 | |
---|
508 | |
---|
509 | >>> sig_on_count() |
---|
510 | 0 |
---|
511 | """ |
---|
512 | |
---|
513 | def example_7(): r""">>> set_random_seed(0L) |
---|
514 | |
---|
515 | >>> change_warning_output(sys.stdout) |
---|
516 | |
---|
517 | |
---|
518 | Returns the source code for the wrapped function. |
---|
519 | |
---|
520 | TESTS:: |
---|
521 | |
---|
522 | >>> from sage.misc.sageinspect import sage_getsource###line 491:_sage_ >>> from sage.misc.sageinspect import sage_getsource |
---|
523 | >>> g = CachedFunction(number_of_partitions)###line 492:_sage_ >>> g = CachedFunction(number_of_partitions) |
---|
524 | >>> 'bober' in sage_getsource(g) # indirect doctest###line 493:_sage_ >>> 'bober' in sage_getsource(g) # indirect doctest |
---|
525 | True |
---|
526 | |
---|
527 | |
---|
528 | >>> sig_on_count() |
---|
529 | 0 |
---|
530 | """ |
---|
531 | |
---|
532 | def example_8(): r""">>> set_random_seed(0L) |
---|
533 | |
---|
534 | >>> change_warning_output(sys.stdout) |
---|
535 | |
---|
536 | |
---|
537 | Returns the list of source lines and the first line number |
---|
538 | of the wrapped function. |
---|
539 | |
---|
540 | TEST:: |
---|
541 | |
---|
542 | >>> P = QQ['x, y']; (x, y,) = P._first_ngens(2)###line 507:_sage_ >>> P.<x,y> = QQ[] |
---|
543 | >>> I = P*[x,y]###line 508:_sage_ >>> I = P*[x,y] |
---|
544 | >>> from sage.misc.sageinspect import sage_getsourcelines###line 509:_sage_ >>> from sage.misc.sageinspect import sage_getsourcelines |
---|
545 | >>> l = " elif algorithm == 'macaulay2:gb':\n"###line 510:_sage_ >>> l = " elif algorithm == 'macaulay2:gb':\n" |
---|
546 | >>> l in sage_getsourcelines(I.groebner_basis)[Integer(0)] # indirect doctest###line 511:_sage_ >>> l in sage_getsourcelines(I.groebner_basis)[0] # indirect doctest |
---|
547 | True |
---|
548 | |
---|
549 | |
---|
550 | >>> sig_on_count() |
---|
551 | 0 |
---|
552 | """ |
---|
553 | |
---|
554 | def example_9(): r""">>> set_random_seed(0L) |
---|
555 | |
---|
556 | >>> change_warning_output(sys.stdout) |
---|
557 | |
---|
558 | |
---|
559 | Return the argspec of the wrapped function or method. |
---|
560 | |
---|
561 | This was implemented in trac ticket #11115. |
---|
562 | |
---|
563 | EXAMPLE:: |
---|
564 | |
---|
565 | >>> P = QQ['x, y']; (x, y,) = P._first_ngens(2)###line 526:_sage_ >>> P.<x,y> = QQ[] |
---|
566 | >>> I = P*[x,y]###line 527:_sage_ >>> I = P*[x,y] |
---|
567 | >>> from sage.misc.sageinspect import sage_getargspec###line 528:_sage_ >>> from sage.misc.sageinspect import sage_getargspec |
---|
568 | >>> sage_getargspec(I.groebner_basis) # indirect doctest###line 529:_sage_ >>> sage_getargspec(I.groebner_basis) # indirect doctest |
---|
569 | ArgSpec(args=['self', 'algorithm', 'deg_bound', 'mult_bound', 'prot'], |
---|
570 | varargs='args', keywords='kwds', defaults=('', None, None, |
---|
571 | False)) |
---|
572 | |
---|
573 | |
---|
574 | >>> sig_on_count() |
---|
575 | 0 |
---|
576 | """ |
---|
577 | |
---|
578 | def example_10(): r""">>> set_random_seed(0L) |
---|
579 | |
---|
580 | >>> change_warning_output(sys.stdout) |
---|
581 | |
---|
582 | |
---|
583 | Return value from cache or call the wrapped function, |
---|
584 | caching the output. |
---|
585 | |
---|
586 | TESTS:: |
---|
587 | |
---|
588 | >>> g = CachedFunction(number_of_partitions)###line 545:_sage_ >>> g = CachedFunction(number_of_partitions) |
---|
589 | >>> a = g(Integer(5))###line 546:_sage_ >>> a = g(5) |
---|
590 | >>> g.get_cache()###line 547:_sage_ >>> g.get_cache() |
---|
591 | {((5, None, 'default'), ()): 7} |
---|
592 | >>> a = g(Integer(10)**Integer(5)) # indirect doctest###line 549:_sage_ >>> a = g(10^5) # indirect doctest |
---|
593 | >>> a == number_of_partitions(Integer(10)**Integer(5))###line 550:_sage_ >>> a == number_of_partitions(10^5) |
---|
594 | True |
---|
595 | >>> a is g(Integer(10)**Integer(5))###line 552:_sage_ >>> a is g(10^5) |
---|
596 | True |
---|
597 | >>> a is number_of_partitions(Integer(10)**Integer(5))###line 554:_sage_ >>> a is number_of_partitions(10^5) |
---|
598 | False |
---|
599 | |
---|
600 | |
---|
601 | >>> sig_on_count() |
---|
602 | 0 |
---|
603 | """ |
---|
604 | |
---|
605 | def example_11(): r""">>> set_random_seed(0L) |
---|
606 | |
---|
607 | >>> change_warning_output(sys.stdout) |
---|
608 | |
---|
609 | |
---|
610 | Returns the cache dictionary. |
---|
611 | |
---|
612 | EXAMPLES:: |
---|
613 | |
---|
614 | >>> g = CachedFunction(number_of_partitions)###line 580:_sage_ >>> g = CachedFunction(number_of_partitions) |
---|
615 | >>> a = g(Integer(5))###line 581:_sage_ >>> a = g(5) |
---|
616 | >>> g.get_cache()###line 582:_sage_ >>> g.get_cache() |
---|
617 | {((5, None, 'default'), ()): 7} |
---|
618 | |
---|
619 | |
---|
620 | >>> sig_on_count() |
---|
621 | 0 |
---|
622 | """ |
---|
623 | |
---|
624 | def example_12(): r""">>> set_random_seed(0L) |
---|
625 | |
---|
626 | >>> change_warning_output(sys.stdout) |
---|
627 | |
---|
628 | |
---|
629 | Checks if the argument list is in the cache. |
---|
630 | |
---|
631 | EXAMPLES:: |
---|
632 | |
---|
633 | >>> class Foo:###line 594:_sage_ >>> class Foo: |
---|
634 | ... def __init__(self, x): |
---|
635 | ... self._x = x |
---|
636 | ... @cached_method |
---|
637 | ... def f(self, z, y=Integer(0)): |
---|
638 | ... return self._x*z+y |
---|
639 | ... |
---|
640 | >>> a = Foo(Integer(2))###line 601:_sage_ >>> a = Foo(2) |
---|
641 | >>> a.f.is_in_cache(Integer(3))###line 602:_sage_ >>> a.f.is_in_cache(3) |
---|
642 | False |
---|
643 | >>> a.f(Integer(3))###line 604:_sage_ >>> a.f(3) |
---|
644 | 6 |
---|
645 | >>> a.f.is_in_cache(Integer(3),y=Integer(0))###line 606:_sage_ >>> a.f.is_in_cache(3,y=0) |
---|
646 | True |
---|
647 | |
---|
648 | >>> sig_on_count() |
---|
649 | 0 |
---|
650 | """ |
---|
651 | |
---|
652 | def example_13(): r""">>> set_random_seed(0L) |
---|
653 | |
---|
654 | >>> change_warning_output(sys.stdout) |
---|
655 | |
---|
656 | |
---|
657 | Set the value for those args and keyword args |
---|
658 | Mind the unintuitive syntax (value first). |
---|
659 | Any idea on how to improve that welcome! |
---|
660 | |
---|
661 | EXAMPLES:: |
---|
662 | |
---|
663 | >>> g = CachedFunction(number_of_partitions)###line 619:_sage_ >>> g = CachedFunction(number_of_partitions) |
---|
664 | >>> a = g(Integer(5))###line 620:_sage_ >>> a = g(5) |
---|
665 | >>> g.get_cache()###line 621:_sage_ >>> g.get_cache() |
---|
666 | {((5, None, 'default'), ()): 7} |
---|
667 | >>> g.set_cache(Integer(17), Integer(5))###line 623:_sage_ >>> g.set_cache(17, 5) |
---|
668 | >>> g.get_cache()###line 624:_sage_ >>> g.get_cache() |
---|
669 | {((5, None, 'default'), ()): 17} |
---|
670 | >>> g(Integer(5))###line 626:_sage_ >>> g(5) |
---|
671 | 17 |
---|
672 | |
---|
673 | DEVELOPER NOTE: |
---|
674 | |
---|
675 | Is there a way to use the following intuitive syntax? |
---|
676 | |
---|
677 | :: |
---|
678 | |
---|
679 | |
---|
680 | |
---|
681 | |
---|
682 | |
---|
683 | 19 |
---|
684 | |
---|
685 | >>> sig_on_count() |
---|
686 | 0 |
---|
687 | """ |
---|
688 | |
---|
689 | def example_14(): r""">>> set_random_seed(0L) |
---|
690 | |
---|
691 | >>> change_warning_output(sys.stdout) |
---|
692 | |
---|
693 | |
---|
694 | Returns the key in the cache to be used when args |
---|
695 | and kwds are passed in as parameters. |
---|
696 | |
---|
697 | EXAMPLES:: |
---|
698 | |
---|
699 | >>> @cached_function###line 648:_sage_ >>> @cached_function |
---|
700 | ... def foo(x): |
---|
701 | ... return x**Integer(2) |
---|
702 | ... |
---|
703 | >>> foo(Integer(2))###line 652:_sage_ >>> foo(2) |
---|
704 | 4 |
---|
705 | >>> foo.get_key(Integer(2))###line 654:_sage_ >>> foo.get_key(2) |
---|
706 | ((2,), ()) |
---|
707 | >>> foo.get_key(x=Integer(3))###line 656:_sage_ >>> foo.get_key(x=3) |
---|
708 | ((3,), ()) |
---|
709 | |
---|
710 | >>> sig_on_count() |
---|
711 | 0 |
---|
712 | """ |
---|
713 | |
---|
714 | def example_15(): r""">>> set_random_seed(0L) |
---|
715 | |
---|
716 | >>> change_warning_output(sys.stdout) |
---|
717 | |
---|
718 | |
---|
719 | EXAMPLES:: |
---|
720 | |
---|
721 | >>> g = CachedFunction(number_of_partitions)###line 665:_sage_ >>> g = CachedFunction(number_of_partitions) |
---|
722 | >>> g # indirect doctest###line 666:_sage_ >>> g # indirect doctest |
---|
723 | Cached version of <function number_of_partitions at 0x...> |
---|
724 | |
---|
725 | >>> sig_on_count() |
---|
726 | 0 |
---|
727 | """ |
---|
728 | |
---|
729 | def example_16(): r""">>> set_random_seed(0L) |
---|
730 | |
---|
731 | >>> change_warning_output(sys.stdout) |
---|
732 | |
---|
733 | |
---|
734 | Clear the cache dictionary. |
---|
735 | |
---|
736 | EXAMPLES:: |
---|
737 | |
---|
738 | >>> g = CachedFunction(number_of_partitions)###line 680:_sage_ >>> g = CachedFunction(number_of_partitions) |
---|
739 | >>> a = g(Integer(5))###line 681:_sage_ >>> a = g(5) |
---|
740 | >>> g.get_cache()###line 682:_sage_ >>> g.get_cache() |
---|
741 | {((5, None, 'default'), ()): 7} |
---|
742 | >>> g.clear_cache()###line 684:_sage_ >>> g.clear_cache() |
---|
743 | >>> g.get_cache()###line 685:_sage_ >>> g.get_cache() |
---|
744 | {} |
---|
745 | |
---|
746 | >>> sig_on_count() |
---|
747 | 0 |
---|
748 | """ |
---|
749 | |
---|
750 | def example_17(): r""">>> set_random_seed(0L) |
---|
751 | |
---|
752 | >>> change_warning_output(sys.stdout) |
---|
753 | |
---|
754 | |
---|
755 | Cache values for a number of inputs. Do the computation |
---|
756 | in parallel, and only bother to compute values that we |
---|
757 | haven't already cached. |
---|
758 | |
---|
759 | EXAMPLES:: |
---|
760 | |
---|
761 | >>> @cached_function###line 700:_sage_ >>> @cached_function |
---|
762 | ... def oddprime_factors(n): |
---|
763 | ... l = [p for p,e in factor(n) if p != Integer(2)] |
---|
764 | ... return len(l) |
---|
765 | >>> oddprime_factors.precompute(range(Integer(1),Integer(100)), Integer(4))###line 704:_sage_ >>> oddprime_factors.precompute(range(1,100), 4) |
---|
766 | >>> oddprime_factors.cache[(Integer(25),),()]###line 705:_sage_ >>> oddprime_factors.cache[(25,),()] |
---|
767 | 1 |
---|
768 | |
---|
769 | >>> sig_on_count() |
---|
770 | 0 |
---|
771 | """ |
---|
772 | |
---|
773 | def example_18(): r""">>> set_random_seed(0L) |
---|
774 | |
---|
775 | >>> change_warning_output(sys.stdout) |
---|
776 | |
---|
777 | |
---|
778 | This class helps to unpickle cached methods. |
---|
779 | |
---|
780 | NOTE: |
---|
781 | |
---|
782 | Since trac ticket #8611, a cached method is an attribute |
---|
783 | of the instance (provided that it has a ``__dict__``). |
---|
784 | Hence, when pickling the instance, it would be attempted |
---|
785 | to pickle that attribute as well, but this is a problem, |
---|
786 | since functions can not be pickled, currently. Therefore, |
---|
787 | we replace the actual cached method by a place holder, |
---|
788 | that kills itself as soon as any attribute is requested. |
---|
789 | Then, the original cached attribute is reinstated. But the |
---|
790 | cached values are in fact saved. |
---|
791 | |
---|
792 | EXAMPLE:: |
---|
793 | |
---|
794 | >>> R = PolynomialRing(QQ, Integer(3), names=('x', 'y', 'z',)); (x, y, z,) = R._first_ngens(3)###line 738:_sage_ >>> R.<x, y, z> = PolynomialRing(QQ, 3) |
---|
795 | >>> I = R*(x**Integer(3) + y**Integer(3) + z**Integer(3),x**Integer(4)-y**Integer(4))###line 739:_sage_ >>> I = R*(x^3 + y^3 + z^3,x^4-y^4) |
---|
796 | >>> I.groebner_basis()###line 740:_sage_ >>> I.groebner_basis() |
---|
797 | [y^5*z^3 - 1/4*x^2*z^6 + 1/2*x*y*z^6 + 1/4*y^2*z^6, |
---|
798 | x^2*y*z^3 - x*y^2*z^3 + 2*y^3*z^3 + z^6, |
---|
799 | x*y^3 + y^4 + x*z^3, x^3 + y^3 + z^3] |
---|
800 | >>> I.groebner_basis###line 744:_sage_ >>> I.groebner_basis |
---|
801 | Cached version of <function groebner_basis at 0x...> |
---|
802 | |
---|
803 | We now pickle and unpickle the ideal. The cached method |
---|
804 | ``groebner_basis`` is replaced by a placeholder:: |
---|
805 | |
---|
806 | >>> J = loads(dumps(I))###line 750:_sage_ >>> J = loads(dumps(I)) |
---|
807 | >>> J.groebner_basis###line 751:_sage_ >>> J.groebner_basis |
---|
808 | Pickle of the cached method "groebner_basis" |
---|
809 | |
---|
810 | But as soon as any other attribute is requested from the |
---|
811 | placeholder, it replaces itself by the cached method, and |
---|
812 | the entries of the cache are actually preserved:: |
---|
813 | |
---|
814 | >>> J.groebner_basis.is_in_cache()###line 758:_sage_ >>> J.groebner_basis.is_in_cache() |
---|
815 | True |
---|
816 | >>> J.groebner_basis###line 760:_sage_ >>> J.groebner_basis |
---|
817 | Cached version of <function groebner_basis at 0x...> |
---|
818 | >>> J.groebner_basis() == I.groebner_basis()###line 762:_sage_ >>> J.groebner_basis() == I.groebner_basis() |
---|
819 | True |
---|
820 | |
---|
821 | TESTS: |
---|
822 | |
---|
823 | Since Trac Ticket #11115, there is a special implementation for |
---|
824 | cached methods that don't take arguments:: |
---|
825 | |
---|
826 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 770:_sage_ >>> P.<a,b,c,d> = QQ[] |
---|
827 | >>> I = P*[a,b]###line 771:_sage_ >>> I = P*[a,b] |
---|
828 | >>> type(I.gens)###line 772:_sage_ >>> type(I.gens) |
---|
829 | <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'> |
---|
830 | >>> type(I.groebner_basis)###line 774:_sage_ >>> type(I.groebner_basis) |
---|
831 | <type 'sage.misc.cachefunc.CachedMethodCaller'> |
---|
832 | |
---|
833 | We demonstrate that both implementations can be pickled and |
---|
834 | preserve the cache. For that purpose, we assign nonsense to the |
---|
835 | cache. Of course, it is a very bad idea to override the cache in |
---|
836 | that way. So, please don't try this at home:: |
---|
837 | |
---|
838 | >>> I.groebner_basis.set_cache('foo',algorithm='singular')###line 782:_sage_ >>> I.groebner_basis.set_cache('foo',algorithm='singular') |
---|
839 | >>> I.groebner_basis(algorithm='singular')###line 783:_sage_ >>> I.groebner_basis(algorithm='singular') |
---|
840 | 'foo' |
---|
841 | >>> I.gens.set_cache('bar')###line 785:_sage_ >>> I.gens.set_cache('bar') |
---|
842 | >>> I.gens()###line 786:_sage_ >>> I.gens() |
---|
843 | 'bar' |
---|
844 | >>> J = loads(dumps(I))###line 788:_sage_ >>> J = loads(dumps(I)) |
---|
845 | >>> J.gens()###line 789:_sage_ >>> J.gens() |
---|
846 | 'bar' |
---|
847 | >>> J.groebner_basis(algorithm='singular')###line 791:_sage_ >>> J.groebner_basis(algorithm='singular') |
---|
848 | 'foo' |
---|
849 | |
---|
850 | Anyway, the cache will be automatically reconstructed after |
---|
851 | clearing it:: |
---|
852 | |
---|
853 | >>> J.gens.clear_cache()###line 797:_sage_ >>> J.gens.clear_cache() |
---|
854 | >>> J.gens()###line 798:_sage_ >>> J.gens() |
---|
855 | [a, b] |
---|
856 | >>> J.groebner_basis.clear_cache()###line 800:_sage_ >>> J.groebner_basis.clear_cache() |
---|
857 | >>> J.groebner_basis(algorithm='singular')###line 801:_sage_ >>> J.groebner_basis(algorithm='singular') |
---|
858 | [a, b] |
---|
859 | |
---|
860 | AUTHOR: |
---|
861 | |
---|
862 | - Simon King (2011-01) |
---|
863 | |
---|
864 | >>> sig_on_count() |
---|
865 | 0 |
---|
866 | """ |
---|
867 | |
---|
868 | def example_19(): r""">>> set_random_seed(0L) |
---|
869 | |
---|
870 | >>> change_warning_output(sys.stdout) |
---|
871 | |
---|
872 | |
---|
873 | INPUT: |
---|
874 | |
---|
875 | - ``inst`` - some instance. |
---|
876 | - ``name`` (string) - usually the name of an attribute |
---|
877 | of ``inst`` to which ``self`` is assigned. |
---|
878 | |
---|
879 | TEST:: |
---|
880 | |
---|
881 | >>> from sage.misc.cachefunc import CachedMethodPickle###line 818:_sage_ >>> from sage.misc.cachefunc import CachedMethodPickle |
---|
882 | >>> P = CachedMethodPickle(Integer(1), 'foo')###line 819:_sage_ >>> P = CachedMethodPickle(1, 'foo') |
---|
883 | >>> P###line 820:_sage_ >>> P |
---|
884 | Pickle of the cached method "foo" |
---|
885 | |
---|
886 | |
---|
887 | >>> sig_on_count() |
---|
888 | 0 |
---|
889 | """ |
---|
890 | |
---|
891 | def example_20(): r""">>> set_random_seed(0L) |
---|
892 | |
---|
893 | >>> change_warning_output(sys.stdout) |
---|
894 | |
---|
895 | |
---|
896 | TEST:: |
---|
897 | |
---|
898 | >>> R = PolynomialRing(QQ, Integer(3), names=('x', 'y', 'z',)); (x, y, z,) = R._first_ngens(3)###line 831:_sage_ >>> R.<x, y, z> = PolynomialRing(QQ, 3) |
---|
899 | >>> I = R*(x**Integer(3) + y**Integer(3) + z**Integer(3),x**Integer(4)-y**Integer(4))###line 832:_sage_ >>> I = R*(x^3 + y^3 + z^3,x^4-y^4) |
---|
900 | >>> G = I.groebner_basis()###line 833:_sage_ >>> G = I.groebner_basis() |
---|
901 | >>> J = loads(dumps(I))###line 834:_sage_ >>> J = loads(dumps(I)) |
---|
902 | >>> J.groebner_basis #indirect doctest###line 835:_sage_ >>> J.groebner_basis #indirect doctest |
---|
903 | Pickle of the cached method "groebner_basis" |
---|
904 | |
---|
905 | >>> sig_on_count() |
---|
906 | 0 |
---|
907 | """ |
---|
908 | |
---|
909 | def example_21(): r""">>> set_random_seed(0L) |
---|
910 | |
---|
911 | >>> change_warning_output(sys.stdout) |
---|
912 | |
---|
913 | |
---|
914 | This class is a pickle. However, sometimes, pickles |
---|
915 | need to be pickled another time. |
---|
916 | |
---|
917 | TEST:: |
---|
918 | |
---|
919 | >>> PF = WeylGroup(['A',Integer(3)]).pieri_factors()###line 846:_sage_ >>> PF = WeylGroup(['A',3]).pieri_factors() |
---|
920 | >>> a = PF.an_element()###line 847:_sage_ >>> a = PF.an_element() |
---|
921 | >>> a.bruhat_lower_covers()###line 848:_sage_ >>> a.bruhat_lower_covers() |
---|
922 | [[0 1 0 0] |
---|
923 | [0 0 1 0] |
---|
924 | [1 0 0 0] |
---|
925 | [0 0 0 1], [0 1 0 0] |
---|
926 | [1 0 0 0] |
---|
927 | [0 0 0 1] |
---|
928 | [0 0 1 0], [1 0 0 0] |
---|
929 | [0 0 1 0] |
---|
930 | [0 0 0 1] |
---|
931 | [0 1 0 0]] |
---|
932 | >>> b = loads(dumps(a))###line 859:_sage_ >>> b = loads(dumps(a)) |
---|
933 | >>> b.bruhat_lower_covers###line 860:_sage_ >>> b.bruhat_lower_covers |
---|
934 | Pickle of the cached method "bruhat_lower_covers" |
---|
935 | |
---|
936 | When we now pickle ``b``, the pickle of the cached method |
---|
937 | needs to be taken care of:: |
---|
938 | |
---|
939 | >>> c = loads(dumps(b)) # indirect doctest###line 866:_sage_ >>> c = loads(dumps(b)) # indirect doctest |
---|
940 | >>> c.bruhat_lower_covers###line 867:_sage_ >>> c.bruhat_lower_covers |
---|
941 | Pickle of the cached method "bruhat_lower_covers" |
---|
942 | >>> c.bruhat_lower_covers()###line 869:_sage_ >>> c.bruhat_lower_covers() |
---|
943 | [[0 1 0 0] |
---|
944 | [0 0 1 0] |
---|
945 | [1 0 0 0] |
---|
946 | [0 0 0 1], [0 1 0 0] |
---|
947 | [1 0 0 0] |
---|
948 | [0 0 0 1] |
---|
949 | [0 0 1 0], [1 0 0 0] |
---|
950 | [0 0 1 0] |
---|
951 | [0 0 0 1] |
---|
952 | [0 1 0 0]] |
---|
953 | |
---|
954 | |
---|
955 | >>> sig_on_count() |
---|
956 | 0 |
---|
957 | """ |
---|
958 | |
---|
959 | def example_22(): r""">>> set_random_seed(0L) |
---|
960 | |
---|
961 | >>> change_warning_output(sys.stdout) |
---|
962 | |
---|
963 | |
---|
964 | The purpose of this call method is to kill ``self`` and to |
---|
965 | replace it by an actual :class:`CachedMethodCaller`. The last |
---|
966 | thing that ``self`` does before disappearing is to call the |
---|
967 | :class:`CachedMethodCaller` and return the result. |
---|
968 | |
---|
969 | EXAMPLE:: |
---|
970 | |
---|
971 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 892:_sage_ >>> P.<a,b,c,d> = QQ[] |
---|
972 | >>> I = P*[a,b]###line 893:_sage_ >>> I = P*[a,b] |
---|
973 | >>> I.gens###line 894:_sage_ >>> I.gens |
---|
974 | Cached version of <function gens at 0x...> |
---|
975 | >>> J = loads(dumps(I))###line 896:_sage_ >>> J = loads(dumps(I)) |
---|
976 | >>> J.gens###line 897:_sage_ >>> J.gens |
---|
977 | Pickle of the cached method "gens" |
---|
978 | >>> J.gens() # indirect doctest###line 899:_sage_ >>> J.gens() # indirect doctest |
---|
979 | [a, b] |
---|
980 | >>> J.gens###line 901:_sage_ >>> J.gens |
---|
981 | Cached version of <function gens at 0x...> |
---|
982 | |
---|
983 | |
---|
984 | >>> sig_on_count() |
---|
985 | 0 |
---|
986 | """ |
---|
987 | |
---|
988 | def example_23(): r""">>> set_random_seed(0L) |
---|
989 | |
---|
990 | >>> change_warning_output(sys.stdout) |
---|
991 | |
---|
992 | |
---|
993 | TEST:: |
---|
994 | |
---|
995 | >>> R = PolynomialRing(QQ, Integer(3), names=('x', 'y', 'z',)); (x, y, z,) = R._first_ngens(3)###line 919:_sage_ >>> R.<x, y, z> = PolynomialRing(QQ, 3) |
---|
996 | >>> I = R*(x**Integer(3) + y**Integer(3) + z**Integer(3),x**Integer(4)-y**Integer(4))###line 920:_sage_ >>> I = R*(x^3 + y^3 + z^3,x^4-y^4) |
---|
997 | >>> G = I.groebner_basis()###line 921:_sage_ >>> G = I.groebner_basis() |
---|
998 | >>> J = loads(dumps(I))###line 922:_sage_ >>> J = loads(dumps(I)) |
---|
999 | >>> J.groebner_basis###line 923:_sage_ >>> J.groebner_basis |
---|
1000 | Pickle of the cached method "groebner_basis" |
---|
1001 | |
---|
1002 | If an attribute of name ``s`` is requested (say, |
---|
1003 | ``is_in_cache``), the attribute ``self._name`` of |
---|
1004 | ``self._instance`` is deleted. Then, the attribute |
---|
1005 | of name ``s`` of the attribute ``self._name`` of |
---|
1006 | ``self._instance`` is requested. Since ``self._name`` |
---|
1007 | is a cached method defined for the class of |
---|
1008 | ``self._instance``, retrieving the just-deleted |
---|
1009 | attribute ``self._name`` succeeds. |
---|
1010 | |
---|
1011 | In that way, the unpickling of the cached method is |
---|
1012 | finally accomplished:: |
---|
1013 | |
---|
1014 | >>> J.groebner_basis.is_in_cache() #indirect doctest###line 938:_sage_ >>> J.groebner_basis.is_in_cache() #indirect doctest |
---|
1015 | True |
---|
1016 | >>> J.groebner_basis###line 940:_sage_ >>> J.groebner_basis |
---|
1017 | Cached version of <function groebner_basis at 0x...> |
---|
1018 | |
---|
1019 | |
---|
1020 | >>> sig_on_count() |
---|
1021 | 0 |
---|
1022 | """ |
---|
1023 | |
---|
1024 | def example_24(): r""">>> set_random_seed(0L) |
---|
1025 | |
---|
1026 | >>> change_warning_output(sys.stdout) |
---|
1027 | |
---|
1028 | |
---|
1029 | Utility class that is used by :class:`CachedMethod` to bind a |
---|
1030 | cached method to an instance. |
---|
1031 | |
---|
1032 | NOTE: |
---|
1033 | |
---|
1034 | Since Trac Ticket #11115, there is a special implementation |
---|
1035 | :class:`CachedMethodCallerNoArgs` for methods that do not take |
---|
1036 | arguments. |
---|
1037 | |
---|
1038 | EXAMPLE:: |
---|
1039 | |
---|
1040 | >>> class A:###line 967:_sage_ >>> class A: |
---|
1041 | ... @cached_method |
---|
1042 | ... def bar(self,x): |
---|
1043 | ... return x**Integer(2) |
---|
1044 | >>> a = A()###line 971:_sage_ >>> a = A() |
---|
1045 | >>> a.bar###line 972:_sage_ >>> a.bar |
---|
1046 | Cached version of <function bar at 0x...> |
---|
1047 | >>> type(a.bar)###line 974:_sage_ >>> type(a.bar) |
---|
1048 | <type 'sage.misc.cachefunc.CachedMethodCaller'> |
---|
1049 | >>> a.bar(Integer(2)) is a.bar(x=Integer(2))###line 976:_sage_ >>> a.bar(2) is a.bar(x=2) |
---|
1050 | True |
---|
1051 | |
---|
1052 | |
---|
1053 | >>> sig_on_count() |
---|
1054 | 0 |
---|
1055 | """ |
---|
1056 | |
---|
1057 | def example_25(): r""">>> set_random_seed(0L) |
---|
1058 | |
---|
1059 | >>> change_warning_output(sys.stdout) |
---|
1060 | |
---|
1061 | |
---|
1062 | EXAMPLES:: |
---|
1063 | |
---|
1064 | >>> class Foo:###line 984:_sage_ >>> class Foo: |
---|
1065 | ... def __init__(self, x): |
---|
1066 | ... self._x = x |
---|
1067 | ... @cached_method |
---|
1068 | ... def f(self,*args): |
---|
1069 | ... return self._x**Integer(2) |
---|
1070 | ... |
---|
1071 | >>> a = Foo(Integer(2))###line 991:_sage_ >>> a = Foo(2) |
---|
1072 | >>> a.f.get_cache()###line 992:_sage_ >>> a.f.get_cache() |
---|
1073 | {} |
---|
1074 | >>> a.f()###line 994:_sage_ >>> a.f() |
---|
1075 | 4 |
---|
1076 | >>> a.f.get_cache()###line 996:_sage_ >>> a.f.get_cache() |
---|
1077 | {((), ()): 4} |
---|
1078 | |
---|
1079 | >>> sig_on_count() |
---|
1080 | 0 |
---|
1081 | """ |
---|
1082 | |
---|
1083 | def example_26(): r""">>> set_random_seed(0L) |
---|
1084 | |
---|
1085 | >>> change_warning_output(sys.stdout) |
---|
1086 | |
---|
1087 | |
---|
1088 | The pickle of a :class:`CachedMethodCaller` unpickles |
---|
1089 | to a :class:`CachedMethodPickle`, that is able to replace |
---|
1090 | itself by a copy of the original :class:`CachedMethodCaller`. |
---|
1091 | |
---|
1092 | TEST:: |
---|
1093 | |
---|
1094 | >>> R = PolynomialRing(QQ, Integer(3), names=('x', 'y', 'z',)); (x, y, z,) = R._first_ngens(3)###line 1014:_sage_ >>> R.<x, y, z> = PolynomialRing(QQ, 3) |
---|
1095 | >>> I = R*(x**Integer(3) + y**Integer(3) + z**Integer(3),x**Integer(4)-y**Integer(4))###line 1015:_sage_ >>> I = R*(x^3 + y^3 + z^3,x^4-y^4) |
---|
1096 | >>> G = I.groebner_basis()###line 1016:_sage_ >>> G = I.groebner_basis() |
---|
1097 | >>> J = loads(dumps(I)) #indirect doctest###line 1017:_sage_ >>> J = loads(dumps(I)) #indirect doctest |
---|
1098 | >>> J.groebner_basis###line 1018:_sage_ >>> J.groebner_basis |
---|
1099 | Pickle of the cached method "groebner_basis" |
---|
1100 | >>> J.groebner_basis.is_in_cache()###line 1020:_sage_ >>> J.groebner_basis.is_in_cache() |
---|
1101 | True |
---|
1102 | >>> J.groebner_basis###line 1022:_sage_ >>> J.groebner_basis |
---|
1103 | Cached version of <function groebner_basis at 0x...> |
---|
1104 | |
---|
1105 | |
---|
1106 | >>> sig_on_count() |
---|
1107 | 0 |
---|
1108 | """ |
---|
1109 | |
---|
1110 | def example_27(): r""">>> set_random_seed(0L) |
---|
1111 | |
---|
1112 | >>> change_warning_output(sys.stdout) |
---|
1113 | |
---|
1114 | |
---|
1115 | Call the cached method without using the cache. |
---|
1116 | |
---|
1117 | EXAMPLE:: |
---|
1118 | |
---|
1119 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 1038:_sage_ >>> P.<a,b,c,d> = QQ[] |
---|
1120 | >>> I = P*[a,b]###line 1039:_sage_ >>> I = P*[a,b] |
---|
1121 | >>> I.groebner_basis()###line 1040:_sage_ >>> I.groebner_basis() |
---|
1122 | [a, b] |
---|
1123 | >>> I.groebner_basis._instance_call() is I.groebner_basis()###line 1042:_sage_ >>> I.groebner_basis._instance_call() is I.groebner_basis() |
---|
1124 | False |
---|
1125 | >>> I.groebner_basis._instance_call() == I.groebner_basis()###line 1044:_sage_ >>> I.groebner_basis._instance_call() == I.groebner_basis() |
---|
1126 | True |
---|
1127 | |
---|
1128 | |
---|
1129 | >>> sig_on_count() |
---|
1130 | 0 |
---|
1131 | """ |
---|
1132 | |
---|
1133 | def example_28(): r""">>> set_random_seed(0L) |
---|
1134 | |
---|
1135 | >>> change_warning_output(sys.stdout) |
---|
1136 | |
---|
1137 | |
---|
1138 | Call the cached method. |
---|
1139 | |
---|
1140 | TESTS:: |
---|
1141 | |
---|
1142 | >>> class Foo:###line 1056:_sage_ >>> class Foo: |
---|
1143 | ... @cached_method |
---|
1144 | ... def f(self, x,y=Integer(1)): |
---|
1145 | ... return x+y |
---|
1146 | ... |
---|
1147 | >>> a = Foo()###line 1061:_sage_ >>> a = Foo() |
---|
1148 | >>> a.f(Integer(1)) #indirect doctest###line 1062:_sage_ >>> a.f(1) #indirect doctest |
---|
1149 | 2 |
---|
1150 | |
---|
1151 | The result is cached, taking into account |
---|
1152 | the three ways of providing (named) arguments:: |
---|
1153 | |
---|
1154 | >>> a.f(Integer(5)) is a.f(Integer(5),Integer(1))###line 1068:_sage_ >>> a.f(5) is a.f(5,1) |
---|
1155 | True |
---|
1156 | >>> a.f(Integer(5)) is a.f(Integer(5),y=Integer(1))###line 1070:_sage_ >>> a.f(5) is a.f(5,y=1) |
---|
1157 | True |
---|
1158 | >>> a.f(Integer(5)) is a.f(y=Integer(1),x=Integer(5))###line 1072:_sage_ >>> a.f(5) is a.f(y=1,x=5) |
---|
1159 | True |
---|
1160 | |
---|
1161 | We test that #5843 is fixed:: |
---|
1162 | |
---|
1163 | >>> class Foo:###line 1077:_sage_ >>> class Foo: |
---|
1164 | ... def __init__(self, x): |
---|
1165 | ... self._x = x |
---|
1166 | ... @cached_method |
---|
1167 | ... def f(self, y): |
---|
1168 | ... return self._x |
---|
1169 | ... |
---|
1170 | >>> a = Foo(Integer(2))###line 1084:_sage_ >>> a = Foo(2) |
---|
1171 | >>> b = Foo(Integer(3))###line 1085:_sage_ >>> b = Foo(3) |
---|
1172 | >>> a.f(b.f)###line 1086:_sage_ >>> a.f(b.f) |
---|
1173 | 2 |
---|
1174 | |
---|
1175 | >>> sig_on_count() |
---|
1176 | 0 |
---|
1177 | """ |
---|
1178 | |
---|
1179 | def example_29(): r""">>> set_random_seed(0L) |
---|
1180 | |
---|
1181 | >>> change_warning_output(sys.stdout) |
---|
1182 | |
---|
1183 | |
---|
1184 | Convert arguments to the key for this instance's cache. |
---|
1185 | |
---|
1186 | EXAMPLES:: |
---|
1187 | |
---|
1188 | >>> class Foo:###line 1135:_sage_ >>> class Foo: |
---|
1189 | ... def __init__(self, x): |
---|
1190 | ... self._x = x |
---|
1191 | ... @cached_method |
---|
1192 | ... def f(self, y, z=Integer(0)): |
---|
1193 | ... return self._x * y + z |
---|
1194 | ... |
---|
1195 | >>> a = Foo(Integer(2))###line 1142:_sage_ >>> a = Foo(2) |
---|
1196 | >>> z = a.f(Integer(37))###line 1143:_sage_ >>> z = a.f(37) |
---|
1197 | >>> k = a.f.get_key(Integer(37)); k###line 1144:_sage_ >>> k = a.f.get_key(37); k |
---|
1198 | ((37, 0), ()) |
---|
1199 | >>> a.f.get_cache()[k] is z###line 1146:_sage_ >>> a.f.get_cache()[k] is z |
---|
1200 | True |
---|
1201 | |
---|
1202 | Note that the method does not test whether there are |
---|
1203 | too many arguments, or wrong argument names:: |
---|
1204 | |
---|
1205 | >>> a.f.get_key(Integer(1),Integer(2),Integer(3),x=Integer(4),y=Integer(5),z=Integer(6))###line 1152:_sage_ >>> a.f.get_key(1,2,3,x=4,y=5,z=6) |
---|
1206 | ((1, 2, 3), (('x', 4), ('y', 5), ('z', 6))) |
---|
1207 | |
---|
1208 | It does, however, take into account the different |
---|
1209 | ways of providing named arguments, possibly with a |
---|
1210 | default value:: |
---|
1211 | |
---|
1212 | >>> a.f.get_key(Integer(5))###line 1159:_sage_ >>> a.f.get_key(5) |
---|
1213 | ((5, 0), ()) |
---|
1214 | >>> a.f.get_key(y=Integer(5))###line 1161:_sage_ >>> a.f.get_key(y=5) |
---|
1215 | ((5, 0), ()) |
---|
1216 | >>> a.f.get_key(Integer(5),Integer(0))###line 1163:_sage_ >>> a.f.get_key(5,0) |
---|
1217 | ((5, 0), ()) |
---|
1218 | >>> a.f.get_key(Integer(5),z=Integer(0))###line 1165:_sage_ >>> a.f.get_key(5,z=0) |
---|
1219 | ((5, 0), ()) |
---|
1220 | >>> a.f.get_key(y=Integer(5),z=Integer(0))###line 1167:_sage_ >>> a.f.get_key(y=5,z=0) |
---|
1221 | ((5, 0), ()) |
---|
1222 | |
---|
1223 | |
---|
1224 | >>> sig_on_count() |
---|
1225 | 0 |
---|
1226 | """ |
---|
1227 | |
---|
1228 | def example_30(): r""">>> set_random_seed(0L) |
---|
1229 | |
---|
1230 | >>> change_warning_output(sys.stdout) |
---|
1231 | |
---|
1232 | |
---|
1233 | Get a :class:`CachedMethodCaller` bound to a specific |
---|
1234 | instance of the class of the cached method. |
---|
1235 | |
---|
1236 | NOTE: |
---|
1237 | |
---|
1238 | :class:`CachedMethodCaller` has a separate ``__get__`` |
---|
1239 | since the categories framework creates and caches the |
---|
1240 | return value of ``CachedMethod.__get__`` with |
---|
1241 | ``inst==None``. |
---|
1242 | |
---|
1243 | This getter attempts to assign a bound method as an |
---|
1244 | attribute to the given instance. If this is not |
---|
1245 | possible (for example, for some extension classes), |
---|
1246 | it is attempted to find an attribute ``__cached_methods``, |
---|
1247 | and store/retrieve the bound method there. In that |
---|
1248 | way, cached methods can be implemented for extension |
---|
1249 | classes deriving from :class:`~sage.structure.parent.Parent` |
---|
1250 | and :class:`~sage.structure.element.Element`. |
---|
1251 | |
---|
1252 | TESTS: |
---|
1253 | |
---|
1254 | Due to the separate ``__get__`` method, it is possible |
---|
1255 | to define a cached method in one class and use it as |
---|
1256 | an attribute of another class. |
---|
1257 | |
---|
1258 | >>> class Foo:###line 1202:_sage_ >>> class Foo: |
---|
1259 | ... @cached_method |
---|
1260 | ... def f(self, y): |
---|
1261 | ... return y - Integer(1) |
---|
1262 | >>> class Bar:###line 1206:_sage_ >>> class Bar: |
---|
1263 | ... f = Foo.f |
---|
1264 | >>> b1 = Bar()###line 1208:_sage_ >>> b1 = Bar() |
---|
1265 | >>> b2 = Bar()###line 1209:_sage_ >>> b2 = Bar() |
---|
1266 | |
---|
1267 | The :class:`CachedMethod` is replaced by an instance |
---|
1268 | of :class:`CachedMethodCaller` that (by trac ticket |
---|
1269 | #8611) is set as an attribute. Hence, we have:: |
---|
1270 | |
---|
1271 | >>> b1.f is b1.f###line 1215:_sage_ >>> b1.f is b1.f |
---|
1272 | True |
---|
1273 | |
---|
1274 | Any instance of ``Bar`` gets its own instance of |
---|
1275 | :class:`CachedMethodCaller``:: |
---|
1276 | |
---|
1277 | >>> b1.f is b2.f###line 1221:_sage_ >>> b1.f is b2.f |
---|
1278 | False |
---|
1279 | |
---|
1280 | The method caller knows the instance that it belongs |
---|
1281 | to:: |
---|
1282 | |
---|
1283 | >>> Foo.f._instance is None###line 1227:_sage_ >>> Foo.f._instance is None |
---|
1284 | True |
---|
1285 | >>> b1.f._instance is b1###line 1229:_sage_ >>> b1.f._instance is b1 |
---|
1286 | True |
---|
1287 | >>> b2.f._instance is b2###line 1231:_sage_ >>> b2.f._instance is b2 |
---|
1288 | True |
---|
1289 | |
---|
1290 | An extension class can inherit a cached method from the |
---|
1291 | parent or element class of a category (trac ticket #11115). |
---|
1292 | See :class:`CachedMethodCaller` for examples. |
---|
1293 | |
---|
1294 | |
---|
1295 | >>> sig_on_count() |
---|
1296 | 0 |
---|
1297 | """ |
---|
1298 | |
---|
1299 | def example_31(): r""">>> set_random_seed(0L) |
---|
1300 | |
---|
1301 | >>> change_warning_output(sys.stdout) |
---|
1302 | |
---|
1303 | |
---|
1304 | Utility class that is used by :class:`CachedMethod` to bind a |
---|
1305 | cached method to an instance, in the case of a method that does |
---|
1306 | not accept any arguments except ``self``. |
---|
1307 | |
---|
1308 | NOTE: |
---|
1309 | |
---|
1310 | The return value ``None`` would not be cached. So, if you have |
---|
1311 | a method that does not accept arguments and may return ``None`` |
---|
1312 | after a lengthy computation, then ``@cached_method`` should not |
---|
1313 | be used. |
---|
1314 | |
---|
1315 | EXAMPLE:: |
---|
1316 | |
---|
1317 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 1274:_sage_ >>> P.<a,b,c,d> = QQ[] |
---|
1318 | >>> I = P*[a,b]###line 1275:_sage_ >>> I = P*[a,b] |
---|
1319 | >>> I.gens###line 1276:_sage_ >>> I.gens |
---|
1320 | Cached version of <function gens at 0x...> |
---|
1321 | >>> type(I.gens)###line 1278:_sage_ >>> type(I.gens) |
---|
1322 | <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'> |
---|
1323 | >>> I.gens is I.gens###line 1280:_sage_ >>> I.gens is I.gens |
---|
1324 | True |
---|
1325 | >>> I.gens() is I.gens()###line 1282:_sage_ >>> I.gens() is I.gens() |
---|
1326 | True |
---|
1327 | |
---|
1328 | AUTHOR: |
---|
1329 | |
---|
1330 | - Simon King (2011-04) |
---|
1331 | |
---|
1332 | >>> sig_on_count() |
---|
1333 | 0 |
---|
1334 | """ |
---|
1335 | |
---|
1336 | def example_32(): r""">>> set_random_seed(0L) |
---|
1337 | |
---|
1338 | >>> change_warning_output(sys.stdout) |
---|
1339 | |
---|
1340 | |
---|
1341 | EXAMPLES:: |
---|
1342 | |
---|
1343 | >>> class Foo:###line 1293:_sage_ >>> class Foo: |
---|
1344 | ... def __init__(self, x): |
---|
1345 | ... self._x = x |
---|
1346 | ... @cached_method |
---|
1347 | ... def f(self): |
---|
1348 | ... return self._x**Integer(2) |
---|
1349 | ... |
---|
1350 | >>> a = Foo(Integer(2))###line 1300:_sage_ >>> a = Foo(2) |
---|
1351 | >>> print a.f.get_cache()###line 1301:_sage_ >>> print a.f.get_cache() |
---|
1352 | None |
---|
1353 | >>> a.f()###line 1303:_sage_ >>> a.f() |
---|
1354 | 4 |
---|
1355 | >>> a.f.get_cache()###line 1305:_sage_ >>> a.f.get_cache() |
---|
1356 | 4 |
---|
1357 | |
---|
1358 | |
---|
1359 | >>> sig_on_count() |
---|
1360 | 0 |
---|
1361 | """ |
---|
1362 | |
---|
1363 | def example_33(): r""">>> set_random_seed(0L) |
---|
1364 | |
---|
1365 | >>> change_warning_output(sys.stdout) |
---|
1366 | |
---|
1367 | |
---|
1368 | Since functions can not be pickled, the cached method caller |
---|
1369 | is pickled by a :class:`CachedMethodPickle`, that replaces |
---|
1370 | itself by an actual :class:`CachedMethodCallerNoArgs` as soon |
---|
1371 | as it is asked to do anything. |
---|
1372 | |
---|
1373 | TEST:: |
---|
1374 | |
---|
1375 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 1346:_sage_ >>> P.<a,b,c,d> = QQ[] |
---|
1376 | >>> I = P*[a,b]###line 1347:_sage_ >>> I = P*[a,b] |
---|
1377 | >>> I.gens()###line 1348:_sage_ >>> I.gens() |
---|
1378 | [a, b] |
---|
1379 | >>> I.gens###line 1350:_sage_ >>> I.gens |
---|
1380 | Cached version of <function gens at 0x...> |
---|
1381 | >>> J = loads(dumps(I))###line 1352:_sage_ >>> J = loads(dumps(I)) |
---|
1382 | >>> J.gens###line 1353:_sage_ >>> J.gens |
---|
1383 | Pickle of the cached method "gens" |
---|
1384 | >>> J.gens.cache###line 1355:_sage_ >>> J.gens.cache |
---|
1385 | [a, b] |
---|
1386 | >>> J.gens###line 1357:_sage_ >>> J.gens |
---|
1387 | Cached version of <function gens at 0x...> |
---|
1388 | |
---|
1389 | |
---|
1390 | >>> sig_on_count() |
---|
1391 | 0 |
---|
1392 | """ |
---|
1393 | |
---|
1394 | def example_34(): r""">>> set_random_seed(0L) |
---|
1395 | |
---|
1396 | >>> change_warning_output(sys.stdout) |
---|
1397 | |
---|
1398 | |
---|
1399 | Call the cached method without using the cache. |
---|
1400 | |
---|
1401 | EXAMPLE:: |
---|
1402 | |
---|
1403 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 1369:_sage_ >>> P.<a,b,c,d> = QQ[] |
---|
1404 | >>> I = P*[a,b]###line 1370:_sage_ >>> I = P*[a,b] |
---|
1405 | >>> I.gens()###line 1371:_sage_ >>> I.gens() |
---|
1406 | [a, b] |
---|
1407 | >>> I.gens._instance_call() is I.gens()###line 1373:_sage_ >>> I.gens._instance_call() is I.gens() |
---|
1408 | False |
---|
1409 | >>> I.gens._instance_call() == I.gens()###line 1375:_sage_ >>> I.gens._instance_call() == I.gens() |
---|
1410 | True |
---|
1411 | |
---|
1412 | |
---|
1413 | >>> sig_on_count() |
---|
1414 | 0 |
---|
1415 | """ |
---|
1416 | |
---|
1417 | def example_35(): r""">>> set_random_seed(0L) |
---|
1418 | |
---|
1419 | >>> change_warning_output(sys.stdout) |
---|
1420 | |
---|
1421 | |
---|
1422 | Call the cached method. |
---|
1423 | |
---|
1424 | EXAMPLE:: |
---|
1425 | |
---|
1426 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 1387:_sage_ >>> P.<a,b,c,d> = QQ[] |
---|
1427 | >>> I = P*[a,b]###line 1388:_sage_ >>> I = P*[a,b] |
---|
1428 | >>> I.gens() # indirect doctest###line 1389:_sage_ >>> I.gens() # indirect doctest |
---|
1429 | [a, b] |
---|
1430 | >>> I.gens() is I.gens()###line 1391:_sage_ >>> I.gens() is I.gens() |
---|
1431 | True |
---|
1432 | |
---|
1433 | |
---|
1434 | >>> sig_on_count() |
---|
1435 | 0 |
---|
1436 | """ |
---|
1437 | |
---|
1438 | def example_36(): r""">>> set_random_seed(0L) |
---|
1439 | |
---|
1440 | >>> change_warning_output(sys.stdout) |
---|
1441 | |
---|
1442 | |
---|
1443 | Override the cache with a specific value. |
---|
1444 | |
---|
1445 | NOTE: |
---|
1446 | |
---|
1447 | ``None`` is not suitable for a cached value. It would be |
---|
1448 | interpreted as an empty cache, forcing a new computation. |
---|
1449 | |
---|
1450 | EXAMPLES:: |
---|
1451 | |
---|
1452 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 1411:_sage_ >>> P.<a,b,c,d> = QQ[] |
---|
1453 | >>> I = P*[a,b]###line 1412:_sage_ >>> I = P*[a,b] |
---|
1454 | >>> I.gens()###line 1413:_sage_ >>> I.gens() |
---|
1455 | [a, b] |
---|
1456 | >>> I.gens.set_cache('bar')###line 1415:_sage_ >>> I.gens.set_cache('bar') |
---|
1457 | >>> I.gens()###line 1416:_sage_ >>> I.gens() |
---|
1458 | 'bar' |
---|
1459 | |
---|
1460 | The cache can be emptied and thus the original value will |
---|
1461 | be reconstructed:: |
---|
1462 | |
---|
1463 | >>> I.gens.clear_cache()###line 1422:_sage_ >>> I.gens.clear_cache() |
---|
1464 | >>> I.gens()###line 1423:_sage_ >>> I.gens() |
---|
1465 | [a, b] |
---|
1466 | |
---|
1467 | The attempt to assign ``None`` to the cache fails:: |
---|
1468 | |
---|
1469 | >>> I.gens.set_cache(None)###line 1428:_sage_ >>> I.gens.set_cache(None) |
---|
1470 | >>> I.gens()###line 1429:_sage_ >>> I.gens() |
---|
1471 | [a, b] |
---|
1472 | |
---|
1473 | |
---|
1474 | >>> sig_on_count() |
---|
1475 | 0 |
---|
1476 | """ |
---|
1477 | |
---|
1478 | def example_37(): r""">>> set_random_seed(0L) |
---|
1479 | |
---|
1480 | >>> change_warning_output(sys.stdout) |
---|
1481 | |
---|
1482 | |
---|
1483 | Clear the cache dictionary. |
---|
1484 | |
---|
1485 | EXAMPLES:: |
---|
1486 | |
---|
1487 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 1441:_sage_ >>> P.<a,b,c,d> = QQ[] |
---|
1488 | >>> I = P*[a,b]###line 1442:_sage_ >>> I = P*[a,b] |
---|
1489 | >>> I.gens()###line 1443:_sage_ >>> I.gens() |
---|
1490 | [a, b] |
---|
1491 | >>> I.gens.set_cache('bar')###line 1445:_sage_ >>> I.gens.set_cache('bar') |
---|
1492 | >>> I.gens()###line 1446:_sage_ >>> I.gens() |
---|
1493 | 'bar' |
---|
1494 | |
---|
1495 | The cache can be emptied and thus the original value will |
---|
1496 | be reconstructed:: |
---|
1497 | |
---|
1498 | >>> I.gens.clear_cache()###line 1452:_sage_ >>> I.gens.clear_cache() |
---|
1499 | >>> I.gens()###line 1453:_sage_ >>> I.gens() |
---|
1500 | [a, b] |
---|
1501 | |
---|
1502 | |
---|
1503 | >>> sig_on_count() |
---|
1504 | 0 |
---|
1505 | """ |
---|
1506 | |
---|
1507 | def example_38(): r""">>> set_random_seed(0L) |
---|
1508 | |
---|
1509 | >>> change_warning_output(sys.stdout) |
---|
1510 | |
---|
1511 | |
---|
1512 | Answers whether the return value is already in the cache. |
---|
1513 | |
---|
1514 | NOTE: |
---|
1515 | |
---|
1516 | Recall that a cached method without arguments can not cache |
---|
1517 | the return value ``None``. |
---|
1518 | |
---|
1519 | EXAMPLE:: |
---|
1520 | |
---|
1521 | >>> P = QQ['x, y']; (x, y,) = P._first_ngens(2)###line 1470:_sage_ >>> P.<x,y> = QQ[] |
---|
1522 | >>> I = P*[x,y]###line 1471:_sage_ >>> I = P*[x,y] |
---|
1523 | >>> I.gens.is_in_cache()###line 1472:_sage_ >>> I.gens.is_in_cache() |
---|
1524 | False |
---|
1525 | >>> I.gens()###line 1474:_sage_ >>> I.gens() |
---|
1526 | [x, y] |
---|
1527 | >>> I.gens.is_in_cache()###line 1476:_sage_ >>> I.gens.is_in_cache() |
---|
1528 | True |
---|
1529 | |
---|
1530 | |
---|
1531 | >>> sig_on_count() |
---|
1532 | 0 |
---|
1533 | """ |
---|
1534 | |
---|
1535 | def example_39(): r""">>> set_random_seed(0L) |
---|
1536 | |
---|
1537 | >>> change_warning_output(sys.stdout) |
---|
1538 | |
---|
1539 | |
---|
1540 | Get a :class:`CachedMethodCallerNoArgs` bound to a specific |
---|
1541 | instance of the class of the cached method. |
---|
1542 | |
---|
1543 | NOTE: |
---|
1544 | |
---|
1545 | :class:`CachedMethodCallerNoArgs` has a separate ``__get__`` |
---|
1546 | since the categories framework creates and caches the |
---|
1547 | return value of ``CachedMethod.__get__`` with |
---|
1548 | ``inst==None``. |
---|
1549 | |
---|
1550 | This getter attempts to assign a bound method as an |
---|
1551 | attribute to the given instance. If this is not |
---|
1552 | possible (for example, for some extension classes), |
---|
1553 | it is attempted to find an attribute ``__cached_methods``, |
---|
1554 | and store/retrieve the bound method there. In that |
---|
1555 | way, cached methods can be implemented for extension |
---|
1556 | classes deriving from :class:`~sage.structure.parent.Parent` |
---|
1557 | and :class:`~sage.structure.element.Element`. |
---|
1558 | |
---|
1559 | TESTS: |
---|
1560 | |
---|
1561 | Due to the separate ``__get__`` method, it is possible |
---|
1562 | to define a cached method in one class and use it as |
---|
1563 | an attribute of another class. |
---|
1564 | |
---|
1565 | >>> class Foo:###line 1509:_sage_ >>> class Foo: |
---|
1566 | ... def __init__(self, n): |
---|
1567 | ... self.__n = n |
---|
1568 | ... @cached_method |
---|
1569 | ... def f(self): |
---|
1570 | ... return self.__n**Integer(2) |
---|
1571 | ... |
---|
1572 | >>> class Bar:###line 1516:_sage_ >>> class Bar: |
---|
1573 | ... f = Foo.f |
---|
1574 | ... |
---|
1575 | >>> b1 = Bar()###line 1519:_sage_ >>> b1 = Bar() |
---|
1576 | >>> b2 = Bar()###line 1520:_sage_ >>> b2 = Bar() |
---|
1577 | |
---|
1578 | The :class:`CachedMethod` is replaced by an instance of |
---|
1579 | :class:`CachedMethodCallerNoArgs` that is set as an |
---|
1580 | attribute. Hence, we have:: |
---|
1581 | |
---|
1582 | >>> b1.f is b1.f###line 1526:_sage_ >>> b1.f is b1.f |
---|
1583 | True |
---|
1584 | >>> type(b1.f)###line 1528:_sage_ >>> type(b1.f) |
---|
1585 | <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'> |
---|
1586 | |
---|
1587 | Any instance of ``Bar`` gets its own instance of |
---|
1588 | :class:`CachedMethodCaller``:: |
---|
1589 | |
---|
1590 | >>> b1.f is b2.f###line 1534:_sage_ >>> b1.f is b2.f |
---|
1591 | False |
---|
1592 | |
---|
1593 | The method caller knows the instance that it belongs |
---|
1594 | to:: |
---|
1595 | |
---|
1596 | >>> Foo.f._instance is None###line 1540:_sage_ >>> Foo.f._instance is None |
---|
1597 | True |
---|
1598 | >>> b1.f._instance is b1###line 1542:_sage_ >>> b1.f._instance is b1 |
---|
1599 | True |
---|
1600 | >>> b2.f._instance is b2###line 1544:_sage_ >>> b2.f._instance is b2 |
---|
1601 | True |
---|
1602 | |
---|
1603 | |
---|
1604 | >>> sig_on_count() |
---|
1605 | 0 |
---|
1606 | """ |
---|
1607 | |
---|
1608 | def example_40(): r""">>> set_random_seed(0L) |
---|
1609 | |
---|
1610 | >>> change_warning_output(sys.stdout) |
---|
1611 | |
---|
1612 | |
---|
1613 | A decorator that creates a cached version of an instance |
---|
1614 | method of a class. |
---|
1615 | |
---|
1616 | NOTE: |
---|
1617 | |
---|
1618 | For proper behavior, the method must be a pure function |
---|
1619 | (no side effects). Arguments to the method must be hashable. |
---|
1620 | |
---|
1621 | EXAMPLES:: |
---|
1622 | |
---|
1623 | >>> class Foo(object):###line 1580:_sage_ >>> class Foo(object): |
---|
1624 | ... @cached_method |
---|
1625 | ... def f(self, t, x=Integer(2)): |
---|
1626 | ... print 'computing' |
---|
1627 | ... return t**x |
---|
1628 | >>> a = Foo()###line 1585:_sage_ >>> a = Foo() |
---|
1629 | |
---|
1630 | The example shows that the actual computation |
---|
1631 | takes place only once, and that the result is |
---|
1632 | identical for equivalent input:: |
---|
1633 | |
---|
1634 | >>> res = a.f(Integer(3), Integer(2)); res###line 1591:_sage_ >>> res = a.f(3, 2); res |
---|
1635 | computing |
---|
1636 | 9 |
---|
1637 | >>> a.f(t = Integer(3), x = Integer(2)) is res###line 1594:_sage_ >>> a.f(t = 3, x = 2) is res |
---|
1638 | True |
---|
1639 | >>> a.f(Integer(3)) is res###line 1596:_sage_ >>> a.f(3) is res |
---|
1640 | True |
---|
1641 | |
---|
1642 | Note, however, that the :class:`CachedMethod` is replaced by a |
---|
1643 | :class:`CachedMethodCaller` or :class:`CachedMethodCallerNoArgs` |
---|
1644 | as soon as it is bound to an instance or class:: |
---|
1645 | |
---|
1646 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 1603:_sage_ >>> P.<a,b,c,d> = QQ[] |
---|
1647 | >>> I = P*[a,b]###line 1604:_sage_ >>> I = P*[a,b] |
---|
1648 | >>> type(I.__class__.gens)###line 1605:_sage_ >>> type(I.__class__.gens) |
---|
1649 | <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'> |
---|
1650 | |
---|
1651 | So, you would hardly ever see an instance of this class alive. |
---|
1652 | |
---|
1653 | >>> sig_on_count() |
---|
1654 | 0 |
---|
1655 | """ |
---|
1656 | |
---|
1657 | def example_41(): r""">>> set_random_seed(0L) |
---|
1658 | |
---|
1659 | >>> change_warning_output(sys.stdout) |
---|
1660 | |
---|
1661 | |
---|
1662 | EXAMPLES:: |
---|
1663 | |
---|
1664 | >>> class Foo:###line 1614:_sage_ >>> class Foo: |
---|
1665 | ... def __init__(self, x): |
---|
1666 | ... self._x = x |
---|
1667 | ... @cached_method |
---|
1668 | ... def f(self,n): |
---|
1669 | ... return self._x**n |
---|
1670 | ... @cached_method |
---|
1671 | ... def f0(self): |
---|
1672 | ... return self._x**Integer(2) |
---|
1673 | ... |
---|
1674 | >>> a = Foo(Integer(2))###line 1624:_sage_ >>> a = Foo(2) |
---|
1675 | >>> a.f(Integer(2))###line 1625:_sage_ >>> a.f(2) |
---|
1676 | 4 |
---|
1677 | >>> a.f0()###line 1627:_sage_ >>> a.f0() |
---|
1678 | 4 |
---|
1679 | |
---|
1680 | The computations in method ``f`` are tried to store in a |
---|
1681 | dictionary assigned to the instance ``a``:: |
---|
1682 | |
---|
1683 | >>> hasattr(a, '_cache__f')###line 1633:_sage_ >>> hasattr(a, '_cache__f') |
---|
1684 | True |
---|
1685 | >>> a._cache__f###line 1635:_sage_ >>> a._cache__f |
---|
1686 | {((2,), ()): 4} |
---|
1687 | |
---|
1688 | As a shortcut, useful to speed up internal computations, |
---|
1689 | the same dictionary is also available as an attribute |
---|
1690 | of the ``CachedMethodCaller``:: |
---|
1691 | |
---|
1692 | >>> type(a.f)###line 1642:_sage_ >>> type(a.f) |
---|
1693 | <type 'sage.misc.cachefunc.CachedMethodCaller'> |
---|
1694 | >>> a.f.cache is a._cache__f###line 1644:_sage_ >>> a.f.cache is a._cache__f |
---|
1695 | True |
---|
1696 | |
---|
1697 | Note that if the instance ``a`` would not accept attribute |
---|
1698 | assignment, the computations would still be cached in |
---|
1699 | ``a.f.cache``, and they would in fact be preserved when |
---|
1700 | pickling. |
---|
1701 | |
---|
1702 | The cached method ``f0`` accepts no arguments, which allows |
---|
1703 | for an improved way of caching: By an attribute of the cached |
---|
1704 | method itsel. This cache is *only* available in that way, i.e., |
---|
1705 | it is not additionally stored as an attribute of ``a``:: |
---|
1706 | |
---|
1707 | >>> type(a.f0)###line 1657:_sage_ >>> type(a.f0) |
---|
1708 | <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'> |
---|
1709 | >>> a.f0.cache###line 1659:_sage_ >>> a.f0.cache |
---|
1710 | 4 |
---|
1711 | >>> sorted(dir(a))###line 1661:_sage_ >>> sorted(dir(a)) |
---|
1712 | ['__doc__', '__init__', '__module__', '_cache__f', '_x', 'f', 'f0'] |
---|
1713 | |
---|
1714 | |
---|
1715 | >>> sig_on_count() |
---|
1716 | 0 |
---|
1717 | """ |
---|
1718 | |
---|
1719 | def example_42(): r""">>> set_random_seed(0L) |
---|
1720 | |
---|
1721 | >>> change_warning_output(sys.stdout) |
---|
1722 | |
---|
1723 | |
---|
1724 | Call the cached method *without* using the cache. |
---|
1725 | |
---|
1726 | INPUT: |
---|
1727 | |
---|
1728 | - ``inst`` - an instance at which the method is to be called |
---|
1729 | - Further positional or named arguments. |
---|
1730 | |
---|
1731 | EXAMPLES:: |
---|
1732 | |
---|
1733 | >>> class Foo(object):###line 1679:_sage_ >>> class Foo(object): |
---|
1734 | ... def __init__(self, x): |
---|
1735 | ... self._x = x |
---|
1736 | ... @cached_method |
---|
1737 | ... def f(self,n=Integer(2)): |
---|
1738 | ... return self._x**n |
---|
1739 | ... |
---|
1740 | >>> a = Foo(Integer(2))###line 1686:_sage_ >>> a = Foo(2) |
---|
1741 | >>> a.f()###line 1687:_sage_ >>> a.f() |
---|
1742 | 4 |
---|
1743 | |
---|
1744 | Usually, a cached method is indeed cached:: |
---|
1745 | |
---|
1746 | >>> a.f() is a.f()###line 1692:_sage_ >>> a.f() is a.f() |
---|
1747 | True |
---|
1748 | |
---|
1749 | However, when it becomes necessary, one can call it without |
---|
1750 | using the cache. Note that ``a.f`` is an instance of |
---|
1751 | :class:`CachedMethodCaller`. But its |
---|
1752 | :meth:`CachedMethodCaller._instance_call` relies on this |
---|
1753 | method, so, we have an indirect doctest:: |
---|
1754 | |
---|
1755 | >>> a.f._instance_call() is a.f() # indirect doctest###line 1701:_sage_ >>> a.f._instance_call() is a.f() # indirect doctest |
---|
1756 | False |
---|
1757 | >>> a.f._instance_call() == a.f()###line 1703:_sage_ >>> a.f._instance_call() == a.f() |
---|
1758 | True |
---|
1759 | |
---|
1760 | |
---|
1761 | >>> sig_on_count() |
---|
1762 | 0 |
---|
1763 | """ |
---|
1764 | |
---|
1765 | def example_43(): r""">>> set_random_seed(0L) |
---|
1766 | |
---|
1767 | >>> change_warning_output(sys.stdout) |
---|
1768 | |
---|
1769 | |
---|
1770 | Returns the cache dictionary. |
---|
1771 | |
---|
1772 | TESTS:: |
---|
1773 | |
---|
1774 | >>> class Foo:###line 1715:_sage_ >>> class Foo: |
---|
1775 | ... def __init__(self, x): |
---|
1776 | ... self._x = x |
---|
1777 | ... @cached_method |
---|
1778 | ... def f(self,n=Integer(2)): |
---|
1779 | ... return self._x**n |
---|
1780 | ... |
---|
1781 | >>> a = Foo(Integer(2))###line 1722:_sage_ >>> a = Foo(2) |
---|
1782 | >>> a.f()###line 1723:_sage_ >>> a.f() |
---|
1783 | 4 |
---|
1784 | |
---|
1785 | Note that we can not provide a direct test, since ``a.f`` is |
---|
1786 | an instance of :class:`CachedMethodCaller`. But during its |
---|
1787 | initialisation, this method was called in order to provide the |
---|
1788 | cached method caller with its cache, and, if possible, assign |
---|
1789 | it to an attribute of ``a``. So, the following is an indirect |
---|
1790 | doctest:: |
---|
1791 | |
---|
1792 | >>> a.f.get_cache() # indirect doctest###line 1733:_sage_ >>> a.f.get_cache() # indirect doctest |
---|
1793 | {((2,), ()): 4} |
---|
1794 | >>> a._cache__f###line 1735:_sage_ >>> a._cache__f |
---|
1795 | {((2,), ()): 4} |
---|
1796 | |
---|
1797 | |
---|
1798 | >>> sig_on_count() |
---|
1799 | 0 |
---|
1800 | """ |
---|
1801 | |
---|
1802 | def example_44(): r""">>> set_random_seed(0L) |
---|
1803 | |
---|
1804 | >>> change_warning_output(sys.stdout) |
---|
1805 | |
---|
1806 | |
---|
1807 | Get a CachedMethodCaller bound to this specific instance of |
---|
1808 | the class of the cached method. |
---|
1809 | |
---|
1810 | TESTS:: |
---|
1811 | |
---|
1812 | >>> class Foo:###line 1751:_sage_ >>> class Foo: |
---|
1813 | ... @cached_method |
---|
1814 | ... def f(self): |
---|
1815 | ... return Integer(1) |
---|
1816 | ... @cached_method |
---|
1817 | ... def g(self, x,n=Integer(3)): |
---|
1818 | ... return x**n |
---|
1819 | ... |
---|
1820 | >>> a = Foo()###line 1759:_sage_ >>> a = Foo() |
---|
1821 | >>> type(a.f)###line 1760:_sage_ >>> type(a.f) |
---|
1822 | <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'> |
---|
1823 | >>> type(a.g)###line 1762:_sage_ >>> type(a.g) |
---|
1824 | <type 'sage.misc.cachefunc.CachedMethodCaller'> |
---|
1825 | |
---|
1826 | By trac ticket #8611, it is attempted to set the |
---|
1827 | CachedMethodCaller as an attribute of the instance ``a``, |
---|
1828 | replacing the original cached attribute. Therefore, the |
---|
1829 | ``__get__`` method will be used only once, which saves much |
---|
1830 | time. Hence, we have:: |
---|
1831 | |
---|
1832 | >>> a.f is a.f###line 1771:_sage_ >>> a.f is a.f |
---|
1833 | True |
---|
1834 | >>> a.g is a.g###line 1773:_sage_ >>> a.g is a.g |
---|
1835 | True |
---|
1836 | |
---|
1837 | |
---|
1838 | >>> sig_on_count() |
---|
1839 | 0 |
---|
1840 | """ |
---|
1841 | |
---|
1842 | def example_45(): r""">>> set_random_seed(0L) |
---|
1843 | |
---|
1844 | >>> change_warning_output(sys.stdout) |
---|
1845 | |
---|
1846 | |
---|
1847 | A decorator that creates a cached version of an instance |
---|
1848 | method of a class. |
---|
1849 | |
---|
1850 | In contrast to :class:`CachedMethod`, |
---|
1851 | the cache dictionary is an attribute of the parent of |
---|
1852 | the instance to which the method belongs. |
---|
1853 | |
---|
1854 | ASSUMPTION: |
---|
1855 | |
---|
1856 | This way of caching works only if |
---|
1857 | |
---|
1858 | - the instances *have* a parent, and |
---|
1859 | - the instances are hashable (they are part of the cache key). |
---|
1860 | |
---|
1861 | NOTE: |
---|
1862 | |
---|
1863 | For proper behavior, the method must be a pure function (no side |
---|
1864 | effects). If this decorator is used on a method, it will have |
---|
1865 | identical output on equal elements. This is since the element is |
---|
1866 | part of the hash key. Arguments to the method and the instance |
---|
1867 | it is assigned to must be hashable. |
---|
1868 | |
---|
1869 | Examples can be found at :mod:`~sage.misc.cachefunc`. |
---|
1870 | |
---|
1871 | |
---|
1872 | >>> sig_on_count() |
---|
1873 | 0 |
---|
1874 | """ |
---|
1875 | |
---|
1876 | def example_46(): r""">>> set_random_seed(0L) |
---|
1877 | |
---|
1878 | >>> change_warning_output(sys.stdout) |
---|
1879 | |
---|
1880 | |
---|
1881 | Constructs a new method with cache stored in the parent of the instance. |
---|
1882 | |
---|
1883 | See also ``cached_method`` and ``cached_function``. |
---|
1884 | |
---|
1885 | EXAMPLES:: |
---|
1886 | |
---|
1887 | >>> class MyParent(Parent):###line 1857:_sage_ >>> class MyParent(Parent): |
---|
1888 | ... pass |
---|
1889 | >>> class Foo:###line 1859:_sage_ >>> class Foo: |
---|
1890 | ... def __init__(self, x): |
---|
1891 | ... self._x = x |
---|
1892 | ... _parent = MyParent() |
---|
1893 | ... def parent(self): |
---|
1894 | ... return self._parent |
---|
1895 | ... @cached_in_parent_method #indirect doctest |
---|
1896 | ... def f(self): |
---|
1897 | ... return self._x**Integer(2) |
---|
1898 | ... |
---|
1899 | >>> a = Foo(Integer(2))###line 1869:_sage_ >>> a = Foo(2) |
---|
1900 | >>> a.f()###line 1870:_sage_ >>> a.f() |
---|
1901 | 4 |
---|
1902 | >>> hasattr(a.parent(), '_cache__element_f')###line 1872:_sage_ >>> hasattr(a.parent(), '_cache__element_f') |
---|
1903 | True |
---|
1904 | |
---|
1905 | For speeding up internal computations, this dictionary |
---|
1906 | is also accessible as an attribute of the CachedMethodCaller |
---|
1907 | (by trac ticket #8611):: |
---|
1908 | |
---|
1909 | >>> a.parent()._cache__element_f is a.f.cache###line 1879:_sage_ >>> a.parent()._cache__element_f is a.f.cache |
---|
1910 | True |
---|
1911 | |
---|
1912 | >>> sig_on_count() |
---|
1913 | 0 |
---|
1914 | """ |
---|
1915 | |
---|
1916 | def example_47(): r""">>> set_random_seed(0L) |
---|
1917 | |
---|
1918 | >>> change_warning_output(sys.stdout) |
---|
1919 | |
---|
1920 | |
---|
1921 | Returns the cache dictionary, which is stored in the parent. |
---|
1922 | |
---|
1923 | EXAMPLES:: |
---|
1924 | |
---|
1925 | >>> class MyParent(Parent):###line 1891:_sage_ >>> class MyParent(Parent): |
---|
1926 | ... pass |
---|
1927 | ... |
---|
1928 | >>> class Foo:###line 1894:_sage_ >>> class Foo: |
---|
1929 | ... def __init__(self, x): |
---|
1930 | ... self._x = x |
---|
1931 | ... _parent = MyParent() |
---|
1932 | ... def parent(self): |
---|
1933 | ... return self._parent |
---|
1934 | ... def __eq__(self, other): |
---|
1935 | ... return self._x**Integer(2) == other._x**Integer(2) |
---|
1936 | ... def __hash__(self): |
---|
1937 | ... return hash(self._x**Integer(2)) |
---|
1938 | ... def __repr__(self): |
---|
1939 | ... return 'My %s'%self._x |
---|
1940 | ... @cached_in_parent_method |
---|
1941 | ... def f(self): |
---|
1942 | ... return self._x**Integer(3) |
---|
1943 | ... |
---|
1944 | >>> a = Foo(Integer(2))###line 1910:_sage_ >>> a = Foo(2) |
---|
1945 | >>> a.f()###line 1911:_sage_ >>> a.f() |
---|
1946 | 8 |
---|
1947 | >>> a.f.get_cache() #indirect doctest###line 1913:_sage_ >>> a.f.get_cache() #indirect doctest |
---|
1948 | {(My 2, ((), ())): 8} |
---|
1949 | |
---|
1950 | Since the key for the cache depends on equality of |
---|
1951 | the instances, we obtain *identical* result for |
---|
1952 | *equal* instance - even though in this particular |
---|
1953 | example the result is wrong:: |
---|
1954 | |
---|
1955 | >>> b = Foo(-Integer(2))###line 1921:_sage_ >>> b = Foo(-2) |
---|
1956 | >>> a is not b###line 1922:_sage_ >>> a is not b |
---|
1957 | True |
---|
1958 | >>> a == b###line 1924:_sage_ >>> a == b |
---|
1959 | True |
---|
1960 | >>> b.f() is a.f()###line 1926:_sage_ >>> b.f() is a.f() |
---|
1961 | True |
---|
1962 | |
---|
1963 | Non-equal instances do not share the result of |
---|
1964 | the cached method, but they do share the cache:: |
---|
1965 | |
---|
1966 | >>> c = Foo(Integer(3))###line 1932:_sage_ >>> c = Foo(3) |
---|
1967 | >>> c.f()###line 1933:_sage_ >>> c.f() |
---|
1968 | 27 |
---|
1969 | >>> c.f.get_cache() is a.f.get_cache() #indirect doctest###line 1935:_sage_ >>> c.f.get_cache() is a.f.get_cache() #indirect doctest |
---|
1970 | True |
---|
1971 | |
---|
1972 | Note that the cache is also available as an |
---|
1973 | attribute of the cached method, which speeds |
---|
1974 | up internal computations:: |
---|
1975 | |
---|
1976 | >>> a.f.cache is b.f.get_cache() is c.f._cachedmethod._get_instance_cache(c)###line 1942:_sage_ >>> a.f.cache is b.f.get_cache() is c.f._cachedmethod._get_instance_cache(c) |
---|
1977 | True |
---|
1978 | |
---|
1979 | |
---|
1980 | >>> sig_on_count() |
---|
1981 | 0 |
---|
1982 | """ |
---|
1983 | |
---|
1984 | def example_48(): r""">>> set_random_seed(0L) |
---|
1985 | |
---|
1986 | >>> change_warning_output(sys.stdout) |
---|
1987 | |
---|
1988 | |
---|
1989 | Get a CachedMethodCaller bound to this specific instance of |
---|
1990 | the class of the cached-in-parent method. |
---|
1991 | |
---|
1992 | >>> sig_on_count() |
---|
1993 | 0 |
---|
1994 | """ |
---|
1995 | |
---|
1996 | def example_49(): r""">>> set_random_seed(0L) |
---|
1997 | |
---|
1998 | >>> change_warning_output(sys.stdout) |
---|
1999 | |
---|
2000 | |
---|
2001 | FileCache is a dictionary-like class which stores keys and |
---|
2002 | values on disk. The keys take the form of a tuple (A,K) |
---|
2003 | |
---|
2004 | - A is a tuple of objects t where each t is an exact |
---|
2005 | object which is uniquely identified by a short string. |
---|
2006 | |
---|
2007 | - K is a tuple of tuples (s,v) where s is a valid |
---|
2008 | variable name and v is an exact object which is uniquely |
---|
2009 | identified by a short string with letters [a-zA-Z0-9-._] |
---|
2010 | |
---|
2011 | The primary use case is the DiskCachedFunction. If |
---|
2012 | ``memory_cache == True``, we maintain a cache of objects seen |
---|
2013 | during this session in memory -- but we don't load them from |
---|
2014 | disk until necessary. The keys and values are stored in a |
---|
2015 | pair of files: |
---|
2016 | |
---|
2017 | - ``prefix-argstring.key.sobj`` contains the ``key`` only, |
---|
2018 | - ``prefix-argstring.sobj`` contains the tuple ``(key,val)`` |
---|
2019 | |
---|
2020 | where ``self[key] == val``. |
---|
2021 | |
---|
2022 | NOTE: |
---|
2023 | |
---|
2024 | We assume that each FileCache lives in its own directory. |
---|
2025 | Use **extreme** caution if you wish to break that assumption. |
---|
2026 | |
---|
2027 | >>> sig_on_count() |
---|
2028 | 0 |
---|
2029 | """ |
---|
2030 | |
---|
2031 | def example_50(): r""">>> set_random_seed(0L) |
---|
2032 | |
---|
2033 | >>> change_warning_output(sys.stdout) |
---|
2034 | |
---|
2035 | |
---|
2036 | EXAMPLES:: |
---|
2037 | |
---|
2038 | >>> from sage.misc.cachefunc import FileCache###line 2005:_sage_ >>> from sage.misc.cachefunc import FileCache |
---|
2039 | >>> dir = tmp_dir()###line 2006:_sage_ >>> dir = tmp_dir() |
---|
2040 | >>> FC = FileCache(dir, memory_cache = True)###line 2007:_sage_ >>> FC = FileCache(dir, memory_cache = True) |
---|
2041 | >>> FC[((),())] = Integer(1)###line 2008:_sage_ >>> FC[((),())] = 1 |
---|
2042 | >>> FC[((Integer(1),Integer(2)),())] = Integer(2)###line 2009:_sage_ >>> FC[((1,2),())] = 2 |
---|
2043 | >>> FC[((),())]###line 2010:_sage_ >>> FC[((),())] |
---|
2044 | 1 |
---|
2045 | |
---|
2046 | >>> sig_on_count() |
---|
2047 | 0 |
---|
2048 | """ |
---|
2049 | |
---|
2050 | def example_51(): r""">>> set_random_seed(0L) |
---|
2051 | |
---|
2052 | >>> change_warning_output(sys.stdout) |
---|
2053 | |
---|
2054 | |
---|
2055 | Returns the list of files corresponding to self. |
---|
2056 | |
---|
2057 | EXAMPLES:: |
---|
2058 | |
---|
2059 | >>> from sage.misc.cachefunc import FileCache###line 2032:_sage_ >>> from sage.misc.cachefunc import FileCache |
---|
2060 | >>> dir = tmp_dir()###line 2033:_sage_ >>> dir = tmp_dir() |
---|
2061 | >>> FC = FileCache(dir, memory_cache = True, prefix='t')###line 2034:_sage_ >>> FC = FileCache(dir, memory_cache = True, prefix='t') |
---|
2062 | >>> FC[((),())] = Integer(1)###line 2035:_sage_ >>> FC[((),())] = 1 |
---|
2063 | >>> FC[((Integer(1),Integer(2)),())] = Integer(2)###line 2036:_sage_ >>> FC[((1,2),())] = 2 |
---|
2064 | >>> FC[((Integer(1),),(('a',Integer(1)),))] = Integer(3)###line 2037:_sage_ >>> FC[((1,),(('a',1),))] = 3 |
---|
2065 | >>> for f in sorted(FC.file_list()): print f[len(dir):]###line 2038:_sage_ >>> for f in sorted(FC.file_list()): print f[len(dir):] |
---|
2066 | /t-.key.sobj |
---|
2067 | /t-.sobj |
---|
2068 | /t-1_2.key.sobj |
---|
2069 | /t-1_2.sobj |
---|
2070 | /t-a-1.1.key.sobj |
---|
2071 | /t-a-1.1.sobj |
---|
2072 | |
---|
2073 | >>> sig_on_count() |
---|
2074 | 0 |
---|
2075 | """ |
---|
2076 | |
---|
2077 | def example_52(): r""">>> set_random_seed(0L) |
---|
2078 | |
---|
2079 | >>> change_warning_output(sys.stdout) |
---|
2080 | |
---|
2081 | |
---|
2082 | Returns a list of tuples ``(k,v)`` where ``self[k] = v``. |
---|
2083 | |
---|
2084 | EXAMPLES:: |
---|
2085 | |
---|
2086 | >>> from sage.misc.cachefunc import FileCache###line 2061:_sage_ >>> from sage.misc.cachefunc import FileCache |
---|
2087 | >>> dir = tmp_dir()###line 2062:_sage_ >>> dir = tmp_dir() |
---|
2088 | >>> FC = FileCache(dir, memory_cache = False)###line 2063:_sage_ >>> FC = FileCache(dir, memory_cache = False) |
---|
2089 | >>> FC[((),())] = Integer(1)###line 2064:_sage_ >>> FC[((),())] = 1 |
---|
2090 | >>> FC[((Integer(1),Integer(2)),())] = Integer(2)###line 2065:_sage_ >>> FC[((1,2),())] = 2 |
---|
2091 | >>> FC[((Integer(1),),(('a',Integer(1)),))] = Integer(3)###line 2066:_sage_ >>> FC[((1,),(('a',1),))] = 3 |
---|
2092 | >>> I = FC.items()###line 2067:_sage_ >>> I = FC.items() |
---|
2093 | >>> I.sort(); print I###line 2068:_sage_ >>> I.sort(); print I |
---|
2094 | [(((), ()), 1), (((1,), (('a', 1),)), 3), (((1, 2), ()), 2)] |
---|
2095 | |
---|
2096 | >>> sig_on_count() |
---|
2097 | 0 |
---|
2098 | """ |
---|
2099 | |
---|
2100 | def example_53(): r""">>> set_random_seed(0L) |
---|
2101 | |
---|
2102 | >>> change_warning_output(sys.stdout) |
---|
2103 | |
---|
2104 | |
---|
2105 | Returns a list of values that are stored in ``self``. |
---|
2106 | |
---|
2107 | EXAMPLES:: |
---|
2108 | |
---|
2109 | >>> from sage.misc.cachefunc import FileCache###line 2079:_sage_ >>> from sage.misc.cachefunc import FileCache |
---|
2110 | >>> dir = tmp_dir()###line 2080:_sage_ >>> dir = tmp_dir() |
---|
2111 | >>> FC = FileCache(dir, memory_cache = False)###line 2081:_sage_ >>> FC = FileCache(dir, memory_cache = False) |
---|
2112 | >>> FC[((),())] = Integer(1)###line 2082:_sage_ >>> FC[((),())] = 1 |
---|
2113 | >>> FC[((Integer(1),Integer(2)),())] = Integer(2)###line 2083:_sage_ >>> FC[((1,2),())] = 2 |
---|
2114 | >>> FC[((Integer(1),),(('a',Integer(1)),))] = Integer(3)###line 2084:_sage_ >>> FC[((1,),(('a',1),))] = 3 |
---|
2115 | >>> FC[((),(('a',Integer(1)),))] = Integer(4)###line 2085:_sage_ >>> FC[((),(('a',1),))] = 4 |
---|
2116 | >>> v = FC.values()###line 2086:_sage_ >>> v = FC.values() |
---|
2117 | >>> v.sort(); print v###line 2087:_sage_ >>> v.sort(); print v |
---|
2118 | [1, 2, 3, 4] |
---|
2119 | |
---|
2120 | >>> sig_on_count() |
---|
2121 | 0 |
---|
2122 | """ |
---|
2123 | |
---|
2124 | def example_54(): r""">>> set_random_seed(0L) |
---|
2125 | |
---|
2126 | >>> change_warning_output(sys.stdout) |
---|
2127 | |
---|
2128 | |
---|
2129 | Returns a list of keys of ``self``. |
---|
2130 | |
---|
2131 | EXAMPLES:: |
---|
2132 | |
---|
2133 | >>> from sage.misc.cachefunc import FileCache###line 2098:_sage_ >>> from sage.misc.cachefunc import FileCache |
---|
2134 | >>> dir = tmp_dir()###line 2099:_sage_ >>> dir = tmp_dir() |
---|
2135 | >>> FC = FileCache(dir, memory_cache = False)###line 2100:_sage_ >>> FC = FileCache(dir, memory_cache = False) |
---|
2136 | >>> FC[((),())] = Integer(1)###line 2101:_sage_ >>> FC[((),())] = 1 |
---|
2137 | >>> FC[((Integer(1),Integer(2)),())] = Integer(2)###line 2102:_sage_ >>> FC[((1,2),())] = 2 |
---|
2138 | >>> FC[((Integer(1),),(('a',Integer(1)),))] = Integer(3)###line 2103:_sage_ >>> FC[((1,),(('a',1),))] = 3 |
---|
2139 | >>> for k in sorted(FC): print k###line 2104:_sage_ >>> for k in sorted(FC): print k |
---|
2140 | ((), ()) |
---|
2141 | ((1,), (('a', 1),)) |
---|
2142 | ((1, 2), ()) |
---|
2143 | |
---|
2144 | >>> sig_on_count() |
---|
2145 | 0 |
---|
2146 | """ |
---|
2147 | |
---|
2148 | def example_55(): r""">>> set_random_seed(0L) |
---|
2149 | |
---|
2150 | >>> change_warning_output(sys.stdout) |
---|
2151 | |
---|
2152 | |
---|
2153 | Returns a list of keys ``k`` where ``self[k]`` is defined. |
---|
2154 | |
---|
2155 | EXAMPLES:: |
---|
2156 | |
---|
2157 | >>> from sage.misc.cachefunc import FileCache###line 2117:_sage_ >>> from sage.misc.cachefunc import FileCache |
---|
2158 | >>> dir = tmp_dir()###line 2118:_sage_ >>> dir = tmp_dir() |
---|
2159 | >>> FC = FileCache(dir, memory_cache = False)###line 2119:_sage_ >>> FC = FileCache(dir, memory_cache = False) |
---|
2160 | >>> FC[((),())] = Integer(1)###line 2120:_sage_ >>> FC[((),())] = 1 |
---|
2161 | >>> FC[((Integer(1),Integer(2)),())] = Integer(2)###line 2121:_sage_ >>> FC[((1,2),())] = 2 |
---|
2162 | >>> FC[((Integer(1),),(('a',Integer(1)),))] = Integer(3)###line 2122:_sage_ >>> FC[((1,),(('a',1),))] = 3 |
---|
2163 | >>> K = FC.keys()###line 2123:_sage_ >>> K = FC.keys() |
---|
2164 | >>> K.sort(); print K###line 2124:_sage_ >>> K.sort(); print K |
---|
2165 | [((), ()), ((1,), (('a', 1),)), ((1, 2), ())] |
---|
2166 | |
---|
2167 | >>> sig_on_count() |
---|
2168 | 0 |
---|
2169 | """ |
---|
2170 | |
---|
2171 | def example_56(): r""">>> set_random_seed(0L) |
---|
2172 | |
---|
2173 | >>> change_warning_output(sys.stdout) |
---|
2174 | |
---|
2175 | |
---|
2176 | Computes the filename associated with a certain key. |
---|
2177 | |
---|
2178 | EXAMPLES:: |
---|
2179 | |
---|
2180 | >>> from sage.misc.cachefunc import FileCache###line 2140:_sage_ >>> from sage.misc.cachefunc import FileCache |
---|
2181 | >>> dir = tmp_dir() + '/'###line 2141:_sage_ >>> dir = tmp_dir() + '/' |
---|
2182 | >>> FC = FileCache(dir, memory_cache = False, prefix='foo')###line 2142:_sage_ >>> FC = FileCache(dir, memory_cache = False, prefix='foo') |
---|
2183 | >>> N = FC._filename(((Integer(1),Integer(2)), (('a',Integer(1)),('b',Integer(2)))))###line 2143:_sage_ >>> N = FC._filename(((1,2), (('a',1),('b',2)))) |
---|
2184 | >>> print N[len(dir):]###line 2144:_sage_ >>> print N[len(dir):] |
---|
2185 | foo-a-1_b-2.1_2 |
---|
2186 | >>> N = FC._filename(((), (('a',Integer(1)),('b',Integer(2)))))###line 2146:_sage_ >>> N = FC._filename(((), (('a',1),('b',2)))) |
---|
2187 | >>> print N[len(dir):]###line 2147:_sage_ >>> print N[len(dir):] |
---|
2188 | foo-a-1_b-2 |
---|
2189 | >>> N = FC._filename(((Integer(1),Integer(2)), ()))###line 2149:_sage_ >>> N = FC._filename(((1,2), ())) |
---|
2190 | >>> print N[len(dir):]###line 2150:_sage_ >>> print N[len(dir):] |
---|
2191 | foo-1_2 |
---|
2192 | |
---|
2193 | >>> sig_on_count() |
---|
2194 | 0 |
---|
2195 | """ |
---|
2196 | |
---|
2197 | def example_57(): r""">>> set_random_seed(0L) |
---|
2198 | |
---|
2199 | >>> change_warning_output(sys.stdout) |
---|
2200 | |
---|
2201 | |
---|
2202 | Returns ``True`` if ``self[key]`` is defined and False otherwise. |
---|
2203 | |
---|
2204 | EXAMPLES:: |
---|
2205 | |
---|
2206 | >>> from sage.misc.cachefunc import FileCache###line 2168:_sage_ >>> from sage.misc.cachefunc import FileCache |
---|
2207 | >>> dir = tmp_dir() + '/'###line 2169:_sage_ >>> dir = tmp_dir() + '/' |
---|
2208 | >>> FC = FileCache(dir, memory_cache = False, prefix='foo')###line 2170:_sage_ >>> FC = FileCache(dir, memory_cache = False, prefix='foo') |
---|
2209 | >>> k = ((),(('a',Integer(1)),))###line 2171:_sage_ >>> k = ((),(('a',1),)) |
---|
2210 | >>> FC[k] = True###line 2172:_sage_ >>> FC[k] = True |
---|
2211 | >>> FC.has_key(k)###line 2173:_sage_ >>> FC.has_key(k) |
---|
2212 | True |
---|
2213 | >>> FC.has_key(((),()))###line 2175:_sage_ >>> FC.has_key(((),())) |
---|
2214 | False |
---|
2215 | |
---|
2216 | >>> sig_on_count() |
---|
2217 | 0 |
---|
2218 | """ |
---|
2219 | |
---|
2220 | def example_58(): r""">>> set_random_seed(0L) |
---|
2221 | |
---|
2222 | >>> change_warning_output(sys.stdout) |
---|
2223 | |
---|
2224 | |
---|
2225 | Returns the value set by ``self[key] = val``, in this session |
---|
2226 | or a previous one. |
---|
2227 | |
---|
2228 | EXAMPLES:: |
---|
2229 | |
---|
2230 | >>> from sage.misc.cachefunc import FileCache###line 2187:_sage_ >>> from sage.misc.cachefunc import FileCache |
---|
2231 | >>> dir = tmp_dir() + '/'###line 2188:_sage_ >>> dir = tmp_dir() + '/' |
---|
2232 | >>> FC1 = FileCache(dir, memory_cache = False, prefix='foo')###line 2189:_sage_ >>> FC1 = FileCache(dir, memory_cache = False, prefix='foo') |
---|
2233 | >>> FC2 = FileCache(dir, memory_cache = False, prefix='foo')###line 2190:_sage_ >>> FC2 = FileCache(dir, memory_cache = False, prefix='foo') |
---|
2234 | >>> k = ((),(('a',Integer(1)),))###line 2191:_sage_ >>> k = ((),(('a',1),)) |
---|
2235 | >>> t = randint(Integer(0), Integer(1000))###line 2192:_sage_ >>> t = randint(0, 1000) |
---|
2236 | >>> FC1[k] = t###line 2193:_sage_ >>> FC1[k] = t |
---|
2237 | >>> FC2[k] == FC1[k] == t###line 2194:_sage_ >>> FC2[k] == FC1[k] == t |
---|
2238 | True |
---|
2239 | >>> FC1[(Integer(1),Integer(2)),(('a',Integer(4)),('b',Integer(2)))]###line 2196:_sage_ >>> FC1[(1,2),(('a',4),('b',2))] |
---|
2240 | Traceback (most recent call last): |
---|
2241 | ... |
---|
2242 | KeyError: ((1, 2), (('a', 4), ('b', 2))) |
---|
2243 | |
---|
2244 | |
---|
2245 | >>> sig_on_count() |
---|
2246 | 0 |
---|
2247 | """ |
---|
2248 | |
---|
2249 | def example_59(): r""">>> set_random_seed(0L) |
---|
2250 | |
---|
2251 | >>> change_warning_output(sys.stdout) |
---|
2252 | |
---|
2253 | |
---|
2254 | Sets ``self[key] = value`` and stores both key and value on |
---|
2255 | disk. |
---|
2256 | |
---|
2257 | EXAMPLES:: |
---|
2258 | |
---|
2259 | >>> from sage.misc.cachefunc import FileCache###line 2228:_sage_ >>> from sage.misc.cachefunc import FileCache |
---|
2260 | >>> dir = tmp_dir() + '/'###line 2229:_sage_ >>> dir = tmp_dir() + '/' |
---|
2261 | >>> FC1 = FileCache(dir, memory_cache = False, prefix='foo')###line 2230:_sage_ >>> FC1 = FileCache(dir, memory_cache = False, prefix='foo') |
---|
2262 | >>> FC2 = FileCache(dir, memory_cache = False, prefix='foo')###line 2231:_sage_ >>> FC2 = FileCache(dir, memory_cache = False, prefix='foo') |
---|
2263 | >>> k = ((),(('a',Integer(1)),))###line 2232:_sage_ >>> k = ((),(('a',1),)) |
---|
2264 | >>> t = randint(Integer(0), Integer(1000))###line 2233:_sage_ >>> t = randint(0, 1000) |
---|
2265 | >>> FC1[k] = t###line 2234:_sage_ >>> FC1[k] = t |
---|
2266 | >>> FC2[k] == t###line 2235:_sage_ >>> FC2[k] == t |
---|
2267 | True |
---|
2268 | >>> FC1[k] = Integer(2000)###line 2237:_sage_ >>> FC1[k] = 2000 |
---|
2269 | >>> FC2[k]!= t###line 2238:_sage_ >>> FC2[k]!= t |
---|
2270 | True |
---|
2271 | |
---|
2272 | >>> sig_on_count() |
---|
2273 | 0 |
---|
2274 | """ |
---|
2275 | |
---|
2276 | def example_60(): r""">>> set_random_seed(0L) |
---|
2277 | |
---|
2278 | >>> change_warning_output(sys.stdout) |
---|
2279 | |
---|
2280 | |
---|
2281 | Delete the key,value pair from self and unlink the associated |
---|
2282 | files from the file cache. |
---|
2283 | |
---|
2284 | EXAMPLES:: |
---|
2285 | |
---|
2286 | >>> from sage.misc.cachefunc import FileCache###line 2257:_sage_ >>> from sage.misc.cachefunc import FileCache |
---|
2287 | >>> dir = tmp_dir() + '/'###line 2258:_sage_ >>> dir = tmp_dir() + '/' |
---|
2288 | >>> FC1 = FileCache(dir, memory_cache = False, prefix='foo')###line 2259:_sage_ >>> FC1 = FileCache(dir, memory_cache = False, prefix='foo') |
---|
2289 | >>> FC2 = FileCache(dir, memory_cache = False, prefix='foo')###line 2260:_sage_ >>> FC2 = FileCache(dir, memory_cache = False, prefix='foo') |
---|
2290 | >>> k = ((),(('a',Integer(1)),))###line 2261:_sage_ >>> k = ((),(('a',1),)) |
---|
2291 | >>> t = randint(Integer(0), Integer(1000))###line 2262:_sage_ >>> t = randint(0, 1000) |
---|
2292 | >>> FC1[k] = t###line 2263:_sage_ >>> FC1[k] = t |
---|
2293 | >>> del FC2[k]###line 2264:_sage_ >>> del FC2[k] |
---|
2294 | >>> FC1.has_key(k)###line 2265:_sage_ >>> FC1.has_key(k) |
---|
2295 | False |
---|
2296 | |
---|
2297 | >>> sig_on_count() |
---|
2298 | 0 |
---|
2299 | """ |
---|
2300 | |
---|
2301 | def example_61(): r""">>> set_random_seed(0L) |
---|
2302 | |
---|
2303 | >>> change_warning_output(sys.stdout) |
---|
2304 | |
---|
2305 | |
---|
2306 | Works similar to CachedFunction, but instead, we keep the |
---|
2307 | cache on disk (optionally, we keep it in memory too). |
---|
2308 | |
---|
2309 | EXAMPLES:: |
---|
2310 | |
---|
2311 | >>> from sage.misc.cachefunc import DiskCachedFunction###line 2285:_sage_ >>> from sage.misc.cachefunc import DiskCachedFunction |
---|
2312 | >>> dir = tmp_dir()###line 2286:_sage_ >>> dir = tmp_dir() |
---|
2313 | >>> factor = DiskCachedFunction(factor, dir, memory_cache=True)###line 2287:_sage_ >>> factor = DiskCachedFunction(factor, dir, memory_cache=True) |
---|
2314 | >>> f = factor(Integer(2775)); f###line 2288:_sage_ >>> f = factor(2775); f |
---|
2315 | 3 * 5^2 * 37 |
---|
2316 | >>> f is factor(Integer(2775))###line 2290:_sage_ >>> f is factor(2775) |
---|
2317 | True |
---|
2318 | |
---|
2319 | >>> sig_on_count() |
---|
2320 | 0 |
---|
2321 | """ |
---|
2322 | |
---|
2323 | def example_62(): r""">>> set_random_seed(0L) |
---|
2324 | |
---|
2325 | >>> change_warning_output(sys.stdout) |
---|
2326 | |
---|
2327 | |
---|
2328 | EXAMPLES:: |
---|
2329 | |
---|
2330 | >>> from sage.misc.cachefunc import DiskCachedFunction###line 2297:_sage_ >>> from sage.misc.cachefunc import DiskCachedFunction |
---|
2331 | >>> def foo(x): sleep(x)###line 2298:_sage_ >>> def foo(x): sleep(x) |
---|
2332 | >>> dir = tmp_dir()###line 2299:_sage_ >>> dir = tmp_dir() |
---|
2333 | >>> bar = DiskCachedFunction(foo, dir, memory_cache = False)###line 2300:_sage_ >>> bar = DiskCachedFunction(foo, dir, memory_cache = False) |
---|
2334 | >>> w = walltime()###line 2301:_sage_ >>> w = walltime() |
---|
2335 | >>> for i in range(Integer(10)): bar(Integer(1))###line 2302:_sage_ >>> for i in range(10): bar(1) |
---|
2336 | >>> walltime(w) < Integer(2)###line 2303:_sage_ >>> walltime(w) < 2 |
---|
2337 | True |
---|
2338 | |
---|
2339 | >>> sig_on_count() |
---|
2340 | 0 |
---|
2341 | """ |
---|
2342 | |
---|
2343 | def example_63(): r""">>> set_random_seed(0L) |
---|
2344 | |
---|
2345 | >>> change_warning_output(sys.stdout) |
---|
2346 | |
---|
2347 | |
---|
2348 | Decorator for :class:`DiskCachedFunction`. |
---|
2349 | |
---|
2350 | EXAMPLES:: |
---|
2351 | |
---|
2352 | >>> dir = tmp_dir()###line 2317:_sage_ >>> dir = tmp_dir() |
---|
2353 | >>> @disk_cached_function(dir)###line 2318:_sage_ >>> @disk_cached_function(dir) |
---|
2354 | ... def foo(x): return next_prime(Integer(2)**x)%x |
---|
2355 | >>> x = foo(Integer(200));x###line 2320:_sage_ >>> x = foo(200);x |
---|
2356 | 11 |
---|
2357 | >>> @disk_cached_function(dir)###line 2322:_sage_ >>> @disk_cached_function(dir) |
---|
2358 | ... def foo(x): return Integer(1)/x |
---|
2359 | >>> foo(Integer(200))###line 2324:_sage_ >>> foo(200) |
---|
2360 | 11 |
---|
2361 | >>> foo.clear_cache()###line 2326:_sage_ >>> foo.clear_cache() |
---|
2362 | >>> foo(Integer(200))###line 2327:_sage_ >>> foo(200) |
---|
2363 | 1/200 |
---|
2364 | |
---|
2365 | >>> sig_on_count() |
---|
2366 | 0 |
---|
2367 | """ |
---|
2368 | |
---|
2369 | def example_64(): r""">>> set_random_seed(0L) |
---|
2370 | |
---|
2371 | >>> change_warning_output(sys.stdout) |
---|
2372 | |
---|
2373 | |
---|
2374 | EXAMPLES:: |
---|
2375 | |
---|
2376 | >>> dir = tmp_dir()###line 2334:_sage_ >>> dir = tmp_dir() |
---|
2377 | >>> @disk_cached_function(dir, memory_cache=True)###line 2335:_sage_ >>> @disk_cached_function(dir, memory_cache=True) |
---|
2378 | ... def foo(x): return next_prime(Integer(2)**x) |
---|
2379 | >>> x = foo(Integer(200))###line 2337:_sage_ >>> x = foo(200) |
---|
2380 | >>> x is foo(Integer(200))###line 2338:_sage_ >>> x is foo(200) |
---|
2381 | True |
---|
2382 | >>> @disk_cached_function(dir, memory_cache=False)###line 2340:_sage_ >>> @disk_cached_function(dir, memory_cache=False) |
---|
2383 | ... def foo(x): return next_prime(Integer(2)**x) |
---|
2384 | >>> x is foo(Integer(200))###line 2342:_sage_ >>> x is foo(200) |
---|
2385 | False |
---|
2386 | |
---|
2387 | >>> sig_on_count() |
---|
2388 | 0 |
---|
2389 | """ |
---|
2390 | |
---|
2391 | def example_65(): r""">>> set_random_seed(0L) |
---|
2392 | |
---|
2393 | >>> change_warning_output(sys.stdout) |
---|
2394 | |
---|
2395 | |
---|
2396 | EXAMPLES:: |
---|
2397 | |
---|
2398 | >>> dir = tmp_dir()###line 2352:_sage_ >>> dir = tmp_dir() |
---|
2399 | >>> @disk_cached_function(dir)###line 2353:_sage_ >>> @disk_cached_function(dir) |
---|
2400 | ... def foo(x): return ModularSymbols(x) |
---|
2401 | >>> foo(Integer(389))###line 2355:_sage_ >>> foo(389) |
---|
2402 | Modular Symbols space of dimension 65 for Gamma_0(389) of weight 2 with sign 0 over Rational Field |
---|
2403 | |
---|
2404 | >>> sig_on_count() |
---|
2405 | 0 |
---|
2406 | """ |
---|
2407 | |
---|
2408 | def example_66(): r""">>> set_random_seed(0L) |
---|
2409 | |
---|
2410 | >>> change_warning_output(sys.stdout) |
---|
2411 | |
---|
2412 | |
---|
2413 | This class implements an appropriate ``__getstate__`` method that |
---|
2414 | clears the cache of the methods (see @cached_method) before |
---|
2415 | passing them on to the caller, typically the pickle and copy modules. |
---|
2416 | |
---|
2417 | The implemented ``__getstate__`` method calls the ``__getstate__`` |
---|
2418 | methods of classes later in the method resolution |
---|
2419 | order. Therefore, classes which want this behaviour should inherit |
---|
2420 | first from this one. |
---|
2421 | |
---|
2422 | EXAMPLE: |
---|
2423 | |
---|
2424 | In the following example, we create a Python class that inherits |
---|
2425 | from multivariate polynomial ideals, but does not pickle cached |
---|
2426 | values. We provide the definition in Cython, however, since |
---|
2427 | interactive Cython definitions provide introspection by trac |
---|
2428 | ticket #9976, whereas Python definitions don't. |
---|
2429 | :: |
---|
2430 | |
---|
2431 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 2380:_sage_ >>> P.<a,b,c,d> = QQ[] |
---|
2432 | >>> I = P*[a,b]###line 2381:_sage_ >>> I = P*[a,b] |
---|
2433 | >>> classdef = ['from sage.misc.cachefunc import ClearCacheOnPickle',###line 2382:_sage_ >>> classdef = ['from sage.misc.cachefunc import ClearCacheOnPickle', |
---|
2434 | ... 'from sage.all import QQ', |
---|
2435 | ... 'P = QQ["a","b","c","d"]; I = P*[P.gen(0),P.gen(1)]', |
---|
2436 | ... 'class MyClass(ClearCacheOnPickle,I.__class__):', |
---|
2437 | ... ' def __init__(self,ring,gens):', |
---|
2438 | ... ' I.__class__.__init__(self,ring,gens)', |
---|
2439 | ... ' def __getnewargs__(self):', |
---|
2440 | ... ' return (self._Ideal_generic__ring,self._Ideal_generic__gens)'] |
---|
2441 | >>> cython('\n'.join(classdef))###line 2390:_sage_ >>> cython('\n'.join(classdef)) |
---|
2442 | |
---|
2443 | We destroy the cache of two methods of ``I`` on purpose |
---|
2444 | (demonstrating that the two different implementations of cached |
---|
2445 | methods are correctly dealt with). Pickling ``I`` preserves the |
---|
2446 | cache:: |
---|
2447 | |
---|
2448 | >>> I.gens.set_cache('bar')###line 2397:_sage_ >>> I.gens.set_cache('bar') |
---|
2449 | >>> I.groebner_basis.set_cache('foo',algorithm='singular')###line 2398:_sage_ >>> I.groebner_basis.set_cache('foo',algorithm='singular') |
---|
2450 | >>> J = loads(dumps(I))###line 2399:_sage_ >>> J = loads(dumps(I)) |
---|
2451 | >>> J.gens()###line 2400:_sage_ >>> J.gens() |
---|
2452 | 'bar' |
---|
2453 | >>> J.groebner_basis(algorithm='singular')###line 2402:_sage_ >>> J.groebner_basis(algorithm='singular') |
---|
2454 | 'foo' |
---|
2455 | |
---|
2456 | However, if we have an ideal that additionally descends from |
---|
2457 | :class:`ClearCacheOnPickle`, the carefully corrupted cache is not |
---|
2458 | pickled:: |
---|
2459 | |
---|
2460 | >>> A = MyClass(P,[a,b])###line 2409:_sage_ >>> A = MyClass(P,[a,b]) |
---|
2461 | >>> A###line 2410:_sage_ >>> A |
---|
2462 | Ideal (a, b) of Multivariate Polynomial Ring in a, b, c, d over Rational Field |
---|
2463 | >>> A.gens.set_cache('foo')###line 2412:_sage_ >>> A.gens.set_cache('foo') |
---|
2464 | >>> A.groebner_basis.set_cache('bar',algorithm='singular')###line 2413:_sage_ >>> A.groebner_basis.set_cache('bar',algorithm='singular') |
---|
2465 | >>> A.gens()###line 2414:_sage_ >>> A.gens() |
---|
2466 | 'foo' |
---|
2467 | >>> A.groebner_basis(algorithm='singular')###line 2416:_sage_ >>> A.groebner_basis(algorithm='singular') |
---|
2468 | 'bar' |
---|
2469 | >>> B = loads(dumps(A))###line 2418:_sage_ >>> B = loads(dumps(A)) |
---|
2470 | >>> B.gens()###line 2419:_sage_ >>> B.gens() |
---|
2471 | [a, b] |
---|
2472 | >>> B.groebner_basis(algorithm='singular')###line 2421:_sage_ >>> B.groebner_basis(algorithm='singular') |
---|
2473 | [a, b] |
---|
2474 | >>> A.gens()###line 2423:_sage_ >>> A.gens() |
---|
2475 | 'foo' |
---|
2476 | |
---|
2477 | |
---|
2478 | >>> sig_on_count() |
---|
2479 | 0 |
---|
2480 | """ |
---|
2481 | |
---|
2482 | def example_67(): r""">>> set_random_seed(0L) |
---|
2483 | |
---|
2484 | >>> change_warning_output(sys.stdout) |
---|
2485 | |
---|
2486 | |
---|
2487 | The idea is to remove that might provide a cache to some cached method |
---|
2488 | from the return value of the ``__getstate__`` method. |
---|
2489 | |
---|
2490 | EXAMPLE: |
---|
2491 | |
---|
2492 | In the following example, we create a Python class that |
---|
2493 | inherits from multivariate polynomial ideals, but clears the |
---|
2494 | cache as well. |
---|
2495 | |
---|
2496 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 2438:_sage_ >>> P.<a,b,c,d> = QQ[] |
---|
2497 | >>> I = P*[a,b]###line 2439:_sage_ >>> I = P*[a,b] |
---|
2498 | |
---|
2499 | We destroy the cache of two methods if ``I`` on purpose |
---|
2500 | (demonstrating that the two different implementations of cached |
---|
2501 | methods are correctly dealt with). Pickling ``I`` preserves the |
---|
2502 | cache:: |
---|
2503 | |
---|
2504 | >>> I.gens.set_cache('bar')###line 2446:_sage_ >>> I.gens.set_cache('bar') |
---|
2505 | >>> I.groebner_basis.set_cache('foo',algorithm='singular')###line 2447:_sage_ >>> I.groebner_basis.set_cache('foo',algorithm='singular') |
---|
2506 | >>> J = loads(dumps(I))###line 2448:_sage_ >>> J = loads(dumps(I)) |
---|
2507 | >>> J.gens()###line 2449:_sage_ >>> J.gens() |
---|
2508 | 'bar' |
---|
2509 | >>> J.groebner_basis(algorithm='singular')###line 2451:_sage_ >>> J.groebner_basis(algorithm='singular') |
---|
2510 | 'foo' |
---|
2511 | |
---|
2512 | However, if we do the same with a class that additionally |
---|
2513 | descends from :class:`ClearCacheOnPickle`, the cache is not |
---|
2514 | pickled. We provide the definition in Cython, however, since |
---|
2515 | interactive Cython definitions provide introspection by trac |
---|
2516 | ticket #9976, whereas Python definitions don't. |
---|
2517 | :: |
---|
2518 | |
---|
2519 | >>> classdef = ['from sage.misc.cachefunc import ClearCacheOnPickle',###line 2461:_sage_ >>> classdef = ['from sage.misc.cachefunc import ClearCacheOnPickle', |
---|
2520 | ... 'from sage.all import QQ', |
---|
2521 | ... 'from sage.rings.polynomial.multi_polynomial_ideal import MPolynomialIdeal', |
---|
2522 | ... 'class MyClass(ClearCacheOnPickle,MPolynomialIdeal):', |
---|
2523 | ... ' def __init__(self,ring,gens):', |
---|
2524 | ... ' MPolynomialIdeal.__init__(self,ring,gens)', |
---|
2525 | ... ' def __getnewargs__(self):', |
---|
2526 | ... ' return (self._Ideal_generic__ring,self._Ideal_generic__gens)'] |
---|
2527 | >>> cython('\n'.join(classdef))###line 2469:_sage_ >>> cython('\n'.join(classdef)) |
---|
2528 | >>> A = MyClass(P,[a,b])###line 2470:_sage_ >>> A = MyClass(P,[a,b]) |
---|
2529 | >>> A###line 2471:_sage_ >>> A |
---|
2530 | Ideal (a, b) of Multivariate Polynomial Ring in a, b, c, d over Rational Field |
---|
2531 | >>> A.gens.set_cache('foo')###line 2473:_sage_ >>> A.gens.set_cache('foo') |
---|
2532 | >>> A.groebner_basis.set_cache('bar',algorithm='singular')###line 2474:_sage_ >>> A.groebner_basis.set_cache('bar',algorithm='singular') |
---|
2533 | >>> A.gens()###line 2475:_sage_ >>> A.gens() |
---|
2534 | 'foo' |
---|
2535 | >>> A.groebner_basis(algorithm='singular')###line 2477:_sage_ >>> A.groebner_basis(algorithm='singular') |
---|
2536 | 'bar' |
---|
2537 | >>> B = loads(dumps(A))###line 2479:_sage_ >>> B = loads(dumps(A)) |
---|
2538 | >>> B.gens()###line 2480:_sage_ >>> B.gens() |
---|
2539 | [a, b] |
---|
2540 | >>> B.groebner_basis(algorithm='singular')###line 2482:_sage_ >>> B.groebner_basis(algorithm='singular') |
---|
2541 | [a, b] |
---|
2542 | >>> A.gens()###line 2484:_sage_ >>> A.gens() |
---|
2543 | 'foo' |
---|
2544 | |
---|
2545 | And here is why the example works:: |
---|
2546 | |
---|
2547 | >>> ST = I.__getstate__(); ST[Integer(0)],sorted(ST[Integer(1)].items())###line 2489:_sage_ >>> ST = I.__getstate__(); ST[0],sorted(ST[1].items()) |
---|
2548 | (Monoid of ideals of Multivariate Polynomial Ring in a, b, c, d over Rational Field, [('_Ideal_generic__gens', (a, b)), ('_Ideal_generic__ring', Multivariate Polynomial Ring in a, b, c, d over Rational Field), ('_cache__groebner_basis', {(('singular', None, None, False), ()): 'foo'}), ('gens', Cached version of <function gens at 0x...>), ('groebner_basis', Cached version of <function groebner_basis at 0x...>)]) |
---|
2549 | >>> ST = A.__getstate__(); ST[Integer(0)],sorted(ST[Integer(1)].items())###line 2491:_sage_ >>> ST = A.__getstate__(); ST[0],sorted(ST[1].items()) |
---|
2550 | (Monoid of ideals of Multivariate Polynomial Ring in a, b, c, d over Rational Field, [('_Ideal_generic__gens', (a, b)), ('_Ideal_generic__ring', Multivariate Polynomial Ring in a, b, c, d over Rational Field)]) |
---|
2551 | |
---|
2552 | |
---|
2553 | >>> sig_on_count() |
---|
2554 | 0 |
---|
2555 | """ |
---|
2556 | |
---|
2557 | |
---|
2558 | if __name__ == '__main__': |
---|
2559 | verbose = False |
---|
2560 | do_timeit = False |
---|
2561 | output_filename = '/scratch/sking/sage-5.4.beta0/devel/sage-main/sage/misc/cachefunc.pyx.timeit.sobj' |
---|
2562 | |
---|
2563 | import sys |
---|
2564 | sys.path = sys.path + ['/scratch/sking/sage-5.4.beta0/local/bin'] |
---|
2565 | import sagedoctest |
---|
2566 | |
---|
2567 | # execfile('/scratch/sking/sage-5.4.beta0/devel/sage-main/sage/misc/cachefunc.pyx') |
---|
2568 | m = sys.modules[__name__] |
---|
2569 | m.__file__ = '/scratch/sking/sage-5.4.beta0/devel/sage-main/sage/misc/cachefunc.pyx' |
---|
2570 | |
---|
2571 | try: |
---|
2572 | |
---|
2573 | # configure special sage doc test runner |
---|
2574 | runner = sagedoctest.SageDocTestRunner(checker=None, verbose=verbose, optionflags=0) |
---|
2575 | runner._collect_timeit_stats = do_timeit |
---|
2576 | runner._reset_random_seed = True |
---|
2577 | |
---|
2578 | runner = sagedoctest.testmod_returning_runner(m, |
---|
2579 | # filename='/scratch/sking/sage-5.4.beta0/devel/sage-main/sage/misc/cachefunc.pyx', |
---|
2580 | verbose=verbose, |
---|
2581 | globs=globals(), |
---|
2582 | runner=runner) |
---|
2583 | runner.save_timeit_stats_to_file_named(output_filename) |
---|
2584 | except: |
---|
2585 | quit_sage(verbose=False) |
---|
2586 | import traceback |
---|
2587 | traceback.print_exc(file=sys.stdout) |
---|
2588 | sys.exit(255) |
---|
2589 | quit_sage(verbose=False) |
---|
2590 | if runner.failures > 254: |
---|
2591 | sys.exit(254) |
---|
2592 | sys.exit(runner.failures) |
---|