From 9d0a2be845ba735bbf915f1f48dff6f4008a3376 Mon Sep 17 00:00:00 2001 From: Tim Hatch Date: Sun, 10 Nov 2019 07:11:33 -0800 Subject: [PATCH] [parsing 3.3] Matrix multiply (PEP 465) --- libcst/_nodes/tests/test_matrix_multiply.py | 73 +++++++++++++++++++++ libcst/_parser/conversions/expression.py | 3 +- libcst/_parser/conversions/statement.py | 9 +++ 3 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 libcst/_nodes/tests/test_matrix_multiply.py diff --git a/libcst/_nodes/tests/test_matrix_multiply.py b/libcst/_nodes/tests/test_matrix_multiply.py new file mode 100644 index 00000000..cf39bd1a --- /dev/null +++ b/libcst/_nodes/tests/test_matrix_multiply.py @@ -0,0 +1,73 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# pyre-strict +from typing import Any + +import libcst as cst +from libcst._nodes.tests.base import ( + CSTNodeTest, + parse_expression_as, + parse_statement_as, +) +from libcst.testing.utils import data_provider + + +class NamedExprTest(CSTNodeTest): + @data_provider( + ( + { + "node": cst.BinaryOperation( + left=cst.Name("a"), + operator=cst.MatrixMultiply(), + right=cst.Name("b"), + ), + "code": "a @ b", + "parser": parse_expression_as(python_version="3.8"), + }, + { + "node": cst.SimpleStatementLine( + body=( + cst.AugAssign( + target=cst.Name("a"), + operator=cst.MatrixMultiplyAssign(), + value=cst.Name("b"), + ), + ), + ), + "code": "a @= b\n", + "parser": parse_statement_as(python_version="3.8"), + }, + ) + ) + def test_valid(self, **kwargs: Any) -> None: + self.validate_node(**kwargs) + + @data_provider( + ( + { + "code": "a @ b", + "parser": parse_expression_as(python_version="3.6"), + "expect_success": True, + }, + { + "code": "a @ b", + "parser": parse_expression_as(python_version="3.3"), + "expect_success": False, + }, + { + "code": "a @= b", + "parser": parse_statement_as(python_version="3.6"), + "expect_success": True, + }, + { + "code": "a @= b", + "parser": parse_statement_as(python_version="3.3"), + "expect_success": False, + }, + ) + ) + def test_versions(self, code, parser, expect_success) -> None: + self.assert_parses(code, parser, expect_success) diff --git a/libcst/_parser/conversions/expression.py b/libcst/_parser/conversions/expression.py index 7e5d8bcf..0d168fbf 100644 --- a/libcst/_parser/conversions/expression.py +++ b/libcst/_parser/conversions/expression.py @@ -478,7 +478,8 @@ def convert_star_expr( @with_production("and_expr", "shift_expr ('&' shift_expr)*") @with_production("shift_expr", "arith_expr (('<<'|'>>') arith_expr)*") @with_production("arith_expr", "term (('+'|'-') term)*") -@with_production("term", "factor (('*'|'@'|'/'|'%'|'//') factor)*") +@with_production("term", "factor (('*'|'@'|'/'|'%'|'//') factor)*", version=">=3.5") +@with_production("term", "factor (('*'|'/'|'%'|'//') factor)*", version="<3.5") def convert_binop( config: ParserConfig, children: typing.Sequence[typing.Any] ) -> typing.Any: diff --git a/libcst/_parser/conversions/statement.py b/libcst/_parser/conversions/statement.py index 46c3896e..25c528d8 100644 --- a/libcst/_parser/conversions/statement.py +++ b/libcst/_parser/conversions/statement.py @@ -306,6 +306,15 @@ def convert_annassign(config: ParserConfig, children: Sequence[Any]) -> Any: "('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | " + "'>>=' | '**=' | '//=') (yield_expr | testlist)" ), + version=">=3.5", +) +@with_production( + "augassign", + ( + "('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | " + + "'>>=' | '**=' | '//=') (yield_expr | testlist)" + ), + version="<3.5", ) def convert_augassign(config: ParserConfig, children: Sequence[Any]) -> Any: op, expr = children