Skip to content

Commit 94c3fb6

Browse files
committed
src/sage/interfaces/maxima_abstract.py: reimplement _commands()
The maxima _commands() method was implemented in terms of the tab-completion method, completions(), which goes one-letter-at-a-time and is very slow as a result. We reimplement it directly to call maxima's apropos() with the empty string. This gets all commands in one shot. We also clean up the list of commands a little by excluding some junk results. The diff (eliminated elements) from the old list to the new one is, {'SPLITS\\IN\\Q', 'erf_%iargs', 'exp-form', 'is-boole-eval', 'is-boole-verify', 'maybe-boole-eval', 'maybe-boole-verify', 'sstatus-aux', 'time\\/\\/call', 'unknown\\?', 'zeta%pi'} The faster method should help avoid warnings in the CI about the test being too slow.
1 parent 4cdd703 commit 94c3fb6

File tree

1 file changed

+48
-20
lines changed

1 file changed

+48
-20
lines changed

src/sage/interfaces/maxima_abstract.py

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858

5959
from sage.cpython.string import bytes_to_str
6060

61+
from sage.misc.cachefunc import cached_method
6162
from sage.misc.multireplace import multiple_replace
6263
from sage.structure.richcmp import richcmp, rich_to_bool
6364

@@ -291,36 +292,63 @@ def completions(self, s, verbose=True):
291292
cmd_list = [x for x in cmd_list[1:-1].split(',') if x[0] != '?' and not x.endswith('-impl')]
292293
return [x for x in cmd_list if x.find(s) == 0]
293294

295+
@cached_method
294296
def _commands(self, verbose=True):
295297
"""
296298
Return list of all commands defined in Maxima.
297299
298300
INPUT:
299301
300-
- ``verbose`` -- boolean (default: ``True``)
302+
- ``verbose`` -- boolean; ignored (obsolete)
301303
302-
OUTPUT: array of strings
304+
OUTPUT:
303305
304-
EXAMPLES::
306+
A list of strings.
307+
308+
EXAMPLES:
309+
310+
The list changes from time to time (with new versions of
311+
Maxima), so we look only for a few reliable commands::
312+
313+
sage: # long time
314+
sage: cs = maxima._commands()
315+
sage: "display" in cs
316+
True
317+
sage: "gcd" in cs
318+
True
319+
sage: "verbose" in cs
320+
True
305321
306-
# The output is kind of random
307-
sage: sorted(maxima._commands(verbose=False)) # long time (:issue:`39569`)
308-
[...
309-
'display',
310-
...
311-
'gcd',
312-
...
313-
'verbose',
314-
...]
315322
"""
316-
try:
317-
return self.__commands
318-
except AttributeError:
319-
self.__commands = sum(
320-
[self.completions(chr(65+n), verbose=verbose) +
321-
self.completions(chr(97+n), verbose=verbose)
322-
for n in range(26)], [])
323-
return self.__commands
323+
# Passing the empty string to apropos() gets ALL names.
324+
all_names = self._eval_line('apropos("")', error_check=False).split(",")
325+
a_to_Z = tuple( chr(i+j)
326+
for i in range(ord('A'),ord('Z')+1)
327+
for j in (0, 32) ) # 'a' = 'A' + 32
328+
329+
# Whack-a-mole to kill junk entries:
330+
#
331+
# * 'erf_%iargs',
332+
# * 'exp\\-form'
333+
# * 'is\\-boole\\-eval'
334+
# * 'is\\-boole\\-verify'
335+
# * 'maybe\\-boole\\-verify'
336+
# * 'time\\/\\/call'
337+
# * 'unknown\\?'
338+
#
339+
# None of these are documented, and the minus sign / question
340+
# mark / percent symbol probably aren't going to do what you
341+
# think they're going to do if you try to type them in an
342+
# ipython shell. We have to trim spaces too because some names
343+
# show up with a random leading spaces: ' tminverse',
344+
# ' toeplitz', etc.
345+
#
346+
bad_chars = ( "-", "/", "?", "%" )
347+
return [ c.strip()
348+
for c in all_names
349+
if c
350+
and (c[0] in a_to_Z or c[0] == " ")
351+
and not any( bad in c for bad in bad_chars ) ]
324352

325353
def _tab_completion(self, verbose=True, use_disk_cache=True):
326354
r"""

0 commit comments

Comments
 (0)