Coverage for /Users/Newville/Codes/xraylarch/larch/builtins.py: 57%
162 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-09 10:08 -0600
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-09 10:08 -0600
1#!/usr/bin/env python
2""" Builtins for larch"""
4import sys
5import time
7from . import utils
8from .utils.show import _larch_builtins as show_builtins
10from .larchlib import parse_group_args, Journal
11from .symboltable import Group
12from .version import show_version
14from . import math
15from . import io
16from . import fitting
17from . import xray
18from . import xrf
19from . import xafs
20from . import xrd
21from . import xrmmap
22from . import wxlib
24from .utils import physical_constants
26__core_modules = [math, fitting, io, xray, xrf, xafs, xrd, xrmmap, wxlib]
28try:
29 from . import epics
30 __core_modules.append(epics)
31except ImportError:
32 pass
34if wxlib.HAS_WXPYTHON:
35 try:
36 from .wxlib import plotter
37 from . import wxmap, wxxas, wxxrd
38 __core_modules.extend([plotter, wxmap, wxxas, wxxrd])
39 except:
40 pass
42# inherit most available symbols from python's __builtins__
43from_builtin = [sym for sym in __builtins__ if not sym.startswith('__')]
45# inherit these from math (many will be overridden by numpy)
46from_math = ('acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh',
47 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'exp',
48 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'hypot',
49 'isinf', 'isnan', 'ldexp', 'log', 'log10', 'log1p', 'modf',
50 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh',
51 'trunc')
53# inherit these from numpy
55from_numpy = ('Inf', 'NAN', 'abs', 'absolute', 'add', 'all', 'allclose',
56 'alltrue', 'amax', 'amin', 'angle', 'any', 'append', 'arange',
57 'arccos', 'arccosh', 'arcsin', 'arcsinh', 'arctan', 'arctan2',
58 'arctanh', 'argmax', 'argmin', 'argsort', 'argwhere', 'around',
59 'array', 'asanyarray', 'asarray', 'atleast_1d', 'atleast_2d',
60 'atleast_3d', 'average', 'bartlett', 'bincount', 'bitwise_and',
61 'bitwise_not', 'bitwise_or', 'bitwise_xor', 'blackman',
62 'broadcast', 'ceil', 'chararray', 'choose', 'clip',
63 'column_stack', 'common_type', 'complex128', 'compress',
64 'concatenate', 'conjugate', 'convolve', 'copysign', 'corrcoef',
65 'correlate', 'cos', 'cosh', 'cov', 'cross', 'cumprod',
66 'cumproduct', 'cumsum', 'datetime_data', 'deg2rad', 'degrees',
67 'delete', 'diag', 'diag_indices', 'diag_indices_from',
68 'diagflat', 'diagonal', 'diff', 'digitize', 'divide', 'dot',
69 'dsplit', 'dstack', 'dtype', 'e', 'ediff1d', 'empty',
70 'empty_like', 'equal', 'exp', 'exp2', 'expand_dims', 'expm1',
71 'extract', 'eye', 'fabs', 'fft', 'fill_diagonal', 'finfo', 'fix',
72 'flatiter', 'flatnonzero', 'fliplr', 'flipud', 'float64',
73 'floor', 'floor_divide', 'fmax', 'fmin', 'fmod', 'format_parser',
74 'frexp', 'frombuffer', 'fromfile', 'fromfunction', 'fromiter',
75 'frompyfunc', 'fromregex', 'fromstring', 'genfromtxt',
76 'getbufsize', 'geterr', 'gradient', 'greater', 'greater_equal',
77 'hamming', 'hanning', 'histogram', 'histogram2d', 'histogramdd',
78 'hsplit', 'hstack', 'hypot', 'i0', 'identity', 'iinfo', 'imag',
79 'in1d', 'index_exp', 'indices', 'inexact', 'inf', 'info',
80 'infty', 'inner', 'insert', 'int32', 'integer', 'interp',
81 'intersect1d', 'invert', 'iscomplex', 'iscomplexobj', 'isfinite',
82 'isinf', 'isnan', 'isneginf', 'isposinf', 'isreal', 'isrealobj',
83 'isscalar', 'issctype', 'iterable', 'kaiser', 'kron', 'ldexp',
84 'left_shift', 'less', 'less_equal', 'linalg', 'linspace',
85 'little_endian', 'loadtxt', 'log', 'log10', 'log1p', 'log2',
86 'logaddexp', 'logaddexp2', 'logical_and', 'logical_not',
87 'logical_or', 'logical_xor', 'logspace', 'longcomplex',
88 'longdouble', 'longfloat', 'longlong', 'mask_indices', 'mat',
89 'matrix', 'max', 'maximum', 'maximum_sctype', 'may_share_memory',
90 'mean', 'median', 'memmap', 'meshgrid', 'mgrid', 'min',
91 'minimum', 'mintypecode', 'mod', 'modf', 'msort', 'multiply',
92 'nan', 'nan_to_num', 'nanargmax', 'nanargmin', 'nanmax',
93 'nanmin', 'nansum', 'nbytes', 'ndarray', 'ndenumerate', 'ndim',
94 'ndindex', 'negative', 'nextafter', 'nonzero', 'not_equal',
95 'number', 'obj2sctype', 'ogrid', 'ones', 'ones_like', 'outer',
96 'packbits', 'percentile', 'pi', 'piecewise', 'place', 'poly',
97 'poly1d', 'polyadd', 'polyder', 'polydiv', 'polyint', 'polymul',
98 'polynomial', 'polysub', 'polyval', 'power', 'prod', 'product',
99 'ptp', 'put', 'putmask', 'rad2deg', 'radians', 'random', 'ravel',
100 'real', 'real_if_close', 'reciprocal', 'record', 'remainder',
101 'repeat', 'reshape', 'resize', 'right_shift', 'rint', 'roll',
102 'rollaxis', 'roots', 'rot90', 'round', 'round_', 'row_stack',
103 'savetxt', 'savez', 'searchsorted', 'select', 'setbufsize',
104 'setdiff1d', 'seterr', 'setxor1d', 'shape', 'short', 'sign',
105 'signbit', 'signedinteger', 'sin', 'sinc', 'single',
106 'singlecomplex', 'sinh', 'size', 'sometrue', 'sort',
107 'sort_complex', 'spacing', 'split', 'sqrt', 'square', 'squeeze',
108 'std', 'subtract', 'sum', 'swapaxes', 'take', 'tan', 'tanh',
109 'tensordot', 'tile', 'trace', 'transpose', 'trapz', 'tri',
110 'tril', 'tril_indices', 'tril_indices_from', 'trim_zeros',
111 'triu', 'triu_indices', 'triu_indices_from', 'true_divide',
112 'trunc', 'ubyte', 'uint', 'uint32', 'union1d', 'unique',
113 'unpackbits', 'unravel_index', 'unsignedinteger', 'unwrap',
114 'ushort', 'vander', 'var', 'vdot', 'vectorize', 'vsplit',
115 'vstack', 'where', 'who', 'zeros', 'zeros_like')
117numpy_renames = {'ln':'log', 'asin':'arcsin', 'acos':'arccos',
118 'atan':'arctan', 'atan2':'arctan2', 'atanh':'arctanh',
119 'acosh':'arccosh', 'asinh':'arcsinh', 'npy_save': 'save',
120 'npy_load': 'load', 'npy_copy': 'copy'}
122constants = {}
123for pconst_name in ('PLANCK_HC', 'AVOGADRO', 'AMU',
124 'R_ELECTRON_ANG','DEG2RAD', 'RAD2DEG'):
125 constants[pconst_name] = getattr(physical_constants, pconst_name)
129## More builtin commands, to set up the larch language:
131# def _group(_larch=None, **kws):
132# """create a group"""
133# if _larch is None:
134# _larch = Group()
135# else:
136# group = _larch.symtable.create_group()
137# for key, val in kws.items():
138# setattr(group, key, val)
139# return group
141def _eval(text, filename=None, _larch=None):
142 """evaluate a string of larch text
143 """
144 if _larch is None:
145 raise Warning("cannot eval string -- larch broken?")
146 return _larch.eval(text, fname=filename)
149def _run(filename=None, new_module=None, _larch=None):
150 "execute the larch text in a file as larch code."
151 if _larch is None:
152 raise Warning(f"cannot run file '{filename:s}' -- larch broken?")
153 return _larch.runfile(filename, new_module=new_module)
155def _reload(mod, _larch=None):
156 """reload a module, either larch or python"""
157 if _larch is None:
158 raise Warning(f"cannot reload module '{mod:s}' -- larch broken?")
160 modname = None
161 if mod in _larch.symtable._sys.modules.values():
162 for k, v in _larch.symtable._sys.modules.items():
163 if v == mod:
164 modname = k
165 elif mod in sys.modules.values():
166 for k, v in sys.modules.items():
167 if v == mod:
168 modname = k
169 elif (mod in _larch.symtable._sys.modules.keys() or
170 mod in sys.modules.keys()):
171 modname = mod
173 if modname is not None:
174 return _larch.import_module(modname, do_reload=True)
176def _help(*args, _larch=None):
177 "show help on topic or object"
178 write = sys.stdout.write
179 if _larch is not None:
180 write = _larch.writer.write
181 buff = []
182 for arg in args:
183 if _larch is not None and isinstance(arg, str):
184 arg= _larch.symtable.get_symbol(arg, create=False)
185 buff.append(repr(arg))
186 if callable(arg) and arg.__doc__ is not None:
187 buff.append(arg.__doc__)
188 buff.append('')
189 write('\n'.join(buff))
192def _journal(*args, **kws):
193 return Journal(*args, **kws)
195def _dir(obj=None, _larch=None):
196 "return directory of an object -- thin wrapper about python builtin"
197 if obj is None and _larch is not None:
198 obj = _larch.symtable
199 return dir(obj)
201def _subgroups(obj):
202 "return list of subgroups"
203 if isinstance(obj, Group):
204 return obj._subgroups()
205 raise Warning("subgroups() argument must be a group")
207def _groupitems(obj):
208 "returns group items as if items() method of a dict"
209 if isinstance(obj, Group):
210 return obj._members().items()
211 raise Warning("group_items() argument must be a group")
213def _which(sym, _larch=None):
214 "return full path of object, or None if object cannot be found"
215 if _larch is None:
216 raise Warning("cannot run which() -- larch broken?")
217 stable = _larch.symtable
218 if hasattr(sym, '__name__'):
219 sym = sym.__name__
220 if isinstance(sym, str) and stable.has_symbol(sym):
221 obj = stable.get_symbol(sym)
222 if obj is not None:
223 return '%s.%s' % (stable.get_parentpath(sym), sym)
224 return None
226def _exists(sym, _larch=None):
227 "return True if a named symbol exists and can be found, False otherwise"
228 return _which(sym, _larch=_larch) is not None
230def _isgroup(obj, _larch=None):
231 """return whether argument is a group or the name of a group
233 With additional arguments (all must be strings), it also tests
234 that the group has an an attribute named for each argument. This
235 can be used to test not only if a object is a Group, but whether
236 it a group with expected arguments.
238 > x = 10
239 > g = group(x=x, y=2)
240 > isgroup(g), isgroup(x)
241 True, False
242 > isgroup('g'), isgroup('x')
243 True, False
244 > isgroup(g, 'x', 'y')
245 True
246 > isgroup(g, 'x', 'y', 'z')
247 False
249 """
250 if (_larch is not None and
251 isinstance(obj, str) and
252 _larch.symtable.has_symbol(obj)):
253 obj = _larch.symtable.get_symbol(obj)
254 return isinstance(obj, Group)
257def _pause(msg='Hit return to continue', _larch=None):
258 if _larch is None:
259 raise Warning("cannot pause() -- larch broken?")
260 return input(msg)
262def _sleep(t=0):
263 return time.sleep(t)
264_sleep.__doc__ = time.sleep.__doc__
266def _time():
267 return time.time()
268_time.__doc__ = time.time.__doc__
270def _strftime(format, *args):
271 return time.strftime(format, *args)
272_strftime.__doc__ = time.strftime.__doc__
275def save_history(filename, session_only=False, maxlines=5000, _larch=None):
276 """save history of larch commands to a file"""
277 _larch.input.history.save(filename, session_only=session_only, maxlines=maxlines)
279def show_history(max_lines=10000, _larch=None):
280 """show history of larch commands"""
281 nhist = min(max_lines, len(_larch.history.buffer))
282 for hline in _larch.history.buffer[-nhist:]:
283 _larch.writer.write("%s\n" % hline)
285def init_display_group(_larch):
286 symtab = _larch.symtable
287 if not symtab.has_group('_sys.display'):
288 symtab.new_group('_sys.display')
289 colors = {}
290 colors['text'] = {'color': None}
291 colors['text2'] = {'color': 'cyan'}
292 colors['comment'] = {'color': 'green'}
293 colors['error'] = {'color': 'red', 'attrs': ['bold']}
294 display = symtab._sys.display
295 display.colors = colors
296 display.use_color = True
297 display.terminal = 'xterm'
300_main_builtins = dict(group=Group, Group=Group, dir=_dir, which=_which,
301 exists=_exists, isgroup=_isgroup,
302 subgroups=_subgroups, group_items=_groupitems,
303 parse_group_args=parse_group_args, pause=_pause,
304 sleep=_sleep, systime=_time, clock=_time,
305 strftime=_strftime, reload=_reload, run=_run,
306 eval=_eval, help=_help, journal=_journal,
307 show_version=show_version,
308 save_history=save_history,
309 show_history=show_history)
311_main_builtins.update(utils._larch_builtins)
312_main_builtins.update(show_builtins)
315# names to fill in the larch namespace at startup
316init_builtins = dict(_builtin=_main_builtins)
318# functions to run (with signature fcn(_larch)) at interpreter startup
319init_funcs = [init_display_group]
321# group/classes to register for save-restore
322init_moddocs = {}
324for cmod in __core_modules:
325 if cmod is None:
326 continue
327 cmodname = getattr(cmod, '_larch_name', cmod.__name__)
328 if cmodname.startswith('larch.'):
329 cmodname = cmodname.replace('larch.', '_')
331 doc = getattr(cmod, '__DOC__', None)
332 if doc is not None:
333 init_moddocs[cmodname] = doc
334 builtins = getattr(cmod, '_larch_builtins', {})
335 init_fcn = getattr(cmod, '_larch_init', None)
337 for bkey, bval in builtins.items():
338 if bkey not in init_builtins:
339 init_builtins[bkey] = bval
340 else:
341 init_builtins[bkey].update(bval)
343 if init_fcn is not None:
344 init_funcs.append(init_fcn)
346# list of supported valid commands -- don't need parentheses for these
347valid_commands = ['run', 'help', 'show', 'which', 'more', 'cd']