Coverage for larch/builtins.py: 57%
161 statements
« prev ^ index » next coverage.py v7.6.0, created at 2024-10-16 21:04 +0000
« prev ^ index » next coverage.py v7.6.0, created at 2024-10-16 21:04 +0000
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
54from_numpy = ('abs', 'add', 'all', 'amax', 'amin', 'angle', 'any', 'append',
55 'arange', 'arccos', 'arccosh', 'arcsin', 'arcsinh', 'arctan', 'arctan2',
56 'arctanh', 'argmax', 'argmin', 'argsort', 'argwhere', 'around', 'array',
57 'asarray', 'atleast_1d', 'atleast_2d', 'atleast_3d', 'average', 'bartlett',
58 'bitwise_and', 'bitwise_not', 'bitwise_or', 'bitwise_xor', 'blackman',
59 'broadcast', 'ceil', 'choose', 'clip', 'column_stack', 'common_type',
60 'complex128', 'compress', 'concatenate', 'conjugate', 'convolve',
61 'copysign', 'corrcoef', 'correlate', 'cos', 'cosh', 'cov', 'cross',
62 'cumprod', 'cumsum', 'datetime_data', 'deg2rad', 'degrees', 'delete',
63 'diag', 'diag_indices', 'diag_indices_from', 'diagflat', 'diagonal',
64 'diff', 'digitize', 'divide', 'dot', 'dsplit', 'dstack', 'dtype', 'e',
65 'ediff1d', 'empty', 'empty_like', 'equal', 'exp', 'exp2', 'expand_dims',
66 'expm1', 'extract', 'eye', 'fabs', 'fft', 'fill_diagonal', 'finfo', 'fix',
67 'flatiter', 'flatnonzero', 'fliplr', 'flipud', 'float64', 'floor',
68 'floor_divide', 'fmax', 'fmin', 'fmod', 'format_parser', 'frexp',
69 'frombuffer', 'fromfile', 'fromfunction', 'fromiter', 'frompyfunc',
70 'fromregex', 'fromstring', 'genfromtxt', 'getbufsize', 'geterr',
71 'gradient', 'greater', 'greater_equal', 'hamming', 'hanning', 'histogram',
72 'histogram2d', 'histogramdd', 'hsplit', 'hstack', 'hypot', 'i0',
73 'identity', 'iinfo', 'imag', 'indices', 'inexact', 'inf', 'info', 'inner',
74 'insert', 'int32', 'integer', 'interp', 'intersect1d', 'invert',
75 'iscomplex', 'iscomplexobj', 'isfinite', 'isinf', 'isnan', 'isneginf',
76 'isposinf', 'isreal', 'isrealobj', 'isscalar', 'iterable', 'kaiser',
77 'kron', 'ldexp', 'left_shift', 'less', 'less_equal', 'linalg', 'linspace',
78 'little_endian', 'loadtxt', 'log', 'log10', 'log1p', 'log2', 'logaddexp',
79 'logaddexp2', 'logical_and', 'logical_not', 'logical_or', 'logical_xor',
80 'logspace', 'longdouble', 'longlong', 'mask_indices', 'matrix', 'maximum',
81 'may_share_memory', 'mean', 'median', 'memmap', 'meshgrid', 'minimum',
82 'mintypecode', 'mod', 'modf', 'msort', 'multiply', 'nan', 'nan_to_num',
83 'nanargmax', 'nanargmin', 'nanmax', 'nanmin', 'nansum', 'ndarray',
84 'ndenumerate', 'ndim', 'ndindex', 'negative', 'nextafter', 'nonzero',
85 'not_equal', 'number', 'ones', 'ones_like', 'outer', 'packbits',
86 'percentile', 'pi', 'piecewise', 'place', 'poly', 'poly1d', 'polyadd',
87 'polyder', 'polydiv', 'polyint', 'polymul', 'polynomial', 'polysub',
88 'polyval', 'power', 'prod', 'ptp', 'put', 'putmask', 'rad2deg', 'radians',
89 'random', 'ravel', 'real', 'real_if_close', 'reciprocal', 'record',
90 'remainder', 'repeat', 'reshape', 'resize', 'right_shift', 'rint', 'roll',
91 'rollaxis', 'roots', 'rot90', 'round', 'searchsorted', 'select',
92 'setbufsize', 'setdiff1d', 'seterr', 'setxor1d', 'shape', 'short', 'sign',
93 'signbit', 'signedinteger', 'sin', 'sinc', 'single', 'sinh', 'size',
94 'sort', 'sort_complex', 'spacing', 'split', 'sqrt', 'square', 'squeeze',
95 'std', 'subtract', 'sum', 'swapaxes', 'take', 'tan', 'tanh', 'tensordot',
96 'tile', 'trace', 'transpose', 'tri', 'tril', 'tril_indices',
97 'tril_indices_from', 'trim_zeros', 'triu', 'triu_indices',
98 'triu_indices_from', 'true_divide', 'trunc', 'ubyte', 'uint', 'uint32',
99 'union1d', 'unique', 'unravel_index', 'unsignedinteger', 'unwrap',
100 'ushort', 'vander', 'var', 'vdot', 'vectorize', 'vsplit', 'vstack',
101 'where', 'zeros', 'zeros_like')
103numpy_renames = {'ln':'log', 'asin':'arcsin', 'acos':'arccos',
104 'atan':'arctan', 'atan2':'arctan2', 'atanh':'arctanh',
105 'acosh':'arccosh', 'asinh':'arcsinh', 'npy_save': 'save',
106 'npy_load': 'load', 'npy_copy': 'copy'}
108constants = {}
109for pconst_name in ('PLANCK_HC', 'AVOGADRO', 'AMU',
110 'R_ELECTRON_ANG','DEG2RAD', 'RAD2DEG'):
111 constants[pconst_name] = getattr(physical_constants, pconst_name)
115## More builtin commands, to set up the larch language:
117# def _group(_larch=None, **kws):
118# """create a group"""
119# if _larch is None:
120# _larch = Group()
121# else:
122# group = _larch.symtable.create_group()
123# for key, val in kws.items():
124# setattr(group, key, val)
125# return group
127def _eval(text, filename=None, _larch=None):
128 """evaluate a string of larch text
129 """
130 if _larch is None:
131 raise Warning("cannot eval string -- larch broken?")
132 return _larch.eval(text, fname=filename)
135def _run(filename=None, new_module=None, _larch=None):
136 "execute the larch text in a file as larch code."
137 if _larch is None:
138 raise Warning(f"cannot run file '{filename:s}' -- larch broken?")
139 return _larch.runfile(filename, new_module=new_module)
141def _reload(mod, _larch=None):
142 """reload a module, either larch or python"""
143 if _larch is None:
144 raise Warning(f"cannot reload module '{mod:s}' -- larch broken?")
146 modname = None
147 if mod in _larch.symtable._sys.modules.values():
148 for k, v in _larch.symtable._sys.modules.items():
149 if v == mod:
150 modname = k
151 elif mod in sys.modules.values():
152 for k, v in sys.modules.items():
153 if v == mod:
154 modname = k
155 elif (mod in _larch.symtable._sys.modules.keys() or
156 mod in sys.modules.keys()):
157 modname = mod
159 if modname is not None:
160 return _larch.import_module(modname, do_reload=True)
162def _help(*args, _larch=None):
163 "show help on topic or object"
164 write = sys.stdout.write
165 if _larch is not None:
166 write = _larch.writer.write
167 buff = []
168 for arg in args:
169 if _larch is not None and isinstance(arg, str):
170 arg= _larch.symtable.get_symbol(arg, create=False)
171 buff.append(repr(arg))
172 if callable(arg) and arg.__doc__ is not None:
173 buff.append(arg.__doc__)
174 buff.append('')
175 write('\n'.join(buff))
178def _journal(*args, **kws):
179 return Journal(*args, **kws)
181def _dir(obj=None, _larch=None):
182 "return directory of an object -- thin wrapper about python builtin"
183 if obj is None and _larch is not None:
184 obj = _larch.symtable
185 return dir(obj)
187def _subgroups(obj):
188 "return list of subgroups"
189 if isinstance(obj, Group):
190 return obj._subgroups()
191 raise Warning("subgroups() argument must be a group")
193def _groupitems(obj):
194 "returns group items as if items() method of a dict"
195 if isinstance(obj, Group):
196 return obj._members().items()
197 raise Warning("group_items() argument must be a group")
199def _which(sym, _larch=None):
200 "return full path of object, or None if object cannot be found"
201 if _larch is None:
202 raise Warning("cannot run which() -- larch broken?")
203 stable = _larch.symtable
204 if hasattr(sym, '__name__'):
205 sym = sym.__name__
206 if isinstance(sym, str) and stable.has_symbol(sym):
207 obj = stable.get_symbol(sym)
208 if obj is not None:
209 return '%s.%s' % (stable.get_parentpath(sym), sym)
210 return None
212def _exists(sym, _larch=None):
213 "return True if a named symbol exists and can be found, False otherwise"
214 return _which(sym, _larch=_larch) is not None
216def _isgroup(obj, _larch=None):
217 """return whether argument is a group or the name of a group
219 With additional arguments (all must be strings), it also tests
220 that the group has an an attribute named for each argument. This
221 can be used to test not only if a object is a Group, but whether
222 it a group with expected arguments.
224 > x = 10
225 > g = group(x=x, y=2)
226 > isgroup(g), isgroup(x)
227 True, False
228 > isgroup('g'), isgroup('x')
229 True, False
230 > isgroup(g, 'x', 'y')
231 True
232 > isgroup(g, 'x', 'y', 'z')
233 False
235 """
236 if (_larch is not None and
237 isinstance(obj, str) and
238 _larch.symtable.has_symbol(obj)):
239 obj = _larch.symtable.get_symbol(obj)
240 return isinstance(obj, Group)
243def _pause(msg='Hit return to continue', _larch=None):
244 if _larch is None:
245 raise Warning("cannot pause() -- larch broken?")
246 return input(msg)
248def _sleep(t=0):
249 return time.sleep(t)
250_sleep.__doc__ = time.sleep.__doc__
252def _time():
253 return time.time()
254_time.__doc__ = time.time.__doc__
256def _strftime(format, *args):
257 return time.strftime(format, *args)
258_strftime.__doc__ = time.strftime.__doc__
261def save_history(filename, session_only=False, maxlines=5000, _larch=None):
262 """save history of larch commands to a file"""
263 _larch.input.history.save(filename, session_only=session_only, maxlines=maxlines)
265def show_history(max_lines=10000, _larch=None):
266 """show history of larch commands"""
267 nhist = min(max_lines, len(_larch.history.buffer))
268 for hline in _larch.history.buffer[-nhist:]:
269 _larch.writer.write("%s\n" % hline)
271def init_display_group(_larch):
272 symtab = _larch.symtable
273 if not symtab.has_group('_sys.display'):
274 symtab.new_group('_sys.display')
275 colors = {}
276 colors['text'] = {'color': None}
277 colors['text2'] = {'color': 'cyan'}
278 colors['comment'] = {'color': 'green'}
279 colors['error'] = {'color': 'red', 'attrs': ['bold']}
280 display = symtab._sys.display
281 display.colors = colors
282 display.use_color = True
283 display.terminal = 'xterm'
286_main_builtins = dict(group=Group, Group=Group, dir=_dir, which=_which,
287 exists=_exists, isgroup=_isgroup,
288 subgroups=_subgroups, group_items=_groupitems,
289 parse_group_args=parse_group_args, pause=_pause,
290 sleep=_sleep, systime=_time, clock=_time,
291 strftime=_strftime, reload=_reload, run=_run,
292 eval=_eval, help=_help, journal=_journal,
293 show_version=show_version,
294 save_history=save_history,
295 show_history=show_history)
297_main_builtins.update(utils._larch_builtins)
298_main_builtins.update(show_builtins)
301# names to fill in the larch namespace at startup
302init_builtins = dict(_builtin=_main_builtins)
304# functions to run (with signature fcn(_larch)) at interpreter startup
305init_funcs = [init_display_group]
307# group/classes to register for save-restore
308init_moddocs = {}
310for cmod in __core_modules:
311 if cmod is None:
312 continue
313 cmodname = getattr(cmod, '_larch_name', cmod.__name__)
314 if cmodname.startswith('larch.'):
315 cmodname = cmodname.replace('larch.', '_')
317 doc = getattr(cmod, '__DOC__', None)
318 if doc is not None:
319 init_moddocs[cmodname] = doc
320 builtins = getattr(cmod, '_larch_builtins', {})
321 init_fcn = getattr(cmod, '_larch_init', None)
323 for bkey, bval in builtins.items():
324 if bkey not in init_builtins:
325 init_builtins[bkey] = bval
326 else:
327 init_builtins[bkey].update(bval)
329 if init_fcn is not None:
330 init_funcs.append(init_fcn)
332# list of supported valid commands -- don't need parentheses for these
333valid_commands = ['run', 'help', 'show', 'which', 'more', 'cd']