• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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