diff --git a/mindspore/ccsrc/pipeline/jit/parse/parse.cc b/mindspore/ccsrc/pipeline/jit/parse/parse.cc index 0dfc7e3c9c4..7a009d700cf 100644 --- a/mindspore/ccsrc/pipeline/jit/parse/parse.cc +++ b/mindspore/ccsrc/pipeline/jit/parse/parse.cc @@ -32,6 +32,7 @@ #include "frontend/operator/ops.h" #include "frontend/operator/composite/composite.h" #include "utils/ms_context.h" +#include "utils/log_adapter.h" #include "utils/interpret_node_recorder.h" #include "pipeline/jit/debug/trace.h" #include "mindspore/core/ir/cell.h" @@ -86,6 +87,7 @@ void Parser::BuildMethodMap() { stmt_method_map_["Break"] = &Parser::ParseBreak; stmt_method_map_["Continue"] = &Parser::ParseContinue; stmt_method_map_["Pass"] = &Parser::ParsePass; + stmt_method_map_["Raise"] = &Parser::ParseRaise; expr_method_map_["NoneType"] = &Parser::ParseNone; expr_method_map_["BinOp"] = &Parser::ParseBinOp; expr_method_map_["Name"] = &Parser::ParseName; @@ -110,6 +112,8 @@ void Parser::BuildMethodMap() { expr_method_map_["Ellipsis"] = &Parser::ParseEllipsis; expr_method_map_["ListComp"] = &Parser::ParseListComp; expr_method_map_["GeneratorExp"] = &Parser::ParseListComp; // We treat 'GeneratorExp' the same as 'ListComp'. + expr_method_map_["JoinedStr"] = &Parser::ParseJoinedStr; + expr_method_map_["FormattedValue"] = &Parser::ParseFormattedValue; } void Parser::UpdateTopFuncGraph(const FuncGraphPtr &func_graph) { top_func_graph_ = FuncGraphWeakPtr(func_graph); } @@ -884,6 +888,47 @@ AnfNodePtr Parser::ParseSuper(const FunctionBlockPtr &block, const py::list &arg return block->MakeResolve(name_space, symbol); } +void Parser::ParseStrInError(const FunctionBlockPtr &block, const py::list &args, std::vector *str_nodes) { + for (size_t i = 0; i < args.size(); ++i) { + AnfNodePtr node = ParseExprNode(block, args[i]); + (void)str_nodes->emplace_back(node); + } +} + +std::vector Parser::ParseException(const FunctionBlockPtr &block, const py::list &args, + const std::string &name) { + auto exception_type_node = NewValueNode(name); + std::vector node_inputs = {exception_type_node}; + ParseStrInError(block, args, &node_inputs); + return node_inputs; +} + +std::vector Parser::ParseRaiseCall(const FunctionBlockPtr &block, const py::object &node) { + MS_LOG(DEBUG) << "Process ast Call, the current node is raise."; + // Process function call + py::object function_ast_node = python_adapter::GetPyObjAttr(node, "func"); + // Process raise ValueError + if (py::isinstance(function_ast_node)) { + auto name_id = py::cast(python_adapter::GetPyObjAttr(node, "id")); + if (std::find(exception_types.begin(), exception_types.end(), name_id) != exception_types.end()) { + return {NewValueNode(name_id)}; + } + } + + py::list args = python_adapter::GetPyObjAttr(node, "args"); + + auto arg_type = + AstSubType(py::cast(ast_->CallParseModFunction(PYTHON_PARSE_GET_AST_TYPE, function_ast_node))); + if (arg_type == AST_SUB_TYPE_NAME) { + auto name_id = py::cast(python_adapter::GetPyObjAttr(function_ast_node, "id")); + MS_LOG(DEBUG) << "The name of call node is: " << name_id; + if (std::find(exception_types.begin(), exception_types.end(), name_id) != exception_types.end()) { + return ParseException(block, args, name_id); + } + } + return {}; +} + // Process function call, eg : f1(x, y) ... AnfNodePtr Parser::ParseCall(const FunctionBlockPtr &block, const py::object &node) { MS_LOG(DEBUG) << "Process ast Call"; @@ -895,6 +940,7 @@ AnfNodePtr Parser::ParseCall(const FunctionBlockPtr &block, const py::object &no AstSubType(py::cast(ast_->CallParseModFunction(PYTHON_PARSE_GET_AST_TYPE, function_ast_node))); if (arg_type == AST_SUB_TYPE_NAME) { auto name_id = py::cast(python_adapter::GetPyObjAttr(function_ast_node, "id")); + MS_LOG(DEBUG) << "The name of call node is: " << name_id; if (name_id == "super") { return ParseSuper(block, args); } @@ -2012,6 +2058,29 @@ AnfNodePtr Parser::ParseListComp(const FunctionBlockPtr &block, const py::object return output; } +AnfNodePtr Parser::ParseJoinedStr(const FunctionBlockPtr &block, const py::object &node) { + MS_LOG(DEBUG) << "Process ast JoinedStr."; + MS_EXCEPTION_IF_NULL(block); + py::list py_values = python_adapter::GetPyObjAttr(node, "values"); + std::vector value_nodes{NewValueNode(prim::kPrimMakeTuple)}; + for (size_t i = 0; i < py_values.size(); ++i) { + AnfNodePtr str_value = ParseExprNode(block, py_values[i]); + (void)value_nodes.emplace_back(str_value); + } + auto func_graph = block->func_graph(); + MS_EXCEPTION_IF_NULL(func_graph); + AnfNodePtr output = func_graph->NewCNodeInOrder(std::move(value_nodes)); + return output; +} + +AnfNodePtr Parser::ParseFormattedValue(const FunctionBlockPtr &block, const py::object &node) { + MS_LOG(DEBUG) << "Process ast FormattedValue."; + MS_EXCEPTION_IF_NULL(block); + py::object value_object = python_adapter::GetPyObjAttr(node, "value"); + AnfNodePtr value_node = ParseExprNode(block, value_object); + return value_node; +} + void Parser::HandleAssignName(const FunctionBlockPtr &block, const py::object &target_object, const AnfNodePtr &assigned_node) { MS_EXCEPTION_IF_NULL(block); @@ -2336,6 +2405,28 @@ FunctionBlockPtr Parser::ParsePass(const FunctionBlockPtr &block, const py::obje return block; } +FunctionBlockPtr Parser::ParseRaise(const FunctionBlockPtr &block, const py::object &node) { + MS_LOG(DEBUG) << "Process raise statement"; + MS_EXCEPTION_IF_NULL(block); + auto func_graph = block->func_graph(); + MS_EXCEPTION_IF_NULL(func_graph); + py::object exc_ast_node = python_adapter::GetPyObjAttr(node, "exc"); + // raise + if (py::isinstance(exc_ast_node)) { + CNodePtr raise_node = func_graph->NewCNodeInOrder({NewValueNode(prim::kPrimRaise)}); + func_graph->set_return(raise_node); + return block; + } + auto exc_node_inputs = ParseRaiseCall(block, exc_ast_node); + // raise ExceptionType or raise ExceptionType(ExceptionString) + std::vector inputs{NewValueNode(prim::kPrimRaise)}; + (void)inputs.insert(inputs.end(), exc_node_inputs.begin(), exc_node_inputs.end()); + CNodePtr raise_node = func_graph->NewCNodeInOrder(inputs); + CNodePtr return_node = func_graph->NewCNodeInOrder({NewValueNode(prim::kPrimReturn), raise_node}); + func_graph->set_return(return_node); + return block; +} + AnfNodePtr FindPhis(const mindspore::HashMap &removable_phis, const AnfNodePtr &node) { MS_EXCEPTION_IF_NULL(node); const auto &inp = node->cast(); diff --git a/mindspore/ccsrc/pipeline/jit/parse/parse.h b/mindspore/ccsrc/pipeline/jit/parse/parse.h index 1549e140b69..62d80048d9d 100644 --- a/mindspore/ccsrc/pipeline/jit/parse/parse.h +++ b/mindspore/ccsrc/pipeline/jit/parse/parse.h @@ -142,6 +142,8 @@ class Parser { FunctionBlockPtr ParseContinue(const FunctionBlockPtr &block, const py::object &node); // Process pass statement FunctionBlockPtr ParsePass(const FunctionBlockPtr &block, const py::object &node); + // Process raise statement + FunctionBlockPtr ParseRaise(const FunctionBlockPtr &block, const py::object &node); // Process the expr and slice node method list AnfNodePtr ParseBinOp(const FunctionBlockPtr &block, const py::object &node); @@ -197,6 +199,11 @@ class Parser { const py::object &generator_node); AnfNodePtr ParseListCompIfs(const FunctionBlockPtr &list_body_block, const ParameterPtr &list_param, const py::object &node, const py::object &generator_node); + AnfNodePtr ParseJoinedStr(const FunctionBlockPtr &block, const py::object &node); + AnfNodePtr ParseFormattedValue(const FunctionBlockPtr &block, const py::object &node); + std::vector ParseException(const FunctionBlockPtr &block, const py::list &args, const std::string &name); + std::vector ParseRaiseCall(const FunctionBlockPtr &block, const py::object &node); + void ParseStrInError(const FunctionBlockPtr &block, const py::list &args, std::vector *str_nodes); // Transform tail call to parallel call. void TransformParallelCall(); diff --git a/mindspore/ccsrc/pipeline/jit/static_analysis/evaluator.cc b/mindspore/ccsrc/pipeline/jit/static_analysis/evaluator.cc index 269bf370b63..ccff6b26e2a 100644 --- a/mindspore/ccsrc/pipeline/jit/static_analysis/evaluator.cc +++ b/mindspore/ccsrc/pipeline/jit/static_analysis/evaluator.cc @@ -467,7 +467,8 @@ EvalResultPtr TrivialPrimEvaluator::Run(AnalysisEnginePtr engine, const ConfigPt EvalResultPtr TransitionPrimEvaluator::Run(AnalysisEnginePtr engine, const ConfigPtrList &args_conf_list, const AnfNodeConfigPtr &out_conf) { - if (args_conf_list.empty() && identifier_ != "MakeTupleEvaluator" && identifier_ != "MakeListEvaluator") { + if (args_conf_list.empty() && identifier_ != "MakeTupleEvaluator" && identifier_ != "MakeListEvaluator" && + identifier_ != "RaiseEvaluator") { MS_LOG(EXCEPTION) << "Size should be greater than 0, during running " << identifier_; } AbstractBasePtrList args_spec_list; diff --git a/mindspore/ccsrc/pipeline/jit/static_analysis/prim.cc b/mindspore/ccsrc/pipeline/jit/static_analysis/prim.cc index 6465938394a..ec34d3e8f5c 100644 --- a/mindspore/ccsrc/pipeline/jit/static_analysis/prim.cc +++ b/mindspore/ccsrc/pipeline/jit/static_analysis/prim.cc @@ -37,6 +37,7 @@ #include "pipeline/jit/parse/resolve.h" #include "pipeline/jit/pipeline.h" #include "pipeline/jit/static_analysis/static_analysis.h" +#include "pipeline/jit/debug/trace.h" #include "include/common/utils/convert_utils.h" #include "include/common/utils/convert_utils_py.h" #include "utils/ms_context.h" @@ -1918,6 +1919,82 @@ class PartialEvaluator : public Evaluator { } }; +class RaiseEvaluator : public TransitionPrimEvaluator { + public: + RaiseEvaluator() : TransitionPrimEvaluator("RaiseEvaluator") {} + ~RaiseEvaluator() override = default; + MS_DECLARE_PARENT(RaiseEvaluator, TransitionPrimEvaluator); + EvalResultPtr EvalPrim(const AnalysisEnginePtr &engine, const AbstractBasePtrList &args_spec_list, + const ConfigPtr &in_conf0, const AnfNodeConfigPtr &out_conf) override { + auto node = out_conf->node(); + MS_EXCEPTION_IF_NULL(node); + auto cur_graph = node->func_graph(); + MS_EXCEPTION_IF_NULL(cur_graph); + if (cur_graph->is_tensor_condition_branch()) { + MS_LOG(EXCEPTION) << "Currently only supports raise in constant scenarios." + << "Tensor type data cannot exist in the conditional statement." + << "Please check your conditions which raise node is located at:" + << trace::GetDebugInfo(node->debug_info()) << "."; + } + if (args_spec_list.empty()) { + // process raise + MS_LOG(EXCEPTION) << "No active exception to reraise."; + } + + std::string exception_type = GetScalarStringValue(args_spec_list[0]); + auto iter = exception_types_map.find(exception_type); + if (iter == exception_types_map.end()) { + MS_LOG(EXCEPTION) << "Unsupported exception type: " << exception_type << "."; + } + ExceptionType type = iter->second; + if (args_spec_list.size() == 1) { + // Process raise ValueError() + MS_EXCEPTION(type); + } + std::string exception_string = ""; + for (size_t index = 1; index < args_spec_list.size(); ++index) { + exception_string += GetExceptionString(args_spec_list[index]); + } + MS_EXCEPTION(type) << exception_string; + return nullptr; + } + + private: + std::string GetExceptionString(const AbstractBasePtr &arg) { + std::string exception_str = ""; + if (arg->isa()) { + // Process raise ValueError("str") + auto arg_tuple = arg->cast(); + const auto &arg_tuple_elements = arg_tuple->elements(); + if (arg_tuple_elements.size() == 0) { + MS_LOG(EXCEPTION) << "The arg_tuple_elements can't be empty."; + } + for (size_t index = 0; index < arg_tuple_elements.size(); ++index) { + auto &element = arg_tuple_elements[index]; + exception_str += GetScalarStringValue(element); + } + } else { + // Process raise ValueError + exception_str += GetScalarStringValue(arg); + } + return exception_str; + } + + std::string GetScalarStringValue(const AbstractBasePtr &abs) { + std::string str = ""; + if (abs->isa()) { + auto scalar = abs->cast(); + auto scalar_value = scalar->BuildValue(); + if (scalar_value->isa()) { + str = std::to_string(GetValue(scalar_value)); + } else if (scalar_value->isa()) { + str = GetValue(scalar_value); + } + } + return str; + } +}; + struct PrimitiveImplInferValue { PrimitiveImpl impl_; // implement function of primitive bool eval_value_; // whether evaluate value @@ -1976,6 +2053,7 @@ void InitPrimEvaluatorConstructors() { constructor[prim::kPrimPyInterpret] = std::make_shared(); constructor[prim::kPrimMakeTuple] = std::make_shared(); constructor[prim::kPrimMakeList] = std::make_shared(); + constructor[prim::kPrimRaise] = std::make_shared(); } } // namespace diff --git a/mindspore/core/abstract/prim_statement.cc b/mindspore/core/abstract/prim_statement.cc index 87c07007ef8..48427a0a660 100644 --- a/mindspore/core/abstract/prim_statement.cc +++ b/mindspore/core/abstract/prim_statement.cc @@ -34,6 +34,20 @@ AbstractBasePtr InferImplReturn(const AnalysisEnginePtr &, const PrimitivePtr &, return abs_base; } +void SetTensorFlag(const AbstractBasePtr abs) { + if (abs->isa()) { + const auto &func_abs = abs->cast(); + MS_EXCEPTION_IF_NULL(func_abs); + auto closure_abs = func_abs->cast(); + if (closure_abs) { + auto func = closure_abs->func_graph(); + MS_EXCEPTION_IF_NULL(func); + func->set_is_tensor_condition_branch(true); + MS_LOG(DEBUG) << "Set is_tensor_condition_branch for func_graph:" << func->ToString(); + } + } +} + AbstractBasePtr InferImplSwitch(const AnalysisEnginePtr &, const PrimitivePtr &, const AbstractBasePtrList &args_spec_list) { // Inputs: condition, true branch, false branch @@ -51,6 +65,11 @@ AbstractBasePtr InferImplSwitch(const AnalysisEnginePtr &, const PrimitivePtr &, MS_EXCEPTION_IF_NULL(v); // For tensor as condition, keeps both true and false branch. if (v->isa() || cond->isa()) { + // Need record two func_graph + if (cond->isa()) { + SetTensorFlag(tb); + SetTensorFlag(fb); + } MS_EXCEPTION_IF_NULL(tb); return tb->Join(fb); } diff --git a/mindspore/core/base/core_ops.h b/mindspore/core/base/core_ops.h index cd2b34c3dc2..dc464da3821 100644 --- a/mindspore/core/base/core_ops.h +++ b/mindspore/core/base/core_ops.h @@ -742,6 +742,7 @@ GVAR_DEF(PrimitivePtr, kPrimAssignAdd, std::make_shared(kAssignAdd)); GVAR_DEF(PrimitivePtr, kPrimAssignSub, std::make_shared(kAssignSub)); GVAR_DEF(PrimitivePtr, kPrimSelect, std::make_shared(kSelect)); GVAR_DEF(PrimitivePtr, kPrimCall, std::make_shared("call")); +GVAR_DEF(PrimitivePtr, kPrimRaise, std::make_shared("raise")); GVAR_DEF(PrimitivePtr, kPrimMakeTuple, std::make_shared(kMakeTuple)); GVAR_DEF(PrimitivePtr, kPrimMakeSlice, std::make_shared("make_slice")); diff --git a/mindspore/core/ir/func_graph.h b/mindspore/core/ir/func_graph.h index ea037fbb9a8..cb590fa2789 100644 --- a/mindspore/core/ir/func_graph.h +++ b/mindspore/core/ir/func_graph.h @@ -366,6 +366,11 @@ class MS_CORE_API FuncGraph : public deprecated::api::FuncGraph, public FuncGrap void set_used_forward_nodes(const std::vector &used_forward_nodes); void ClearUsedForwardNodes() { used_forward_nodes_.clear(); } + bool is_tensor_condition_branch() const { return is_tensor_condition_branch_; } + void set_is_tensor_condition_branch(bool is_tensor_condition_branch) { + is_tensor_condition_branch_ = is_tensor_condition_branch; + } + private: // Only used for func_graph manager to control resource free. int attached_mng_cnt() const { return attached_mng_cnt_; } @@ -455,6 +460,8 @@ class MS_CORE_API FuncGraph : public deprecated::api::FuncGraph, public FuncGrap // forward nodes used in grad graph will be added to output for holding output values. bool modify_output_ = false; mindspore::HashSet used_forward_nodes_; + // If the func_graph is input of switch node, and the condition of switch is AbstractTensor, need set true. + bool is_tensor_condition_branch_ = false; }; inline CNodePtr NewCNode(const std::vector &inputs, const FuncGraphPtr &fg) { diff --git a/mindspore/core/utils/log_adapter.h b/mindspore/core/utils/log_adapter.h index 8090142e3c7..62e216aad8d 100644 --- a/mindspore/core/utils/log_adapter.h +++ b/mindspore/core/utils/log_adapter.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include "utils/visible.h" @@ -71,6 +72,33 @@ enum ExceptionType { NameError }; +// exception types +const std::vector exception_types = {"NoExceptionType", "UnknownError", "ArgumentError", + "NotSupportError", "NotExistsError", "AlreadyExistsError", + "UnavailableError", "DeviceProcessError", "AbortedError", + "TimeOutError", "ResourceUnavailable", "NoPermissionError", + "IndexError", "ValueError", "TypeError", + "KeyError", "AttributeError", "NameError"}; + +static inline std::map exception_types_map = {{"NoExceptionType", NoExceptionType}, + {"UnknownError", UnknownError}, + {"ArgumentError", ArgumentError}, + {"NotSupportError", NotSupportError}, + {"NotExistsError", NotExistsError}, + {"AlreadyExistsError", AlreadyExistsError}, + {"UnavailableError", UnavailableError}, + {"DeviceProcessError", DeviceProcessError}, + {"AbortedError", AbortedError}, + {"TimeOutError", TimeOutError}, + {"ResourceUnavailable", ResourceUnavailable}, + {"NoPermissionError", NoPermissionError}, + {"IndexError", IndexError}, + {"ValueError", ValueError}, + {"TypeError", TypeError}, + {"KeyError", KeyError}, + {"AttributeError", AttributeError}, + {"NameError", NameError}}; + struct LocationInfo { LocationInfo(const char *file, int line, const char *func) : file_(file), line_(line), func_(func) {} ~LocationInfo() = default; diff --git a/tests/st/raise/test_graph_raise.py b/tests/st/raise/test_graph_raise.py new file mode 100644 index 00000000000..cc476f69a13 --- /dev/null +++ b/tests/st/raise/test_graph_raise.py @@ -0,0 +1,277 @@ +# Copyright 2022 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +""" test graph raise """ +import pytest +import numpy as np +import mindspore.nn as nn +from mindspore import Tensor, context +import mindspore.common.dtype as mstype +from mindspore.common.api import _cell_graph_executor + +context.set_context(mode=context.GRAPH_MODE) + + +@pytest.mark.level0 +@pytest.mark.platform_x86_gpu_training +@pytest.mark.platform_arm_ascend_training +@pytest.mark.platform_x86_ascend_training +@pytest.mark.env_onecard +def test_raise_1(): + """ + Feature: graph raise. + Description: Test raise. + Expectation: No exception. + """ + class RaiseNet(nn.Cell): + def construct(self, x): + if x == 1: + raise ValueError() + return x + + with pytest.raises(ValueError, match=""): + net = RaiseNet() + res = net(1) + print("res:", res) + + +@pytest.mark.level0 +@pytest.mark.platform_x86_gpu_training +@pytest.mark.platform_arm_ascend_training +@pytest.mark.platform_x86_ascend_training +@pytest.mark.env_onecard +def test_raise_2(): + """ + Feature: graph raise. + Description: Test raise. + Expectation: No exception. + """ + class RaiseNet(nn.Cell): + def construct(self, x): + if x == 1: + raise ValueError(1) + return x + + with pytest.raises(ValueError, match="1"): + net = RaiseNet() + res = net(1) + print("res:", res) + + +@pytest.mark.level0 +@pytest.mark.platform_x86_gpu_training +@pytest.mark.platform_arm_ascend_training +@pytest.mark.platform_x86_ascend_training +@pytest.mark.env_onecard +def test_raise_3(): + """ + Feature: graph raise. + Description: Test raise. + Expectation: No exception. + """ + class RaiseNet(nn.Cell): + def construct(self, x): + if x == 1: + raise ValueError(f"The input should not be 1.") + return x + + with pytest.raises(ValueError, match="The input should not be 1."): + net = RaiseNet() + res = net(1) + print("res:", res) + + +@pytest.mark.level0 +@pytest.mark.platform_x86_gpu_training +@pytest.mark.platform_arm_ascend_training +@pytest.mark.platform_x86_ascend_training +@pytest.mark.env_onecard +def test_raise_4(): + """ + Feature: graph raise. + Description: Test raise. + Expectation: No exception. + """ + class RaiseNet(nn.Cell): + def construct(self, x): + if x == 1: + raise ValueError(f"The input should not be 1.") + return x + + with pytest.raises(RuntimeError, match="Currently only supports raise in constant scenarios."): + net = RaiseNet() + x = Tensor(9, mstype.int32) + res = net(x) + assert res == 9 + + +@pytest.mark.level0 +@pytest.mark.platform_x86_gpu_training +@pytest.mark.platform_arm_ascend_training +@pytest.mark.platform_x86_ascend_training +@pytest.mark.env_onecard +def test_raise_5(): + """ + Feature: graph raise. + Description: Test raise. + Expectation: No exception. + """ + class NetWithRaise(nn.Cell): + def construct(self, x): + raise ValueError(f"exception in construct.") + + with pytest.raises(ValueError, match="exception in construct."): + net = NetWithRaise() + inp = Tensor(np.ones([1, 1, 32, 32]).astype(np.float32)) + _cell_graph_executor.compile(net, inp) + + +@pytest.mark.level0 +@pytest.mark.platform_x86_gpu_training +@pytest.mark.platform_arm_ascend_training +@pytest.mark.platform_x86_ascend_training +@pytest.mark.env_onecard +def test_raise_6(): + """ + Feature: graph raise. + Description: Test raise. + Expectation: No exception. + """ + class NetWithRaise(nn.Cell): + def subfunc(self): + raise ValueError(f"exception in subfunc.") + + def construct(self, x): + y = Tensor(0) + if x > 0: + y = Tensor(1) + elif x == 1: + y = Tensor(2) + else: + self.subfunc() + return y + + with pytest.raises(ValueError, match="exception in subfunc."): + net = NetWithRaise() + x = -1 + res = net(x) + print("res:", res) + + +@pytest.mark.skip(reason='Not support graph raise feature yet') +def test_raise_7(): + """ + Feature: graph raise. + Description: Test raise. + Expectation: No exception. + """ + class RaiseNet(nn.Cell): + def construct(self): + x = [1, 3, 5, 7, 9] + raise ValueError("Not expected value, x is {}".format(x)) + + with pytest.raises(ValueError) as info: + net = RaiseNet() + res = net() + print("res:", res) + assert "Not expected value, x is [1, 3, 5, 7, 9]" in str(info.value) + + +@pytest.mark.skip(reason='Not support graph raise feature yet') +def test_raise_8(): + """ + Feature: graph raise. + Description: Test raise. + Expectation: No exception. + """ + class RaiseNet(nn.Cell): + def __init__(self): + super(RaiseNet, self).__init__() + self.x = [1, 3, 5, 7] + + def construct(self): + if self.x == [1, 3, 5, 7, 9]: + return 5 + if self.x == [1, 3, 5]: + return 3 + raise ValueError("Not expected value, x is {}".format(self.x)) + + with pytest.raises(ValueError) as info: + net = RaiseNet() + res = net() + print("res:", res) + assert "Not expected value, x is [1, 3, 5, 7]" in str(info.value) + + +@pytest.mark.level0 +@pytest.mark.platform_x86_gpu_training +@pytest.mark.platform_arm_ascend_training +@pytest.mark.platform_x86_ascend_training +@pytest.mark.env_onecard +def test_raise_9(): + """ + Feature: graph raise. + Description: Test raise. + Expectation: No exception. + """ + class RaiseNet(nn.Cell): + def construct(self): + x = 11 + raise ValueError(f"The input can not be {x}.") + + with pytest.raises(ValueError) as info: + net = RaiseNet() + res = net() + print("res:", res) + assert "The input can not be 11." in str(info.value) + + +@pytest.mark.skip(reason='Not support graph raise feature yet') +def test_raise_10(): + """ + Feature: graph raise. + Description: Test raise. + Expectation: No exception. + """ + class RaiseNet(nn.Cell): + def construct(self, x): + raise ValueError(f"The input can not be %s." % x) + + with pytest.raises(ValueError) as info: + net = RaiseNet() + res = net(11) + print("res:", res) + assert "The input can not be 11." in str(info.value) + + +@pytest.mark.level0 +@pytest.mark.platform_x86_gpu_training +@pytest.mark.platform_arm_ascend_training +@pytest.mark.platform_x86_ascend_training +@pytest.mark.env_onecard +def test_raise_11(): + """ + Feature: graph raise. + Description: Test raise. + Expectation: No exception. + """ + class RaiseNet(nn.Cell): + def construct(self, x): + raise ValueError(f"The input can not be ", x, ".") + + with pytest.raises(ValueError) as info: + net = RaiseNet() + res = net(11) + print("res:", res) + assert "The input can not be 11." in str(info.value) diff --git a/tests/ut/python/ops/test_ops_check.py b/tests/ut/python/ops/test_ops_check.py index 5871b450652..4abea5f2706 100644 --- a/tests/ut/python/ops/test_ops_check.py +++ b/tests/ut/python/ops/test_ops_check.py @@ -16,8 +16,6 @@ import functools import logging import numpy as np -import pytest - import mindspore.context as context from mindspore import Tensor from mindspore import nn @@ -66,27 +64,6 @@ def test_net_without_construct(): _cell_graph_executor.compile(net, inp) -class NetWithRaise(nn.Cell): - """ NetWithRaise definition """ - - def __init__(self): - super(NetWithRaise, self).__init__() - self.conv1 = nn.Conv2d(1, 6, 5, pad_mode='valid') - - # raise exception in method 'construct' - def construct(self, x): - raise 'exception in construct' - - -def test_net_with_raise(): - """ test_net_with_raise """ - net = NetWithRaise() - inp = Tensor(np.ones([1, 1, 32, 32]).astype(np.float32)) - with pytest.raises(RuntimeError) as err: - _cell_graph_executor.compile(net, inp) - assert "Unsupported statement 'Raise'." in str(err.value) - - class NetAddN(nn.Cell): """net for test AddN""" diff --git a/tests/ut/python/pipeline/parse/test_grammar_constraints.py b/tests/ut/python/pipeline/parse/test_grammar_constraints.py index 568a0d4bcc7..68d4d14a280 100644 --- a/tests/ut/python/pipeline/parse/test_grammar_constraints.py +++ b/tests/ut/python/pipeline/parse/test_grammar_constraints.py @@ -30,9 +30,6 @@ context.set_context(mode=context.GRAPH_MODE) def test_missing_return(): class NetMissReturn(nn.Cell): - def __init__(self): - super(NetMissReturn, self).__init__() - def construct(self, x, y, z): if x == 1: return 10 @@ -65,9 +62,6 @@ def test_missing_return(): def test_nest_function_missing_return(): class NetNestFuncMissReturn(nn.Cell): - def __init__(self): - super(NetNestFuncMissReturn, self).__init__() - def construct(self, x, y, z): if x == 1: return 10 @@ -100,12 +94,9 @@ def test_nest_function_missing_return(): def test_raise_in_method(): class NetRaiseInMethod(nn.Cell): - def __init__(self): - super(NetRaiseInMethod, self).__init__() - def construct(self, x, y, z): if x == 1: - return 10 + return Tensor(10, mstype.int32) elif x == 20: # add not support grammar 'raise' here raise ValueError('Illegal case') @@ -118,24 +109,22 @@ def test_raise_in_method(): z = Tensor(2, mstype.int32) with pytest.raises(RuntimeError) as er: net(x, y, z) - assert "Unsupported statement 'Raise'." in str(er.value) + assert "Currently only supports raise in constant scenarios." in str(er.value) def test_raise_in_nested_function(): class NetNestRaise(nn.Cell): - def __init__(self): - super(NetNestRaise, self).__init__() + def nest_fn(self, u): + if u > 0: + # add not support grammar 'raise' here + raise ValueError('Illegal case') + return u + z + 1 def construct(self, x, y, z): if x == 1: - return 10 + return Tensor(10, mstype.int32) elif x == 20: - def nest_fn(u): - if u > 0: - # add not support grammar 'raise' here - raise ValueError('Illegal case') - return u + z + 1 - return nest_fn(y) + return self.nest_fn(y) else: return y + z @@ -145,14 +134,11 @@ def test_raise_in_nested_function(): z = Tensor(2, mstype.int32) with pytest.raises(RuntimeError) as er: net(x, y, z) - assert "Unsupported statement 'Raise'." in str(er.value) + assert "Currently only supports raise in constant scenarios." in str(er.value) def test_nest_branch_with_return(): class NetBranchWithReturn(nn.Cell): - def __init__(self): - super(NetBranchWithReturn, self).__init__() - def construct(self, x, y, z): if x == 1: return 10 @@ -168,9 +154,6 @@ def test_nest_branch_with_return(): def test_any_with_no_return(): class NetAnyNoReturn(nn.Cell): - def __init__(self): - super(NetAnyNoReturn, self).__init__() - def construct(self, inp): result = inp.any() if result: @@ -186,9 +169,6 @@ def test_any_with_no_return(): def test_missing_construct(): class NetMissConstruct(nn.Cell): - def __init__(self): - super(NetMissConstruct, self).__init__() - def construct1(self, inp): return 5