Annotation of OpenXM/src/sage/asir.py, Revision 1.3
1.3 ! takayama 1: # $OpenXM: OpenXM/src/sage/asir.py,v 1.2 2019/03/06 02:38:33 takayama Exp $
1.1 takayama 2: from __future__ import print_function
3: from __future__ import absolute_import
4:
5: import os
1.2 takayama 6: from sage.interfaces.expect import Expect, ExpectElement
1.1 takayama 7: from sage.misc.misc import verbose
8:
1.2 takayama 9: ##Ref: @s/2018/09/20180907-sage-asir-proj, Using External Libraries and Interfaces
10: ##Ref: /usr/lib/python2.7/dist-packages/sage/interfaces
11: ##Usage: load("asir.py");
12:
1.1 takayama 13: class Asir(Expect):
14: r"""
15: Interface to the Asir interpreter.
16:
17: EXAMPLES::
18:
1.3 ! takayama 19: sage: asir.evall("F=fctr(x^10-1)") # optional - asir
1.1 takayama 20: """
21:
22: def __init__(self, maxread=None, script_subdirectory=None, logfile=None,
23: server=None, server_tmpdir=None, seed=None, command=None):
24: """
25: EXAMPLES::
26:
27: sage: asir == loads(dumps(asir))
28: True
29: """
30: if command is None:
31: import os
32: command = os.getenv('SAGE_ASIR_COMMAND') or 'openxm ox_texmacs --view sage --quiet --noCopyright'
33: if server is None:
34: import os
35: server = os.getenv('SAGE_ASIR_SERVER') or None
36: Expect.__init__(self,
37: name = 'asir',
38: # We want the prompt sequence to be unique to avoid confusion with syntax error messages containing >>>
39: prompt = 'asir>',
40: # We don't want any pagination of output
41: command = 'openxm ox_texmacs --view sage --quiet --noCopyright',
42: maxread = maxread,
43: server = server,
44: server_tmpdir = server_tmpdir,
45: script_subdirectory = script_subdirectory,
46: restart_on_ctrlc = False,
47: verbose_start = False,
48: logfile = logfile,
49: eval_using_file_cutoff=100)
50: self._seed = seed
51:
52: def set_seed(self, seed=None):
53: """
1.2 takayama 54: Not implemented. Sets the seed for the random number generator
1.1 takayama 55: for this asir interpreter.
1.2 takayama 56: """
57: return 0
1.1 takayama 58:
59: def __reduce__(self):
60: """
61: EXAMPLES::
62:
63: sage: asir.__reduce__()
64: (<function reduce_load_Asir at 0x...>, ())
65: """
66: return reduce_load_Asir, tuple([])
67:
68: def _read_in_file_command(self, filename):
69: """
70: EXAMPLES::
71:
72: sage: filename = tmp_filename()
73: sage: asir._read_in_file_command(filename)
1.2 takayama 74: 'load("...");'
1.1 takayama 75: """
1.2 takayama 76: return 'load("%s");'%filename
1.1 takayama 77:
78: def _quit_string(self):
79: """
80: EXAMPLES::
81:
82: sage: asir._quit_string()
83: 'quit;'
84: """
85: return '!quit;'
86:
87: def _install_hints(self):
88: """
89: Returns hints on how to install Asir.
90:
91: EXAMPLES::
92:
93: sage: print(asir._install_hints())
94: You must get ...
95: """
96: return """
1.2 takayama 97: You must get the program "asir" and "ox_texmacs" in order to use Asir
1.1 takayama 98: from Sage. You can read all about Asir at
1.2 takayama 99: http://www.openxm.org
100: The command openxm must be in the search path.
1.1 takayama 101: """
1.3 ! takayama 102: def evall(self,cmd):
! 103: """
! 104: evalutes the argument immediately. The argument of eval is buffered
! 105: and ; should be added.
! 106: EXAMPLES::
! 107: sage: asir.eval('1+2;'); asir.evall('3+3')
! 108: """
! 109: return self.eval(cmd+';;')
1.1 takayama 110: def _eval_line(self, line, reformat=True, allow_use_file=False,
111: wait_for_prompt=True, restart_if_needed=False):
112: """
113: EXAMPLES::
114:
115: sage: print(asir._eval_line('2+2')) #optional - asir
1.2 takayama 116: '4'
1.1 takayama 117: """
118: from pexpect.exceptions import EOF
119: if not wait_for_prompt:
120: return Expect._eval_line(self, line)
121: if line == '':
122: return ''
123: if self._expect is None:
124: self._start()
125: if allow_use_file and len(line)>3000:
126: return self._eval_line_using_file(line)
127: try:
128: E = self._expect
129: # debug
130: # self._synchronize(cmd='1+%s\n')
131: verbose("in = '%s'"%line,level=3)
132: E.sendline(line)
133: E.expect(self._prompt)
134: out = E.before
135: # debug
136: verbose("out = '%s'"%out,level=3)
137: except EOF:
138: if self._quit_string() in line:
139: return ''
140: except KeyboardInterrupt:
141: self._keyboard_interrupt()
142: try:
143: if reformat:
144: if 'syntax error' in out:
145: raise SyntaxError(out)
146: out = "\n".join(out.splitlines()[1:])
147: return out
148: except NameError:
149: return ''
150:
151: def _keyboard_interrupt(self):
1.2 takayama 152: print("Ctrl-C: Interrupting %s..."%self)
1.1 takayama 153: if self._restart_on_ctrlc:
154: try:
155: self._expect.close(force=1)
156: except pexpect.ExceptionPexpect as msg:
157: raise RuntimeError( "THIS IS A BUG -- PLEASE REPORT. This should never happen.\n" + msg)
158: self._start()
159: raise KeyboardInterrupt("Restarting %s (WARNING: all variables defined in previous session are now invalid)"%self)
160: else:
161: self._expect.send('\003') # control-c
162: raise KeyboardInterrupt("Ctrl-c pressed while running %s"%self)
163:
164: def quit(self, verbose=False):
165: """
166: EXAMPLES::
167:
168: sage: o = Asir()
169: sage: o._start() # optional - asir
170: sage: o.quit(True) # optional - asir
171: Exiting spawned Asir process.
172: """
173: # Don't bother, since it just hangs in some cases, and it
174: # isn't necessary, since asir behaves well with respect
175: # to signals.
176: if not self._expect is None:
177: if verbose:
178: print("Exiting spawned %s process." % self)
179: return
180:
181: def _start(self):
182: """
183: Starts the Asir process.
184:
185: EXAMPLES::
186:
187: sage: o = Asir() # optional - asir
188: sage: o.is_running() # optional - asir
189: False
190: sage: o._start() # optional - asir
191: sage: o.is_running() # optional - asir
192: True
193: """
194: Expect._start(self)
195: # self.eval("page_screen_output=0;")
196: # self.eval("format none;")
197: # set random seed
198: # self.set_seed(self._seed)
199:
200: def _equality_symbol(self):
201: """
202: EXAMPLES::
203:
204: sage: asir('0 == 1') # optional - asir
205: 0
206: sage: asir('1 == 1') # optional - asir
207: 1
208: """
209: return '=='
210:
211: def _true_symbol(self):
212: """
213: EXAMPLES::
214:
215: sage: asir('1 == 1') # optional - asir
216: 1
217: """
218: return '1'
219:
220: def _false_symbol(self):
221: """
222: EXAMPLES::
223:
224: sage: asir('0 == 1') # optional - asir
225: 0
226: """
227: return '0'
228:
229: def set(self, var, value):
230: """
231: Set the variable ``var`` to the given ``value``.
232:
233: EXAMPLES::
234:
1.2 takayama 235: sage: asir.set('X', '2') # optional - asir
236: sage: asir.get('X') # optional - asir
1.1 takayama 237: ' 2'
238: """
1.3 ! takayama 239: cmd = '%s=%s'%(var,value)
! 240: out = self.evall(cmd)
1.1 takayama 241: if out.find("error") != -1 or out.find("Error") != -1:
242: raise TypeError("Error executing code in Asir\nCODE:\n\t%s\nAsir ERROR:\n\t%s"%(cmd, out))
243:
244: def get(self, var):
245: """
246: Get the value of the variable ``var``.
247:
248: EXAMPLES::
249:
1.2 takayama 250: sage: asir.set('X', '2') # optional - asir
251: sage: asir.get('X') # optional - asir
1.1 takayama 252: ' 2'
253: """
1.3 ! takayama 254: s = self.evall('%s;'%var)
1.1 takayama 255: i = s.find('=')
256: return s[i+1:]
257:
258: def console(self):
259: """
260: Spawn a new Asir command-line session.
261:
262: This requires that the optional asir program be installed and in
263: your PATH, but no optional Sage packages need be installed.
264:
265: EXAMPLES::
266:
1.2 takayama 267: sage: asir_console()
268: This is Risa/Asir, ....
1.1 takayama 269: ...
1.2 takayama 270: [nnnn] 2+3;
271: 5
272: [nnnn] quit();
273:
274: quit(); exits the asir console and returns you to Sage.
1.1 takayama 275: """
276: asir_console()
277:
278: def version(self):
279: """
280: Return the version of Asir.
1.2 takayama 281: bug: it returns error because sage tries to set sage0=version();
282: insread of Sage0=version();
1.1 takayama 283: OUTPUT: string
284:
285: EXAMPLES::
286:
287: sage: v = asir.version() # optional - asir
288: sage: v # optional - asir; random
289: '2.13.7'
290:
291: """
292: return str(self("version()")).strip()
293:
294: def _object_class(self):
295: """
296: EXAMPLES::
297:
298: sage: asir._object_class()
299: <class 'sage.interfaces.asir.AsirElement'>
300: """
301: return AsirElement
302:
303:
304: asir_functions = set()
305:
1.2 takayama 306: #Todo, the following class has not yet been implemented.
307: # These are sample interface with octave.
1.1 takayama 308: class AsirElement(ExpectElement):
309: def _get_sage_ring(self):
310: r"""
311: TESTS::
312:
313: sage: asir('1')._get_sage_ring() # optional - asir
314: Real Double Field
315: sage: asir('I')._get_sage_ring() # optional - asir
316: Complex Double Field
317: sage: asir('[]')._get_sage_ring() # optional - asir
318: Real Double Field
319: """
320: if self.isinteger():
321: import sage.rings.integer_ring
322: return sage.rings.integer_ring.ZZ
323: elif self.isreal():
324: import sage.rings.real_double
325: return sage.rings.real_double.RDF
326: elif self.iscomplex():
327: import sage.rings.complex_double
328: return sage.rings.complex_double.CDF
329: else:
330: raise TypeError("no Sage ring associated to this element.")
331:
332: def __nonzero__(self):
333: r"""
334: Test whether this element is nonzero.
335:
336: EXAMPLES::
337:
338: sage: bool(asir('0')) # optional - asir
339: False
340: sage: bool(asir('[]')) # optional - asir
341: False
342: sage: bool(asir('[0,0]')) # optional - asir
343: False
344: sage: bool(asir('[0,0,0;0,0,0]')) # optional - asir
345: False
346:
347: sage: bool(asir('0.1')) # optional - asir
348: True
349: sage: bool(asir('[0,1,0]')) # optional - asir
350: True
351: sage: bool(asir('[0,0,-0.1;0,0,0]')) # optional - asir
352: True
353: """
354: return str(self) != ' [](0x0)' and any(x != '0' for x in str(self).split())
355:
356: def _matrix_(self, R=None):
357: r"""
358: Return Sage matrix from this asir element.
359:
360: EXAMPLES::
361:
362: sage: A = asir('[1,2;3,4.5]') # optional - asir
363: sage: matrix(A) # optional - asir
364: [1.0 2.0]
365: [3.0 4.5]
366: sage: _.base_ring() # optional - asir
367: Real Double Field
368:
369: sage: A = asir('[I,1;-1,0]') # optional - asir
370: sage: matrix(A) # optional - asir
371: [1.0*I 1.0]
372: [ -1.0 0.0]
373: sage: _.base_ring() # optional - asir
374: Complex Double Field
375:
376: sage: A = asir('[1,2;3,4]') # optional - asir
377: sage: matrix(ZZ, A) # optional - asir
378: [1 2]
379: [3 4]
380: sage: A = asir('[1,2;3,4.5]') # optional - asir
381: sage: matrix(RR, A) # optional - asir
382: [1.00000000000000 2.00000000000000]
383: [3.00000000000000 4.50000000000000]
384: """
385: if not self.ismatrix():
386: raise TypeError('not an asir matrix')
387: if R is None:
388: R = self._get_sage_ring()
389:
390: s = str(self).strip('\n ')
391: w = [u.strip().split(' ') for u in s.split('\n')]
392: nrows = len(w)
393: ncols = len(w[0])
394:
395: if self.iscomplex():
396: w = [[to_complex(x,R) for x in row] for row in w]
397:
398: from sage.matrix.all import MatrixSpace
399: return MatrixSpace(R, nrows, ncols)(w)
400:
401: def _vector_(self, R=None):
402: r"""
403: Return Sage vector from this asir element.
404:
405: EXAMPLES::
406:
407: sage: A = asir('[1,2,3,4]') # optional - asir
408: sage: vector(ZZ, A) # optional - asir
409: (1, 2, 3, 4)
410: sage: A = asir('[1,2.3,4.5]') # optional - asir
411: sage: vector(A) # optional - asir
412: (1.0, 2.3, 4.5)
413: sage: A = asir('[1,I]') # optional - asir
414: sage: vector(A) # optional - asir
415: (1.0, 1.0*I)
416: """
417: oc = self.parent()
418: if not self.isvector():
419: raise TypeError('not an asir vector')
420: if R is None:
421: R = self._get_sage_ring()
422:
423: s = str(self).strip('\n ')
424: w = s.strip().split(' ')
425: nrows = len(w)
426:
427: if self.iscomplex():
428: w = [to_complex(x, R) for x in w]
429:
430: from sage.modules.free_module import FreeModule
431: return FreeModule(R, nrows)(w)
432:
433: def _scalar_(self):
434: """
435: Return Sage scalar from this asir element.
436:
437: EXAMPLES::
438:
439: sage: A = asir('2833') # optional - asir
440: sage: As = A.sage(); As # optional - asir
441: 2833.0
442: sage: As.parent() # optional - asir
443: Real Double Field
444:
445: sage: B = sqrt(A) # optional - asir
446: sage: Bs = B.sage(); Bs # optional - asir
447: 53.2259
448: sage: Bs.parent() # optional - asir
449: Real Double Field
450:
451: sage: C = sqrt(-A) # optional - asir
452: sage: Cs = C.sage(); Cs # optional - asir
453: 53.2259*I
454: sage: Cs.parent() # optional - asir
455: Complex Double Field
456: """
457: if not self.isscalar():
458: raise TypeError("not an asir scalar")
459:
460: R = self._get_sage_ring()
461: if self.iscomplex():
462: return to_complex(str(self), R)
463: else:
464: return R(str(self))
465:
466: def _sage_(self):
467: """
468: Try to parse the asir object and return a sage object.
469:
470: EXAMPLES::
471:
472: sage: A = asir('2833') # optional - asir
473: sage: A.sage() # optional - asir
474: 2833.0
475: sage: B = sqrt(A) # optional - asir
476: sage: B.sage() # optional - asir
477: 53.2259
478: sage: C = sqrt(-A) # optional - asir
479: sage: C.sage() # optional - asir
480: 53.2259*I
481: sage: A = asir('[1,2,3,4]') # optional - asir
482: sage: A.sage() # optional - asir
483: (1.0, 2.0, 3.0, 4.0)
484: sage: A = asir('[1,2.3,4.5]') # optional - asir
485: sage: A.sage() # optional - asir
486: (1.0, 2.3, 4.5)
487: sage: A = asir('[1,2.3+I,4.5]') # optional - asir
488: sage: A.sage() # optional - asir
489: (1.0, 2.3 + 1.0*I, 4.5)
490: """
491: if self.isscalar():
492: return self._scalar_()
493: elif self.isvector():
494: return self._vector_()
495: elif self.ismatrix():
496: return self._matrix_()
497: else:
498: raise NotImplementedError('asir type is not recognized')
499:
500: # An instance
501: asir = Asir()
502:
503: def reduce_load_Asir():
504: """
505: EXAMPLES::
506:
507: sage: from sage.interfaces.asir import reduce_load_Asir
508: sage: reduce_load_Asir()
509: Asir
510: """
511: return asir
512:
513:
514: def asir_console():
515: """
516: Spawn a new Asir command-line session.
517:
518: This requires that the optional asir program be installed and in
519: your PATH, but no optional Sage packages need be installed.
520:
521: EXAMPLES::
522:
523: sage: asir_console() # not tested
1.2 takayama 524: This is Risa/Asir ....
1.1 takayama 525: ...
1.2 takayama 526: [nnnn] 2+3;
527: 5
528: [nnnn] quit();
529:
530: quit(); exits the asir console and returns you to Sage.
1.1 takayama 531: """
532: from sage.repl.rich_output.display_manager import get_display_manager
533: if not get_display_manager().is_in_terminal():
534: raise RuntimeError('Can use the console only in the terminal. Try %%asir magics instead.')
1.2 takayama 535: os.system('openxm fep asir') # with asir prompt
1.1 takayama 536: # os.system('openxm asir -quiet')
537:
538:
539: def asir_version():
540: """
541: DEPRECATED: Return the version of Asir installed.
542:
543: EXAMPLES::
544:
545: sage: asir_version() # optional - asir
546: doctest:...: DeprecationWarning: This has been deprecated. Use
547: asir.version() instead
548: See http://trac.sagemath.org/21135 for details.
549: '...'
550: """
551: from sage.misc.superseded import deprecation
552: deprecation(21135, "This has been deprecated. Use asir.version() instead")
553: return asir.version()
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>