Repository: LMFDB/lmfdb

Issue:
Allow multiplication and exponentiation in input boxes
For integer search boxes, it would be nice if we allowed expressions like `2^5*17` in integer inputs.  This can be achieved by editing line `344` of `lmfdb/utils/search_parsing.py` to change
```
def parse_ints(inp, query, qfield, parse_singleton=int):
```
to 
```
def parse_ints(inp, query, qfield, parse_singleton=my_parser):
```
and write a function that can parse multiplication and exponentiation.  If you use `sage_eval`, make sure you run the input through a regular expression (eg. only allow digits, * and ^) first so that it's safe.


Discussion:
Making that one change should come with a basic arithmetic parser, or regex test with sage_eval (which I assume is essentially the same as taking ZZ(input)?).  We certainly don't want a bunch of people writing their own parsers.
@jwj61 Agreed, the implementation should do a regex match that only allows digits and multiplicative operators and then call sage eval (we don't want to support additive operators to avoid bad interactions with ranges, but almost all of our integer inputs are multiplicative (conductor, discriminant, order, ....)
Addressed by #4268 and now live.
Reopening this issue because there is a problem in the way malformed expressions are handled, typing "3*" into an integer input now throws a server error, but it should be handled the same way as "banana" or any other invalid input.  I'm guessing the regex match is not requiring a full match (which it should).
I think it's easier to just catch the error than to write a regex that handles all the right syntax.
Yeah, I would also go for the catch syntax error


On Wed, Jan 6, 2021, 18:40 roed314 <notifications@github.com> wrote:

> I think it's easier to just catch the error than to write a regex that
> handles all the right syntax.
>
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/LMFDB/lmfdb/issues/4268#issuecomment-755496285>, or
> unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AACO2BR5ZVFSWEYN2HNL233SYSVAZANCNFSM4UXIP7LQ>
> .
>


Resolving patch:
diff --git a/lmfdb/sato_tate_groups/main.py b/lmfdb/sato_tate_groups/main.py
--- a/lmfdb/sato_tate_groups/main.py
+++ b/lmfdb/sato_tate_groups/main.py
@@ -789,8 +789,8 @@ def render_by_label(label):
     info['abelian']=boolean_name(G['abelian'])
     info['solvable']=boolean_name(G['solvable'])
     if data.get('gens'):
-        info['gens']=comma_separated_list([string_matrix(m) for m in data['gens']])
-        info['numgens']=len(info['gens'])
+        info['gens'] = comma_separated_list([string_matrix(m) for m in data['gens']]) if type(data['gens']) == list else data['gens']
+        info['numgens'] = len(info['gens'])
     else:
         info['numgens'] = 0
     if data.get('subgroups'):
diff --git a/lmfdb/utils/search_parsing.py b/lmfdb/utils/search_parsing.py
--- a/lmfdb/utils/search_parsing.py
+++ b/lmfdb/utils/search_parsing.py
@@ -372,12 +372,12 @@ def parse_rational_to_list(inp, query, qfield):
 def parse_ints(inp, query, qfield, parse_singleton=int):
     if LIST_RE.match(inp):
         collapse_ors(parse_range2(inp, qfield, parse_singleton), query)
-    elif MULT_PARSE.match(inp):
+    elif MULT_PARSE.fullmatch(inp):
         try:
             ast_expression = ast.parse(inp.replace('^', '**'), mode='eval')
             inp = str(int(PowMulNodeVisitor().visit(ast_expression).body))
             collapse_ors(parse_range2(inp, qfield, parse_singleton), query)
-        except (TypeError, ValueError):
+        except (TypeError, ValueError, SyntaxError):
             raise SearchParsingError("Unable to evaluate expression.")
     else:
         raise SearchParsingError("It needs to be an integer (such as 25), be a multiplicative expression that parses to an integer (such as 2^2*3), a range of integers (such as 2-10 or 2..10), or a comma-separated list of these (such as 4,9,16 or 4-25, 81-121).")


Test patch: