@@ -27,7 +27,7 @@ This saves a dictionary with ``w`` as one of the keys::
27
27
28
28
sage: z = load( os. path. join( d. name, 'session'))
29
29
sage: list( z)
30
- ['d ', 'w ' ]
30
+ ['w ', 'd ' ]
31
31
sage: z['w' ]
32
32
2/3
33
33
@@ -68,19 +68,19 @@ AUTHOR:
68
68
import builtins
69
69
import types
70
70
71
- # We want the caller's locals, but locals() is emulated in Cython
72
- cdef caller_locals = builtins.locals
73
-
74
71
# Sage imports
75
72
from sage.misc.persist import load, save, loads, dumps
73
+ from sage.misc.lazy_import import LazyImport
74
+
75
+ # We want the caller's locals, but locals() is emulated in Cython
76
+ cdef caller_locals = builtins.locals
76
77
77
78
# This module-scope variables is used to save the
78
79
# global state of the sage environment at the moment
79
80
# before the user starts typing or running code.
80
81
81
82
state_at_init = None
82
83
83
- CythonFunctionType = type (lambda : None )
84
84
85
85
def init (state = None ):
86
86
"""
@@ -163,9 +163,13 @@ def _is_new_var(x, v, hidden):
163
163
# definitely new.
164
164
if x not in state_at_init:
165
165
return True
166
+ # A lazy import that was there at init time is not new
167
+ if isinstance (v, LazyImport):
168
+ return False
166
169
# A variable could also be new even if it was there at init, say if
167
170
# its value changed.
168
- return x not in state_at_init or state_at_init[x] is not v
171
+ return state_at_init[x] is not v
172
+
169
173
170
174
def show_identifiers (hidden = False ):
171
175
r """
@@ -196,7 +200,7 @@ def show_identifiers(hidden=False):
196
200
sage: a = 10
197
201
sage: factor = 20
198
202
sage: show_identifiers( )
199
- ['a ', 'factor ' ]
203
+ ['factor ', 'a ' ]
200
204
201
205
To get the actual value of a variable from the list, use the
202
206
:func:`globals( ) ` function. ::
@@ -210,27 +214,21 @@ def show_identifiers(hidden=False):
210
214
211
215
sage: _hello = 10
212
216
sage: show_identifiers( )
213
- ['a ', 'factor ' ]
217
+ ['factor ', 'a ' ]
214
218
sage: '_hello' in show_identifiers( hidden=True)
215
219
True
216
220
217
221
Many of the hidden variables are part of the IPython command history, at
218
222
least in command line mode. ::
219
223
220
224
sage: show_identifiers( hidden=True) # random output
221
- ['__', '_i', '_6', '_4', '_3', '_1', '_ii', '__doc__', '__builtins__', '___', '_9', '__name__', '_', 'a', '_i12', '_i14', 'factor', '__file__', '_hello', '_i13', '_i11', '_i10', '_i15', '_i5', '_13', '_10', '_iii', '_i9', '_i8', '_i7', '_i6', '_i4', '_i3', '_i2', '_i1', '_init_cmdline', '_14' ]
225
+ ['__builtin__', '_ih', '_oh', '_dh', 'exit', 'quit', '_', '__', '___',
226
+ '_i', '_ii', '_iii', '_i1', 'factor', '_i2', '_2', '_i3', 'a', '_i4',
227
+ '_i5', '_5', '_i6', '_6', '_i7', '_hello', '_i8', '_8', '_i9', '_9',
228
+ '_i10' ]
222
229
"""
223
- from sage.doctest.forker import DocTestTask
224
230
state = caller_locals()
225
- # Ignore extra variables injected into the global namespace by the doctest
226
- # runner
227
- _none = object ()
228
-
229
- def _in_extra_globals (name , val ):
230
- return val == DocTestTask.extra_globals.get(name, _none)
231
-
232
- return sorted ([x for x, v in state.items() if _is_new_var(x, v, hidden)
233
- and not _in_extra_globals(x, v)])
231
+ return [x for x, v in state.items() if _is_new_var(x, v, hidden)]
234
232
235
233
236
234
def save_session (name = ' sage_session' , verbose = False ):
@@ -293,28 +291,44 @@ def save_session(name='sage_session', verbose=False):
293
291
sage: f = lambda x : x^ 2
294
292
sage: save_session( tmp_f)
295
293
sage: save_session( tmp_f, verbose=True)
296
- Saving...
297
- Not saving f: f is a function, method, class or type
298
294
...
295
+ Not saving f: f is a function or method
299
296
300
297
Something similar happens for cython-defined functions::
301
298
302
299
sage: g = cython_lambda( 'double x', 'x* x + 1. 5')
303
300
sage: save_session( tmp_f, verbose=True)
304
- Saving...
305
- Not saving g: g is a function, method, class or type
306
301
...
302
+ Not saving g: g is a cython function or method
303
+
304
+ And the same for a lazy import::
305
+
306
+ sage: from sage. misc. lazy_import import LazyImport
307
+ sage: lazy_ZZ = LazyImport( 'sage. rings. integer_ring', 'ZZ')
308
+ sage: save_session( tmp_f, verbose=True)
309
+ ...
310
+ Not saving lazy_ZZ: lazy_ZZ is a lazy import
307
311
"""
308
312
state = caller_locals()
309
313
# This dict D will contain the session -- as a dict -- that we will save to disk.
310
314
D = {}
311
315
# We iterate only over the new variables that were defined in this
312
316
# session, since those are the only ones we will save.
313
- for k in show_identifiers(hidden = True ):
317
+ for k in show_identifiers(hidden = True ):
314
318
try :
315
319
x = state[k]
316
- if isinstance (x, (types.FunctionType, types.BuiltinFunctionType, types.BuiltinMethodType, CythonFunctionType, type )):
317
- raise TypeError (' {} is a function, method, class or type' .format(k))
320
+
321
+ if isinstance (x, type ):
322
+ raise TypeError (' {} is a class or type' .format(k))
323
+
324
+ if isinstance (x, (types.FunctionType, types.BuiltinFunctionType, types.BuiltinMethodType)):
325
+ raise TypeError (' {} is a function or method' .format(k))
326
+
327
+ if getattr (type (x), ' __name__' , None ) == ' cython_function_or_method' :
328
+ raise TypeError (' {} is a cython function or method' .format(k))
329
+
330
+ if isinstance (x, LazyImport):
331
+ raise TypeError (' {} is a lazy import' .format(k))
318
332
319
333
# We attempt to pickle *and* unpickle every variable to
320
334
# make *certain* that we can pickled D at the end below.
0 commit comments