Skip to content

Comments

catch malformed Pattern#1341

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

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

Conversation

@mmatera
Copy link
Contributor

@mmatera mmatera commented May 1, 2021

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 rocky May 2, 2021 18:08

class PatternArgumentError(PatternError):
def __init__(self, name, count, expected):
super().__init__(None, None)
Copy link
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
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
Contributor Author

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
Contributor Author

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
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?

Copy link
Member

@rocky rocky left a comment

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.

@rocky rocky marked this pull request as draft May 9, 2021 18:56
adding argr message for PatternArgumentError
@mmatera mmatera force-pushed the fix-matchq-errorhandler branch from fb6231a to bbd289a Compare May 10, 2021 23:14
@rocky rocky removed the needs work label May 10, 2021
@rocky
Copy link
Member

rocky commented May 10, 2021

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 master May 10, 2021
Sign up for free to 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