1# This is the Python adaptation and derivative work of Myia (https://github.com/mila-iqia/myia/). 2# 3# Copyright 2020 Huawei Technologies Co., Ltd 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# ============================================================================ 17"""The module of parser python object, called by c++.""" 18 19import os 20import ast 21import hashlib 22import inspect 23import types 24from dataclasses import is_dataclass 25from textwrap import dedent 26 27import asttokens 28 29from mindspore import Tensor 30from mindspore import log as logger 31from mindspore import nn 32from mindspore import ops 33from mindspore.common.api import _MindsporeFunctionExecutor 34from mindspore.common.dtype import pytype_to_dtype 35from .namespace import CellNamespace, ClosureNamespace, ClassMemberNamespace 36from .resources import parse_object_map, convert_object_map, trope_ns, SYMBOL_UNDEFINE, NO_IMPLEMENT 37 38# define return value 39RET_SUCCESS = 0 40RET_FAILURE = 0xFF 41 42# define resolve type 43RESOLVE_TYPE_NONE = 0 # resolve None 44RESOLVE_TYPE_FUNCTION = 1 # resolve function 45RESOLVE_TYPE_METHOD = 2 # resolve class method 46RESOLVE_TYPE_CLASS_TYPE = 3 # resolve class type 47RESOLVE_TYPE_CLASS_INSTANCE = 4 # resolve the class instance of common class 48RESOLVE_TYPE_INVALID = 0xFF 49 50# define the class instance detail type 51# When the type is RESOLVE_TYPE_CLASS_INSTANCE 52CLASS_INSTANCE_TYPE_CELL = 0 # class instance type is Cell 53CLASS_INSTANCE_TYPE_PRIMITIVE = 1 # class instance type is Primitive 54CLASS_INSTANCE_TYPE_INVALID = 0xFF 55 56# Ast main type 57AST_MAIN_TYPE_STMT = 0 # ast.Stmt 58AST_MAIN_TYPE_EXPR = 1 # ast.Expr 59AST_MAIN_TYPE_SLICE = 2 # ast.Slice 60AST_MAIN_TYPE_UNKNOWN = 0xFF # unknown 61 62# Ast sub type 63AST_SUB_TYPE_AND = 3 # ast.And 64AST_SUB_TYPE_OR = 4 # ast.Or 65AST_SUB_TYPE_NAME = 5 # ast.Name 66AST_SUB_TYPE_TUPLE = 6 # ast.Tuple 67AST_SUB_TYPE_SUBSCRIPT = 7 # ast.Subscript 68AST_SUB_TYPE_STARRED = 8 # ast.Starred 69AST_SUB_TYPE_ATTRIBUTE = 9 # ast.Attribute 70AST_SUB_TYPE_UNKNOWN = 0xFF # unknown 71 72# Process expr statement white list 73# add as needed, eg: "clear", "extend", "insert", "remove", "reverse" 74parse_expr_statement_white_list = ( 75 "append", 76) 77 78_builtin_function_or_method_type = type(abs) 79 80 81def create_slice_obj(start, end, step): 82 """Create slice object""" 83 return slice(start, end, step) 84 85 86def parse_cb(func, parse_method=None): 87 """Implements the function of parse.""" 88 return Parser(func, parse_method) 89 90 91def get_parse_method_of_class(obj, parse_method=None): 92 """ 93 Het parse method of class. 94 95 Args: 96 obj(Object): Instance of class. 97 parse_method(str): Save the method name. Cell object has default method named 'construct'. 98 99 Returns: 100 Function, obj's method. 101 """ 102 method = None 103 method_name = None 104 if parse_method is not None: 105 method_name = parse_method 106 elif isinstance(obj, nn.Cell): 107 if obj.enable_hook: 108 method_name = "_hook_construct" 109 else: 110 method_name = "construct" 111 if method_name is not None: 112 if hasattr(obj, method_name): 113 method = getattr(obj, method_name) 114 return method 115 116 117def get_bprop_method_of_class(obj, parse_method=None): 118 """ 119 Get bprop method of class. 120 121 Args: 122 obj (Object): Instance of class. 123 parse_method(str): Save the method name. Cell object has default method named 'bprop'. 124 125 Returns: 126 Function, obj's method. 127 """ 128 method = None 129 if isinstance(obj, nn.Cell): 130 method_name = "bprop" 131 if hasattr(obj, method_name): 132 method = getattr(obj, method_name) 133 return method 134 135# The fallback feature is enabled in default. 136# Not support change the flag during the process is alive. 137support_fallback_ = os.getenv('ENV_SUPPORT_FALLBACK') 138 139 140def resolve_symbol(namespace, symbol): 141 """ 142 Resolve a symbol. 143 144 Note: 145 Can't get function when use closure function. So save the fn on namespace. 146 147 Args: 148 namespace (Object): Symbol's namespace. 149 symbol (str): Need resolve symbol. 150 151 Returns: 152 Object, resolve result of symbol. 153 """ 154 # All exceptions need to be caught in this function 155 try: 156 resolve_ = namespace[symbol] 157 158 # list and dict is not hashable ,it can not be key for the map, just return the result 159 if isinstance(resolve_, (tuple, list, dict)): 160 return resolve_ 161 162 # dataclass may not be hashable 163 if getattr(resolve_, "__hash__") is None: 164 return resolve_ 165 166 # Raise a proper error if not using Fallback feature. 167 if support_fallback_ != '1': 168 # Raise NotImplementedError when parsing the numpy methods, but not the numpy constant. 169 if namespace.name == "numpy" and \ 170 isinstance(resolve_, (types.FunctionType, types.MethodType, types.ModuleType)): 171 raise NotImplementedError("Mindspore does not support to use the numpy methods " \ 172 "within the construct() or @ms_function decorated function in graph mode.") 173 174 # If need trope the obj 175 if resolve_ in convert_object_map: 176 resolve_ = convert_object_map.get(resolve_) 177 logger.debug("convert resolve = %r", resolve_) 178 if resolve_ == NO_IMPLEMENT: 179 raise NotImplementedError(f"Not support for `{symbol}`.") 180 except Exception as e: 181 if isinstance(e, NotImplementedError): 182 raise e 183 resolve_ = None 184 logger.debug("resolve exception occurred, value = %r", e) 185 logger.debug("resolve type is invalid, namespace = %s, symbol = %s", 186 namespace.__str__(), symbol) 187 188 if isinstance(resolve_, _MindsporeFunctionExecutor): 189 logger.debug("resolve class _MindsporeFunctionExecutor, resolve fn instead.") 190 resolve_ = resolve_.fn 191 logger.debug(f'found: {symbol} in {namespace.__str__()}, resolve: {resolve_} / {type(resolve_)}') 192 return resolve_ 193 194 195def generate_scope(obj): 196 """Generate the scope for every cell object in the network.""" 197 if isinstance(obj, nn.Cell): 198 obj.generate_scope() 199 200 201def get_scope_name(obj): 202 """Returns the scope of a cell object in one network.""" 203 if isinstance(obj, nn.Cell): 204 return obj.get_scope() 205 return None 206 207 208def get_object_key(obj): 209 """Return the function key: module + name.""" 210 obj_key = "" 211 if hasattr(obj, "__name__"): 212 if hasattr(obj, "cell_init_args"): 213 obj_key = "%s_ID" % (str(obj.__class__.__name__) + str(obj.__name__) + obj.cell_init_args) 214 obj_id = "%s_ID%d" % (str(obj.__class__.__name__) + str(obj.__name__), id(obj)) 215 else: 216 # `<class 'xxxxxxx'>` 217 # -> `xxxxxxx` 218 tag = str(obj.__class__)[8:-2] 219 if hasattr(obj, "cell_init_args"): 220 obj_key = "%s_ID" % (tag + obj.cell_init_args) 221 obj_id = "%s_ID%d" % (tag, id(obj)) 222 logger.debug("obj_key %s obj_id = %s", obj_key, obj_id) 223 224 # method has same id of different instance 225 if isinstance(obj, types.MethodType): 226 method_instance = obj.__self__ 227 instance_id = "%s_ID%d" % (str(method_instance.__class__.__name__), id(method_instance)) 228 obj_id = instance_id + obj_id + str(obj.__hash__()) 229 return obj_id, obj_key 230 231 232def is_class_member(node): 233 """Check the attr is class member variable.""" 234 type_ = node.__class__.__name__ 235 if type_ == "Attribute": 236 if not hasattr(node.value, "id"): 237 return False 238 id_ = node.value.id 239 if id_ == "self": 240 return True 241 return False 242 243 244def get_obj_id(obj): 245 """Get the obj id.""" 246 return str(id(obj)) 247 248 249def get_obj_type(obj): 250 """Get the obj type.""" 251 logger.debug("Get object type: %r", obj) 252 obj_type = RESOLVE_TYPE_INVALID 253 if obj is None: 254 obj_type = RESOLVE_TYPE_NONE 255 elif isinstance(obj, types.FunctionType): 256 obj_type = RESOLVE_TYPE_FUNCTION 257 elif isinstance(obj, types.MethodType): 258 obj_type = RESOLVE_TYPE_METHOD 259 elif isinstance(obj, type): 260 obj_type = RESOLVE_TYPE_CLASS_TYPE 261 elif _is_class_instance(obj): 262 obj_type = RESOLVE_TYPE_CLASS_INSTANCE 263 else: 264 # here for ndarray, just print its shape (in case of the array to large and print many data in screen) 265 is_ndarray = type(obj).__name__ == 'ndarray' and hasattr(obj, 'shape') 266 raise TypeError(f'Not support for this object with type `{type(obj)}` and {"shape" if is_ndarray else "value"} ' 267 f'`{obj.shape if is_ndarray else obj}`.') 268 return obj_type 269 270 271def get_class_instance_type(obj): 272 """Get the class instance detail type.""" 273 # check the obj type 274 logger.debug("Get the class type(%r)", obj) 275 class_type = CLASS_INSTANCE_TYPE_INVALID 276 if _is_class_instance(obj): 277 if isinstance(obj, nn.Cell): 278 class_type = CLASS_INSTANCE_TYPE_CELL 279 elif isinstance(obj, ops.Primitive): 280 class_type = CLASS_INSTANCE_TYPE_PRIMITIVE 281 # Add the other type base requirement 282 return class_type 283 284 285def _is_class_instance(obj): 286 """Confirm the obj is class instance.""" 287 return isinstance(obj, (nn.Cell, ops.Primitive)) or _is_dataclass_instance(obj) 288 289 290def _is_dataclass_instance(obj): 291 """check whether a class is an instance of a dataclass (and not a dataclass itself)""" 292 return is_dataclass(obj) and not isinstance(obj, type) 293 294 295def _convert_tuple_to_args_kwargs(params): 296 args = tuple() 297 kwargs = dict() 298 for param in params: 299 if isinstance(param, dict): 300 kwargs.update(param) 301 else: 302 args += (param,) 303 return (args, kwargs) 304 305 306def is_supported_create_instance_type(cls_type): 307 return issubclass(cls_type, (nn.Cell, ops.Primitive)) 308 309 310def create_instance(cls_type, params=None): 311 """Create python instance.""" 312 if not isinstance(cls_type, type): 313 logger.warning(f"create_instance(), cls_type is not a type, cls_type: {cls_type}") 314 return None 315 316 # Check the type, now only support nn.Cell and Primitive. 317 obj = None 318 if is_supported_create_instance_type(cls_type): 319 # Check arguments, only support *args or **kwargs. 320 if params is None: 321 obj = cls_type() 322 elif isinstance(params, tuple): 323 args, kwargs = _convert_tuple_to_args_kwargs(params) 324 logger.debug(f"create_instance(), args: {args}, kwargs: {kwargs}") 325 if args and kwargs: 326 obj = cls_type(*args, **kwargs) 327 elif args: 328 obj = cls_type(*args) 329 elif kwargs: 330 obj = cls_type(**kwargs) 331 # If invalid parameters. 332 if obj is None: 333 raise ValueError(f"When call 'create_instance', the parameter should be *args or **kwargs, " 334 f"but got {params.__class__.__name__}, params: {params}") 335 return obj 336 337 338def get_module_namespace(obj): 339 """Get the module's namespace.""" 340 logger.debug("get module namespace, module = %r", obj) 341 mod_namespace = None 342 if isinstance(obj, types.ModuleType): 343 mod_namespace = CellNamespace(obj.__name__) 344 else: 345 logger.warning("Module(%r) is invalid, get namespace failure!", obj) 346 return mod_namespace 347 348 349def get_class_member_namespace_symbol(obj): 350 """Get obj class member type.""" 351 logger.debug("get class instance namespace, object = %r", obj) 352 class_namespace = ClassMemberNamespace(obj) 353 logger.debug("class namesapce = %r", class_namespace) 354 return class_namespace 355 356 357def get_dataclass_attributes(cls): 358 """Get attributes of dataclass.""" 359 fields = cls.__dataclass_fields__ 360 attributes = {name: pytype_to_dtype(field.type) 361 for name, field in fields.items()} 362 return attributes 363 364 365def get_dataclass_methods(cls): 366 """Get functions of dataclass.""" 367 methods = {name: getattr(cls, name) 368 for name in dir(cls) 369 if isinstance(getattr(cls, name), (types.FunctionType,))} 370 return methods 371 372 373def convert_to_ms_tensor(data): 374 """Convert C++ tensor to mindspore tensor.""" 375 return Tensor(data) 376 377 378def get_object_description(obj, fname, fline): 379 """return method or funcition description for error report, include location, class name, etc.""" 380 if isinstance(obj, types.MethodType): 381 obj_cls = obj.__self__.__class__ 382 class_name = f'{obj_cls.__module__}.{obj_cls.__qualname__}' 383 cls_fname = inspect.getfile(obj_cls) 384 _, cls_fline = inspect.getsourcelines(obj_cls) 385 class_loc = f'{cls_fname}:{cls_fline}' 386 return f"bound method '{obj.__name__}' at {fname}:{fline} of <{class_name} at {class_loc} object>" 387 if isinstance(obj, types.FunctionType): 388 return f"function '{obj.__name__}' at {fname}:{fline}" 389 if isinstance(obj, ast.FunctionDef): 390 return f"function '{obj.name}' at {fname}:{fline}" 391 if isinstance(obj, ast.Attribute): 392 return f"attribute " 393 return str(obj) 394 395 396def expand_expr_statement(node): 397 """ 398 Process the expr statement and expand it. 399 400 Returns: 401 tuple, (True, expr.value, x)/(False, None, None). 402 """ 403 if isinstance(node, ast.Expr): 404 expr_value = node.value 405 if isinstance(expr_value, ast.Call): 406 func = expr_value.func 407 if isinstance(func, ast.Attribute) and \ 408 hasattr(func, "attr") and \ 409 hasattr(func, "value"): 410 method = func.attr 411 target = func.value 412 if method in parse_expr_statement_white_list: 413 logger.debug("Expand expr, target:%s, method:%s", target, method) 414 return True, expr_value, target 415 if not isinstance(expr_value, ast.Str): 416 return True, expr_value 417 return (False,) 418 419 420def get_ast_namespace_symbol(obj): 421 """Get obj type and namespace and symbol.""" 422 # step 1:get symbol from object map 423 ops_info = parse_object_map.get(type(obj), SYMBOL_UNDEFINE) 424 logger.debug("ops info = %r", ops_info) 425 return ops_info 426 427 428def get_operation_namespace_symbol(var: str): 429 """Get operation namespace and symbol.""" 430 ops_info = (trope_ns, var) 431 logger.debug("get operation ops info = %r", ops_info) 432 return ops_info 433 434 435def get_ast_type(node): 436 """Get the ast type.""" 437 ast_type = AST_SUB_TYPE_UNKNOWN 438 if isinstance(node, ast.And): 439 ast_type = AST_SUB_TYPE_AND 440 elif isinstance(node, ast.Or): 441 ast_type = AST_SUB_TYPE_OR 442 elif isinstance(node, ast.Name): 443 ast_type = AST_SUB_TYPE_NAME 444 elif isinstance(node, ast.Tuple): 445 ast_type = AST_SUB_TYPE_TUPLE 446 elif isinstance(node, ast.Subscript): 447 ast_type = AST_SUB_TYPE_SUBSCRIPT 448 elif isinstance(node, ast.Starred): 449 ast_type = AST_SUB_TYPE_STARRED 450 elif isinstance(node, ast.Attribute): 451 ast_type = AST_SUB_TYPE_ATTRIBUTE 452 else: 453 ast_type = AST_SUB_TYPE_UNKNOWN 454 return ast_type 455 456 457def get_node_type(node): 458 """Process an ast node.""" 459 method_name = f'{node.__class__.__name__}' 460 node_type = [method_name] 461 # judge the ast main type 462 if isinstance(node, ast.stmt): 463 node_type.append(AST_MAIN_TYPE_STMT) 464 elif isinstance(node, (ast.expr, ast.slice)) or node is None: 465 # ast.slice and ast.expr should be expr 466 node_type.append(AST_MAIN_TYPE_EXPR) 467 else: 468 node_type.append(AST_MAIN_TYPE_UNKNOWN) 469 return node_type 470 471 472def get_args_default_values(node): 473 """get the args'default values of parse object.""" 474 nondefaults = [None] * (len(node.args.args) - len(node.args.defaults)) 475 defaults = nondefaults + node.args.defaults + node.args.kw_defaults 476 if node.args.vararg: 477 defaults.append(None) 478 if node.args.kwarg: 479 defaults.append(None) 480 return defaults 481 482 483def get_args(node): 484 """Get the arg of parse object.""" 485 args = [] 486 # process position args 487 for arg in node.args.args: 488 args.append(arg) 489 490 # process kwonlyargs: kwonlyargs is append after position args 491 if node.args.kwonlyargs: 492 for kwarg in node.args.kwonlyargs: 493 args.append(kwarg) 494 # process vararg: vararg is append after kwonlyargs 495 if node.args.vararg: 496 args.append(node.args.vararg) 497 # process kwarg: kwarg is append after vararg 498 if node.args.kwarg: 499 args.append(node.args.kwarg) 500 return args 501 502 503def eval_script(exp_str, params): 504 """Evaluate a python expression.""" 505 if not isinstance(params, tuple): 506 raise ValueError(f"eval_script(), params is not a tuple, params: {params}") 507 if len(params) != 2: 508 raise ValueError(f"eval_script(), params tuple length is wrong, params: {params}") 509 510 logger.debug(f'exp_str: {exp_str}, params: {params}') 511 global_params = params[0] 512 local_params = params[1] 513 obj = eval(exp_str, global_params, local_params) 514 if obj is None: 515 raise ValueError(f"When call 'eval', the result is none. exp_str: '{exp_str}'") 516 return obj 517 518 519class Parser: 520 """ 521 Parser python code to ast tree. 522 523 Args: 524 fn(FunctionType/MethodType): Need parse object instance. 525 parse_method(ExtendInfoOfParseObj): Extend information for parse the function. 526 ast_cache: Dictionary for caching ast tree. 527 """ 528 ast_cache = {} 529 530 def __init__(self, fn: (types.FunctionType, types.MethodType), parse_method=None) -> None: 531 self.fn = fn 532 self.parse_method = parse_method 533 self.line_offset = 0 534 self.filename: str = inspect.getfile(inspect.unwrap(self.fn)) 535 536 # Used to resolve mindspore builtin ops namespace. 537 self.ms_common_ns = CellNamespace('mindspore.common') 538 self.ms_ops_ns = CellNamespace('mindspore.ops') 539 self.ms_ops_c_ns = CellNamespace('mindspore.ops.composite') 540 self.ms_ops_c_multitype_ns = CellNamespace('mindspore.ops.composite.multitype_ops') 541 self.ms_ops_p_ns = CellNamespace('mindspore.ops.operations') 542 # Used to resolve the function's globals namespace. 543 self.global_namespace = CellNamespace(fn.__module__) 544 self.function_module = fn.__module__ 545 # Used to resolve the function's nonlocals. 546 self.closure_namespace = ClosureNamespace(inspect.unwrap(self.fn)) 547 self.function_name = fn.__name__ 548 self.col_offset = 0 549 550 def parse(self): 551 """Parse the function or method.""" 552 logger.debug("fn = %r", self.fn) 553 if isinstance(self.fn, (types.FunctionType, types.MethodType)): 554 try: 555 lines, self.line_offset = inspect.getsourcelines(self.fn) 556 except OSError as e: 557 if e.__str__() == "could not get source code": 558 raise OSError(f"Mindspore can not compile temporary source code in terminal. " 559 f"Please write source code to a python file and run the file.") 560 raise e 561 original_src = ''.join(lines) 562 hexstr = hashlib.sha256(original_src.encode()).hexdigest() 563 ast_tokens = Parser.ast_cache.get(hexstr) 564 if not ast_tokens: 565 src = dedent(original_src) 566 self.col_offset = \ 567 len(original_src.split('\n')[0]) - len(src.split('\n')[0]) 568 logger.debug("Get source = %s", src) 569 try: 570 ast_tokens = asttokens.ASTTokens(src, parse=True) 571 except IndentationError as idt_err: 572 idt_err.filename = self.filename 573 idt_err.lineno = self.line_offset 574 idt_err.msg = f"There are incorrect indentations in definition or comment of function: " \ 575 f"'{self.fn.__qualname__}'." 576 raise idt_err 577 Parser.ast_cache[hexstr] = ast_tokens 578 return ast_tokens, ast_tokens.tree 579 580 logger.error("Fn type is invalid") 581 return None, None 582 583 def is_unsupported_namespace(self, value): 584 unsupported = isinstance(value, _builtin_function_or_method_type) and value not in convert_object_map 585 logger.debug(f'`{value}` unsupported: {unsupported}.') 586 return unsupported 587 588 def get_namespace_symbol(self, var: str): 589 """Get symbol type and namespace and symbol.""" 590 if var in self.closure_namespace: 591 logger.debug(f"Found `{var}` in closure_namespace {self.closure_namespace.__str__()}") 592 return self.closure_namespace, var 593 if var in self.global_namespace: 594 logger.debug(f"Found `{var}` in global_namespace {self.global_namespace.__str__()}") 595 value = self.global_namespace[var] 596 if self.is_unsupported_namespace(value): 597 error_info = f"The builtin function '{var}' of python is not supported in graph mode." 598 return None, var, error_info 599 return self.global_namespace, var 600 601 error_info = f"The symbol '{var}' is not defined in function '{self.function_name}'." 602 return None, var, error_info 603 604 def is_unsupported_builtin_type(self, value_type): 605 """To check if not supported builtin type""" 606 logger.debug(f'value_type: {value_type}, {type([])}, {type(())}.') 607 return value_type in (list, tuple) 608 609 def is_supported_namespace_module(self, value): 610 """To check if the module is allowed to support.""" 611 # Check `mindspore` namespace. 612 if not hasattr(value, '__name__'): 613 logger.debug(f'`{str(value)}` has no `__name__` attribute.') 614 return True 615 name = value.__name__ 616 if name == 'mindspore': 617 logger.debug(f'Found `{name}` in mindspore root namespace.') 618 return True 619 620 # Check `Tensor` namespace. 621 if value == Tensor: 622 logger.debug(f'Not support `{name}`.') 623 return False 624 625 # Check `builtins` namespace. 626 if hasattr(value, '__module__'): # Not types.ModuleType 627 mod = value.__module__ 628 if mod == 'builtins': 629 logger.debug(f'Found `{name}` in `builtins` namespace.') 630 return True 631 632 # We suppose it's supported if not a Module. 633 if not isinstance(value, types.ModuleType): 634 logger.debug(f'Found `{name}`, not a module.') 635 return True 636 637 # Check supported Module namespace. 638 rightmost_name = name.split('.')[-1] 639 if rightmost_name in self.ms_ops_ns: 640 logger.debug(f'Found `{name}`({rightmost_name}) in ops namespace: {str(self.ms_ops_ns)}.') 641 return True 642 if rightmost_name in self.ms_ops_c_ns: 643 logger.debug(f'Found `{name}`({rightmost_name}) in C namespace: {str(self.ms_ops_c_ns)}.') 644 return True 645 if rightmost_name in self.ms_ops_c_multitype_ns: 646 logger.debug( 647 f'Found `{name}`({rightmost_name}) in C.multitype namespace: {str(self.ms_ops_c_multitype_ns)}.') 648 return True 649 if rightmost_name in self.ms_ops_p_ns: 650 logger.debug(f'Found `{name}`({rightmost_name}) in P namespace: {str(self.ms_ops_p_ns)}.') 651 return True 652 if rightmost_name in self.ms_common_ns: 653 logger.debug(f'Found `{name}`({rightmost_name}) in P namespace: {str(self.ms_common_ns)}.') 654 return True 655 if rightmost_name in trope_ns: 656 logger.debug(f'Found `{name}`({rightmost_name}) in trope namespace: {str(trope_ns)}.') 657 return True 658 659 logger.error(f'Not found `{name}` in mindspore supported namespace.') 660 return False 661 662 def get_builtin_namespace_symbol(self, var: str): 663 """Get mindspore builtin namespace and symbol.""" 664 if var in self.closure_namespace: 665 logger.debug(f"Found `{var}` in closure_namespace {self.closure_namespace.__str__()}.") 666 return self.closure_namespace, var 667 if var in self.global_namespace: 668 logger.debug(f"Found `{var}` in global_namespace {self.global_namespace.__str__()}.") 669 value = self.global_namespace[var] 670 value_str = value.__name__ if hasattr(value, '__name__') else str(value) 671 logger.debug(f"value: {type(value)}, `{value_str}`, hasattr(__name__): {hasattr(value, '__name__')}.") 672 # To check if allowed to support. 673 if self.is_unsupported_namespace(value): 674 return self.global_namespace, var, value 675 if self.is_unsupported_builtin_type(value): 676 return self.global_namespace, var, value 677 if not self.is_supported_namespace_module(value): # Check if support including instance of types.ModuleType 678 return self.global_namespace, var, value 679 return self.global_namespace, var 680 681 error_info = f"The name '{var}' is not defined, or not supported in graph mode." 682 logger.debug(f'error info: {error_info}') 683 return None, var, error_info 684 685 def analyze_super(self, class_type_node, subclass_instance): 686 """Analyze super and return a class instance.""" 687 sub_class = type(subclass_instance) 688 if class_type_node is None: 689 return super(sub_class, subclass_instance) 690 if isinstance(class_type_node, ast.Name): 691 class_name = getattr(class_type_node, 'id') 692 elif isinstance(class_type_node, ast.Attribute): 693 class_name = getattr(class_type_node, 'attr') 694 else: 695 raise ValueError(f"The first argument of 'super()' must be a class type, " 696 f"but got {class_type_node.__class__.__name__}.") 697 698 target_father_class = None 699 for class_element in sub_class.mro(): 700 if class_element.__name__ == class_name: 701 target_father_class = class_element 702 break 703 if target_father_class is None: 704 raise ValueError(f"The second argument of 'super()' must be 'self', " 705 f"but got {subclass_instance}.") 706 return super(target_father_class, subclass_instance) 707 708 def get_location(self, node): 709 """ 710 Get location of node start and end line no. 711 712 Args: 713 node: AST op node or tuple or List. This is a node in the ANF diagram, 714 here is the code location to get this node. 715 716 Returns: 717 List, [fileName, linestart, colstart, lineend, colend]. 718 """ 719 ret = [self.filename] 720 err_exit = 0 721 if isinstance(node, (list, tuple)): 722 node_size = len(node) 723 if node_size == 0: 724 err_exit = 1 725 else: 726 start_node = node[0] 727 end_node = node[-1] 728 else: 729 start_node = node 730 end_node = node 731 732 if err_exit == 0: 733 if hasattr(start_node, "lineno") and \ 734 hasattr(end_node, "col_offset"): 735 start_lineno, start_colno = start_node.first_token.start 736 end_lineno, end_colno = end_node.last_token.end 737 start_lineno += self.line_offset - 1 738 start_colno += self.col_offset 739 end_lineno += self.line_offset - 1 740 end_colno += self.col_offset 741 ret = ret + [start_lineno, start_colno, end_lineno, end_colno] 742 else: 743 ret = ret + [0, 0, 0, 0] 744 return ret 745