summaryrefslogtreecommitdiff
path: root/fs/tests/test_importhook.py
blob: e0d1ad7e74ada0a79e259b61e87d42b75e2d8286 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

import sys
import unittest
import marshal
import imp
import struct
from textwrap import dedent

from fs.expose.importhook import FSImportHook
from fs.tempfs import TempFS
from fs.zipfs import ZipFS

from six import b


class TestFSImportHook(unittest.TestCase):

    def setUp(self):
        pass

    def tearDown(self):
        for mph in list(sys.meta_path):
            if isinstance(mph,FSImportHook):
                sys.meta_path.remove(mph)
        for ph in list(sys.path_hooks):
            if isinstance(ph, type) and issubclass(ph,FSImportHook):
                sys.path_hooks.remove(ph)
        for (k,v) in sys.modules.items():
            if k.startswith("fsih_"):
                del sys.modules[k]
            elif hasattr(v,"__loader__"):
                if isinstance(v.__loader__,FSImportHook):
                    del sys.modules[k]
        sys.path_importer_cache.clear()

    def _init_modules(self,fs):
        fs.setcontents("fsih_hello.py",b(dedent("""
            message = 'hello world!'
        """)))
        fs.makedir("fsih_pkg")
        fs.setcontents("fsih_pkg/__init__.py",b(dedent("""
            a = 42
        """)))
        fs.setcontents("fsih_pkg/sub1.py",b(dedent("""
            import fsih_pkg
            from fsih_hello import message
            a = fsih_pkg.a
        """)))
        fs.setcontents("fsih_pkg/sub2.pyc",self._getpyc(b(dedent("""
            import fsih_pkg
            from fsih_hello import message
            a = fsih_pkg.a * 2
        """))))

    def _getpyc(self,src):
        """Get the .pyc contents to match th given .py source code."""
        code = imp.get_magic() + struct.pack("<i",0)
        code += marshal.dumps(compile(src,__file__,"exec"))
        return code

    def test_loader_methods(self):
        t = TempFS()
        self._init_modules(t)
        ih = FSImportHook(t)
        sys.meta_path.append(ih)
        try:
            self.assertEquals(ih.find_module("fsih_hello"),ih)
            self.assertEquals(ih.find_module("fsih_helo"),None)
            self.assertEquals(ih.find_module("fsih_pkg"),ih)
            self.assertEquals(ih.find_module("fsih_pkg.sub1"),ih)
            self.assertEquals(ih.find_module("fsih_pkg.sub2"),ih)
            self.assertEquals(ih.find_module("fsih_pkg.sub3"),None)
            m = ih.load_module("fsih_hello")
            self.assertEquals(m.message,"hello world!")
            self.assertRaises(ImportError,ih.load_module,"fsih_helo")
            ih.load_module("fsih_pkg")
            m = ih.load_module("fsih_pkg.sub1")
            self.assertEquals(m.message,"hello world!")
            self.assertEquals(m.a,42)
            m = ih.load_module("fsih_pkg.sub2")
            self.assertEquals(m.message,"hello world!")
            self.assertEquals(m.a,42 * 2)
            self.assertRaises(ImportError,ih.load_module,"fsih_pkg.sub3")
        finally:
            sys.meta_path.remove(ih)
            t.close()

    def _check_imports_are_working(self):
        try:
            import fsih_hello
            self.assertEquals(fsih_hello.message,"hello world!")
            try:
                import fsih_helo
            except ImportError:
                pass
            else:
                assert False, "ImportError not raised"
            import fsih_pkg
            import fsih_pkg.sub1
            self.assertEquals(fsih_pkg.sub1.message,"hello world!")
            self.assertEquals(fsih_pkg.sub1.a,42)
            import fsih_pkg.sub2
            self.assertEquals(fsih_pkg.sub2.message,"hello world!")
            self.assertEquals(fsih_pkg.sub2.a,42 * 2)
            try:
                import fsih_pkg.sub3
            except ImportError:
                pass
            else:
                assert False, "ImportError not raised"
        finally:
            for k in sys.modules.keys():
                if k.startswith("fsih_"):
                    del sys.modules[k]

    def test_importer_on_meta_path(self):
        t = TempFS()
        self._init_modules(t)
        ih = FSImportHook(t)
        sys.meta_path.append(ih)
        try:
            self._check_imports_are_working()
        finally:
            sys.meta_path.remove(ih)
            t.close()

    def test_url_on_sys_path(self):
        t = TempFS()
        zpath = t.getsyspath("modules.zip")
        z = ZipFS(zpath,"w")
        self._init_modules(z)
        z.close()
        z = ZipFS(zpath,"r")
        assert z.isfile("fsih_hello.py")
        z.close()
        sys.path.append("zip://" + zpath)
        FSImportHook.install()
        try:
            self._check_imports_are_working()
        finally:
            sys.path_hooks.remove(FSImportHook)
            sys.path.pop()
            t.close()