1# This is the Python adaptation and derivative work of Myia (https://github.com/mila-iqia/myia/). 2# 3# Copyright 2020-2023 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"""Define the namespace of parse.""" 18 19from __future__ import absolute_import 20import builtins 21 22from mindspore import log as logger 23 24 25class Namespace: 26 """ 27 Base class of namespace for resolve variables. 28 29 Args: 30 name (str): The namespace's name. 31 dicts (dict): A list of dict containing the namespace's variable. 32 """ 33 34 def __init__(self, name, *dicts): 35 self.name = name 36 self.dicts = dicts 37 38 def __contains__(self, name): 39 for d in self.dicts: 40 if name in d: 41 return True 42 return False 43 44 def __getitem__(self, name): 45 for d in self.dicts: 46 if name in d: 47 return d[name] 48 raise NameError(name) 49 50 def __repr__(self): 51 return f'Namespace:{self.name}' 52 53 54class ModuleNamespace(Namespace): 55 """ 56 Namespace for global object. 57 58 Args: 59 name (str): Valid module name, it can be imported. 60 """ 61 62 def __init__(self, name): 63 mod_dict = vars(__import__(name, fromlist=['_'])) 64 builtins_dict = vars(builtins) 65 super().__init__(name, mod_dict, builtins_dict) 66 67 def __getstate__(self): 68 return (self.name,) 69 70 def __setstate__(self, state): 71 name, = state 72 mod_dict = vars(__import__(name, fromlist=['_'])) 73 builtins_dict = vars(builtins) 74 super().__init__(name, mod_dict, builtins_dict) 75 76 77class ClosureNamespace(Namespace): 78 """ 79 Namespace for function closure. 80 81 Args: 82 fn (Function): A python function. 83 """ 84 85 def __init__(self, fn): 86 name = f'{fn.__module__}..<{fn.__name__}>' 87 names = fn.__code__.co_freevars 88 cells = fn.__closure__ 89 ns = dict(zip(names, cells or ())) 90 super().__init__(name, ns) 91 92 def __getitem__(self, name): 93 d, = self.dicts 94 try: 95 return d[name].cell_contents 96 except ValueError: 97 raise UnboundLocalError(name) 98 99 100class ClassMemberNamespace(Namespace): 101 """ 102 Namespace of a class's closure. 103 104 Args: 105 obj (Object): A python class object. 106 """ 107 108 def __init__(self, obj): 109 self.__class_member_namespace__ = True 110 label = f'{obj.__module__}..<{obj.__class__.__name__}::{id(obj)}>' 111 super().__init__(label, obj) 112 113 def __getitem__(self, name): 114 d, = self.dicts 115 if name == "namespace": 116 return self 117 try: 118 if hasattr(d, name): 119 return getattr(d, name) 120 return d.__dict__[name] 121 except ValueError: 122 raise UnboundLocalError(name) 123 except KeyError: 124 cls = d.__class__ 125 # Class private attribute. 126 if name.startswith("__"): 127 private_member = "_" + cls.__name__ + name 128 if hasattr(d, private_member): 129 logger.warning(f"The private attribute or method '{name}' is used in '{cls.__name__}'. " + \ 130 f"In graph mode, '{name}' will be adjusted to '{private_member}' for parsing.") 131 return getattr(d, private_member) 132 logger.info(f"'{cls.__name__}' object has no attribute or method: '{name}', so will return None.") 133 raise AttributeError(name) 134 135 def __getattr__(self, name): 136 return self.__getitem__(name) 137