This instance will be upgraded to Heptapod 0.31.0rc on 2022-05-19 at 11:00 UTC+2 (a few minutes of down time)

module.py 4.97 KB
Newer Older
1
2
3
4
"""
Module objects.
"""

5
from pypy.interpreter.baseobjspace import W_Root
6
from pypy.interpreter.error import OperationError
7
from rpython.rlib.objectmodel import we_are_translated, not_rpython
8

9
10

class Module(W_Root):
11
12
    """A module."""

13
    _immutable_fields_ = ["w_dict"]
14

Armin Rigo's avatar
Armin Rigo committed
15
16
    _frozen = False

17
    def __init__(self, space, w_name, w_dict=None, add_package=True):
18
        self.space = space
19
        if w_dict is None:
20
            w_dict = space.newdict(module=True)
21
22
        self.w_dict = w_dict
        self.w_name = w_name
23
        if w_name is not None:
24
            space.setitem(w_dict, space.new_interned_str('__name__'), w_name)
25
26
27
28
29
        if add_package:
            # add the __package__ attribute only when created from internal
            # code, but not when created from Python code (as in CPython)
            space.setitem(w_dict, space.new_interned_str('__package__'),
                          space.w_None)
30
        self.startup_called = False
31

Armin Rigo's avatar
Armin Rigo committed
32
33
34
35
36
37
38
    def _cleanup_(self):
        """Called by the annotator on prebuilt Module instances.
        We don't have many such modules, but for the ones that
        show up, remove their __file__ rather than translate it
        statically inside the executable."""
        try:
            space = self.space
39
            space.delitem(self.w_dict, space.newtext('__file__'))
Armin Rigo's avatar
Armin Rigo committed
40
41
42
        except OperationError:
            pass

43
    @not_rpython
44
    def install(self):
45
        """installs this module into space.builtin_modules"""
46
        modulename = self.space.text0_w(self.w_name)
47
        self.space.builtin_modules[modulename] = self
48

49
    @not_rpython
50
    def setup_after_space_initialization(self):
51
        """to allow built-in modules to do some more setup
52
53
        after the space is fully initialized."""

54
55
56
57
    def init(self, space):
        """This is called each time the module is imported or reloaded
        """
        if not self.startup_called:
Armin Rigo's avatar
Armin Rigo committed
58
59
60
61
62
63
            if not we_are_translated():
                # this special case is to handle the case, during annotation,
                # of module A that gets frozen, then module B (e.g. during
                # a getdict()) runs some code that imports A
                if self._frozen:
                    return
64
65
66
            self.startup_called = True
            self.startup(space)

67
    def startup(self, space):
68
69
        """This is called at runtime on import to allow the module to
        do initialization when it is imported for the first time.
70
        """
71
72
73

    def shutdown(self, space):
        """This is called when the space is shut down, just after
74
        sys.exitfunc(), if the module has been imported.
75
        """
76

77
    def getdict(self, space):
78
79
80
81
        return self.w_dict

    def descr_module__new__(space, w_subtype, __args__):
        module = space.allocate_instance(Module, w_subtype)
82
        Module.__init__(module, space, None, add_package=False)
83
        return module
84

85
    def descr_module__init__(self, w_name, w_doc=None):
86
87
        space = self.space
        self.w_name = w_name
88
        if w_doc is None:
89
            w_doc = space.w_None
Anders Chrigstrom's avatar
Anders Chrigstrom committed
90
91
        space.setitem(self.w_dict, space.new_interned_str('__name__'), w_name)
        space.setitem(self.w_dict, space.new_interned_str('__doc__'), w_doc)
92
93

    def descr__reduce__(self, space):
94
        w_name = space.finditem(self.w_dict, space.newtext('__name__'))
95
        if (w_name is None or
96
            not space.isinstance_w(w_name, space.w_text)):
97
98
99
100
101
102
103
104
            # maybe raise exception here (XXX this path is untested)
            return space.w_None
        w_modules = space.sys.get('modules')
        if space.finditem(w_modules, w_name) is None:
            #not imported case
            from pypy.interpreter.mixedmodule import MixedModule
            w_mod    = space.getbuiltinmodule('_pickle_support')
            mod      = space.interp_w(MixedModule, w_mod)
105
            new_inst = mod.get('module_new')
106
107
108
            return space.newtuple([new_inst,
                                   space.newtuple([w_name,
                                                   self.getdict(space)]),
109
110
111
                                  ])
        #already imported case
        w_import = space.builtin.get('__import__')
Gabriel Lavoie's avatar
Gabriel Lavoie committed
112
113
114
115
116
117
        tup_return = [
            w_import,
            space.newtuple([
                w_name,
                space.w_None,
                space.w_None,
118
                space.newtuple([space.newtext('')])
Gabriel Lavoie's avatar
Gabriel Lavoie committed
119
120
121
122
            ])
        ]

        return space.newtuple(tup_return)
123

124
125
126
    def descr_module__repr__(self, space):
        from pypy.interpreter.mixedmodule import MixedModule
        if self.w_name is not None:
127
            name = space.text_w(space.repr(self.w_name))
128
129
130
        else:
            name = "'?'"
        if isinstance(self, MixedModule):
131
            return space.newtext("<module %s (built-in)>" % name)
132
        try:
133
            w___file__ = space.getattr(self, space.newtext('__file__'))
134
            __file__ = space.text_w(space.repr(w___file__))
135
136
        except OperationError:
            __file__ = '?'
137
        return space.newtext("<module %s from %s>" % (name, __file__))