Skip to content

catch malformed Pattern - #1341

Merged
rocky merged 1 commit into
masterfrom
fix-matchq-errorhandler
May 10, 2021
Merged

catch malformed Pattern#1341
rocky merged 1 commit into
masterfrom
fix-matchq-errorhandler

Conversation

@mmatera

@mmaterammatera commented May 1, 2021

Copy link
Copy Markdown
Contributor

This PR avoids Mathics crashes as in #1174 (comment)
due to a malformed Pattern expression like MatchQ[3, Pattern[Pattern[a, Blank[]],Blank[]]]

@mmatera
mmatera requested a review from rockyMay 2, 2021 18:08
Comment threadmathics/builtin/base.py Outdated

class PatternArgumentError(PatternError):
def __init__(self, name, count, expected):
super().__init__(None, None)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If instead of super().__init__(None, None) you change to super().__init__(name, count) then you don't have to set these explicitly in the next two lines below.

= False
>> MatchQ[3, Pattern[3]]
: First element in pattern Pattern[3] is not a valid pattern name.
= False

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mmatera Here is what I get when I try running this in mathics

MatchQ[3, Pattern[3]]
Traceback (most recent call last):
File "/home/rocky/.pyenv/versions/3.7.10/bin/mathics", line 11, in <module>
load_entry_point('Mathics3', 'console_scripts', 'mathics')()
File "/src/external-vcs/github/mathics/Mathics/mathics/main.py", line 369, in main
result = evaluation.evaluate(query, timeout=settings.TIMEOUT)
File "/src/external-vcs/github/mathics/Mathics/mathics/core/evaluation.py", line 355, in evaluate
result = run_with_timeout_and_stack(evaluate, timeout, self)
File "/src/external-vcs/github/mathics/Mathics/mathics/core/evaluation.py", line 112, in run_with_timeout_and_stack
return request()
File "/src/external-vcs/github/mathics/Mathics/mathics/core/evaluation.py", line 326, in evaluate
self.last_eval = query.evaluate(self)
File "mathics/core/expression.py", line 1310, in mathics.core.expression.Expression.evaluate
expr, reevaluate = expr.evaluate_next(evaluation)
File "mathics/core/expression.py", line 1444, in mathics.core.expression.Expression.evaluate_next
result = rule.apply(new, evaluation, fully=False)
File "mathics/core/rules.py", line 67, in mathics.core.rules.BaseRule.apply
self.pattern.match(yield_match, expression, {}, evaluation, fully=fully)
File "mathics/core/pattern.py", line 291, in mathics.core.pattern.ExpressionPattern.match
self.head.match(yield_head, expression.get_head(), vars, evaluation)
File "mathics/core/pattern.py", line 159, in mathics.core.pattern.AtomPattern.match
yield_func(vars, None)
File "mathics/core/pattern.py", line 281, in mathics.core.pattern.ExpressionPattern.match.yield_head
self.get_pre_choices(
File "mathics/core/pattern.py", line 429, in mathics.core.pattern.ExpressionPattern.get_pre_choices
yield_func(vars)
File "mathics/core/pattern.py", line 258, in mathics.core.pattern.ExpressionPattern.match.yield_choice
self.match_leaf(
File "mathics/core/pattern.py", line 655, in mathics.core.pattern.ExpressionPattern.match_leaf
self.get_wrappings(
File "mathics/core/pattern.py", line 456, in mathics.core.pattern.ExpressionPattern.get_wrappings
yield_func(items[0])
File "mathics/core/pattern.py", line 643, in mathics.core.pattern.ExpressionPattern.match_leaf.yield_wrapping
leaf.match(
File "mathics/builtin/patterns.py", line 829, in mathics.builtin.patterns.Pattern_.match
return self.pattern.get_match_count(vars)
File "mathics/builtin/patterns.py", line 1027, in mathics.builtin.patterns.Blank.match
#> StringReplace["hello world!", _ -> "x"]
File "mathics/core/pattern.py", line 623, in mathics.core.pattern.ExpressionPattern.match_leaf.match_yield
self.match_leaf(
File "mathics/core/pattern.py", line 655, in mathics.core.pattern.ExpressionPattern.match_leaf
self.get_wrappings(
File "mathics/core/pattern.py", line 456, in mathics.core.pattern.ExpressionPattern.get_wrappings
yield_func(items[0])
File "mathics/core/pattern.py", line 643, in mathics.core.pattern.ExpressionPattern.match_leaf.yield_wrapping
leaf.match(
File "mathics/builtin/patterns.py", line 829, in mathics.builtin.patterns.Pattern_.match
return self.pattern.get_match_count(vars)
File "mathics/builtin/patterns.py", line 1027, in mathics.builtin.patterns.Blank.match
#> StringReplace["hello world!", _ -> "x"]
File "mathics/core/pattern.py", line 640, in mathics.core.pattern.ExpressionPattern.match_leaf.match_yield
yield_func(new_vars, items_rest)
File "mathics/core/pattern.py", line 616, in mathics.core.pattern.ExpressionPattern.match_leaf.leaf_yield
yield_func(
File "mathics/core/rules.py", line 42, in mathics.core.rules.BaseRule.apply.yield_match
new_expression = self.do_replace(expression, vars, options, evaluation)
File "mathics/core/rules.py", line 131, in mathics.core.rules.BuiltinRule.do_replace
return self.function(evaluation=evaluation, **vars_noctx)
File "mathics/builtin/patterns.py", line 670, in mathics.builtin.patterns.MatchQ.apply
= False
File "mathics/builtin/patterns.py", line 647, in mathics.builtin.patterns.match
return True
File "mathics/builtin/patterns.py", line 633, in mathics.builtin.patterns.Matcher.__init__
pass
File "mathics/core/pattern.py", line 24, in mathics.core.pattern.Pattern_create
return pattern_object(expr)
File "/src/external-vcs/github/mathics/Mathics/mathics/builtin/base.py", line 382, in __new__
instance.init(*args, **kwargs)
File "mathics/builtin/patterns.py", line 804, in mathics.builtin.patterns.Pattern_.init
"MakeBoxes[Verbatim[Pattern][symbol_Symbol, blank_Blank|blank_BlankSequence|blank_BlankNullSequence], f:StandardForm|TraditionalForm|InputForm|OutputForm]": "MakeBoxes[symbol, f] <> MakeBoxes[blank, f]",
File "/src/external-vcs/github/mathics/Mathics/mathics/builtin/base.py", line 746, in init
self.error_args(len(expr.leaves), *self.arg_counts)
File "/src/external-vcs/github/mathics/Mathics/mathics/builtin/base.py", line 755, in error_args
raise PatternArgumentError(self.get_name(), count, *expected)
mathics.builtin.base.PatternArgumentError

When I run through test, I don't have a problem thought.

Do you know what's up here?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find this error in the current master branch. The patch in this PR catches the exception producing a message
Pattern::patvar: First element in pattern Pattern[3] is not a valid pattern name.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, #> StringReplace["hello world!", _ -> "x"] line in the trace seems to suggest that your branch is probably mixed with something else.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This weird, and I don't understand. I just tried again, looking for this kind of problem of mismatched versions, and I removed any cythonized files and I still get the same thing.

$ git checkout fb6231ae
Note: switching to 'fb6231ae'.
...
HEAD is now at fb6231ae adding argr message for PatternArgumentError
$ mathics
Mathics 2.1.1.dev0
on CPython 3.9.2 (default, Feb 27 2021, 22:36:52) using SymPy 1.7.1, mpmath 1.2.1, numpy 1.20.1, cython 0.29.23
Copyright (C) 2011-2021 The Mathics Team.
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions.
See the documentation for the full license.
Quit by evaluating Quit[] or by pressing CONTROL-D.
In[1]:= MatchQ[3, Pattern[3]]
Traceback (most recent call last):
File "/home/rocky/.pyenv/versions/3.9.2/bin/mathics", line 33, in <module>
sys.exit(load_entry_point('Mathics3', 'console_scripts', 'mathics')())
File "/src/external-vcs/github/mathics/Mathics/mathics/main.py", line 369, in main
result = evaluation.evaluate(query, timeout=settings.TIMEOUT)
File "/src/external-vcs/github/mathics/Mathics/mathics/core/evaluation.py", line 355, in evaluate
result = run_with_timeout_and_stack(evaluate, timeout, self)
File "/src/external-vcs/github/mathics/Mathics/mathics/core/evaluation.py", line 112, in run_with_timeout_and_stack
return request()
File "/src/external-vcs/github/mathics/Mathics/mathics/core/evaluation.py", line 326, in evaluate
self.last_eval = query.evaluate(self)
File "/src/external-vcs/github/mathics/Mathics/mathics/core/expression.py", line 1310, in evaluate
expr, reevaluate = expr.evaluate_next(evaluation)
File "/src/external-vcs/github/mathics/Mathics/mathics/core/expression.py", line 1444, in evaluate_next
result = rule.apply(new, evaluation, fully=False)
File "/src/external-vcs/github/mathics/Mathics/mathics/core/rules.py", line 67, in apply
self.pattern.match(yield_match, expression, {}, evaluation, fully=fully)
File "/src/external-vcs/github/mathics/Mathics/mathics/core/pattern.py", line 291, in match
self.head.match(yield_head, expression.get_head(), vars, evaluation)
File "/src/external-vcs/github/mathics/Mathics/mathics/core/pattern.py", line 159, in match
yield_func(vars, None)
File "/src/external-vcs/github/mathics/Mathics/mathics/core/pattern.py", line 281, in yield_head
self.get_pre_choices(
File "/src/external-vcs/github/mathics/Mathics/mathics/core/pattern.py", line 429, in get_pre_choices
yield_func(vars)
File "/src/external-vcs/github/mathics/Mathics/mathics/core/pattern.py", line 258, in yield_choice
self.match_leaf(
File "/src/external-vcs/github/mathics/Mathics/mathics/core/pattern.py", line 655, in match_leaf
self.get_wrappings(
File "/src/external-vcs/github/mathics/Mathics/mathics/core/pattern.py", line 456, in get_wrappings
yield_func(items[0])
File "/src/external-vcs/github/mathics/Mathics/mathics/core/pattern.py", line 643, in yield_wrapping
leaf.match(
File "mathics/builtin/patterns.py", line 829, in mathics.builtin.patterns.Pattern_.match
def get_match_count(self, vars={}):
File "mathics/builtin/patterns.py", line 1027, in mathics.builtin.patterns.Blank.match
File "/src/external-vcs/github/mathics/Mathics/mathics/core/pattern.py", line 623, in match_yield
self.match_leaf(
File "/src/external-vcs/github/mathics/Mathics/mathics/core/pattern.py", line 655, in match_leaf
self.get_wrappings(
File "/src/external-vcs/github/mathics/Mathics/mathics/core/pattern.py", line 456, in get_wrappings
yield_func(items[0])
File "/src/external-vcs/github/mathics/Mathics/mathics/core/pattern.py", line 643, in yield_wrapping
leaf.match(
File "mathics/builtin/patterns.py", line 829, in mathics.builtin.patterns.Pattern_.match
def get_match_count(self, vars={}):
File "mathics/builtin/patterns.py", line 1027, in mathics.builtin.patterns.Blank.match
File "/src/external-vcs/github/mathics/Mathics/mathics/core/pattern.py", line 640, in match_yield
yield_func(new_vars, items_rest)
File "/src/external-vcs/github/mathics/Mathics/mathics/core/pattern.py", line 616, in leaf_yield
yield_func(
File "/src/external-vcs/github/mathics/Mathics/mathics/core/rules.py", line 42, in yield_match
new_expression = self.do_replace(expression, vars, options, evaluation)
File "/src/external-vcs/github/mathics/Mathics/mathics/core/rules.py", line 131, in do_replace
return self.function(evaluation=evaluation, **vars_noctx)
File "mathics/builtin/patterns.py", line 670, in mathics.builtin.patterns.MatchQ.apply
= False
File "mathics/builtin/patterns.py", line 647, in mathics.builtin.patterns.match
return True
File "mathics/builtin/patterns.py", line 633, in mathics.builtin.patterns.Matcher.__init__
pass
File "/src/external-vcs/github/mathics/Mathics/mathics/core/pattern.py", line 24, in Pattern_create
return pattern_object(expr)
File "/src/external-vcs/github/mathics/Mathics/mathics/builtin/base.py", line 382, in __new__
instance.init(*args, **kwargs)
File "mathics/builtin/patterns.py", line 804, in mathics.builtin.patterns.Pattern_.init
rules = {
File "/src/external-vcs/github/mathics/Mathics/mathics/builtin/base.py", line 743, in init
self.error_args(len(expr.leaves), *self.arg_counts)
File "/src/external-vcs/github/mathics/Mathics/mathics/builtin/base.py", line 752, in error_args
raise PatternArgumentError(self.get_name(), count, *expected)
mathics.builtin.base.PatternArgumentError: (1, 2)
$ 

When you do the same thing you don't get a traceback to falls through to the top-level?

@rockyrocky left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, I think this will help a lot in the future. I am getting a traceback in mathics when an exception via MatchQ[3, Pattern[3]] though. The traceback seen is in one of the comments.

Comment threadmathics/builtin/base.py
@rocky
rocky marked this pull request as draft May 9, 2021 18:56
adding argr message for PatternArgumentError
@mmatera
mmateraforce-pushed the fix-matchq-errorhandler branch from fb6231a to bbd289aCompareMay 10, 2021 23:14
@rocky

Copy link
Copy Markdown
Member

My fault. I had an old cython file for builtin/patterns.

@mmatera
mmatera marked this pull request as ready for review May 10, 2021 23:31
@rocky
rocky merged commit 3de2a23 into masterMay 10, 2021
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@mmatera@rocky