File: test_zipimporter.py

package info (click to toggle)
python-enaml 0.19.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 13,284 kB
  • sloc: python: 31,443; cpp: 4,499; makefile: 140; javascript: 68; lisp: 53; sh: 20
file content (153 lines) | stat: -rw-r--r-- 5,068 bytes parent folder | download
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
144
145
146
147
148
149
150
151
152
153
#------------------------------------------------------------------------------
# Copyright (c) 2013-2025, Nucleic Development Team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file LICENSE, distributed with this software.
#------------------------------------------------------------------------------
import os
import sys
import enaml
import struct
import marshal
import zipfile
from importlib.machinery import ModuleSpec

import pytest

from enaml.core.parser import parse
from enaml.core.enaml_compiler import EnamlCompiler
from enaml.core.import_hooks import MAGIC_NUMBER, make_file_info, EnamlImporter
from utils import wait_for_window_displayed


def generate_cache(path):
    #: Compile
    with open(path) as f:
        ast = parse(f.read(), path)
    code = EnamlCompiler.compile(ast, path)

    #: Generate cache
    with open('tmp.enamlc', 'wb') as f:
        f.write(MAGIC_NUMBER)
        f.write(struct.pack('i', int(os.path.getmtime(path))))
        marshal.dump(code, f)
    with open('tmp.enamlc', 'rb') as f:
        data = f.read()
    #: Cleanup
    if os.path.exists('tmp.enamlc'):
        os.remove('tmp.enamlc')

    return data


def make_library(lib):
    # Create a library.zip with the examples.

    root = os.path.normpath(os.path.join(os.path.dirname(__file__), '..', '..',
                            'examples', 'widgets'))

    with zipfile.ZipFile(lib, 'w') as zf:
        for src, dst in [
                         (os.path.join(root, 'buttons.enaml'),
                          'buttons.enaml'),
                         (None, 'package/__init__.py'),
                         (os.path.join(root, 'form.enaml'),
                          'package/form.enaml'),
                         (None, 'package/subpackage/__init__.py'),
                         (os.path.join(root, 'slider.enaml'),
                          'package/subpackage/slider.enaml'),
                         ]:
            if src:
                zf.write(src, dst, compress_type=zipfile.ZIP_DEFLATED)
            else:
                #: Create the __init__.py
                zf.writestr(dst, '', compress_type=zipfile.ZIP_DEFLATED)

        #: Generate cache for splitter and notebook
        for src, dst in [
                (os.path.join(root, 'splitter.enaml'),
                 make_file_info('splitter.enaml').cache_path),
                (os.path.join(root, 'notebook.enaml'),
                 make_file_info('package/subpackage/'
                                'notebook.enaml').cache_path)
                ]:
            zf.writestr(dst, generate_cache(src),
                        compress_type=zipfile.ZIP_DEFLATED)


@pytest.fixture
def zip_library():
    """ Add and remove library.zip from the sys path

    """
    lib = 'library.zip'
    # Create the zip
    make_library(lib)

    # Add to sys.path
    sys.path.append(lib)

    # Pytest handle the cleanup without the need for try finally close
    yield lib

    sys.path.remove(lib)
    #: Cleanup
    if os.path.exists(lib):
        os.remove(lib)


def assert_window_displays(enaml_qtbot, enaml_sleep, window):
    #: Make sure the imported library actually works
    window.show()
    window.send_to_front()
    wait_for_window_displayed(enaml_qtbot, window)
    enaml_qtbot.wait(enaml_sleep*1000)


def test_zipimport_from_module(enaml_qtbot, enaml_sleep, zip_library):
    with enaml.imports():
        # Test import from library.zip/buttons.enaml
        import buttons

    assert buttons.__name__ == "buttons"
    assert buttons.__file__
    assert buttons.__cached__
    assert isinstance(buttons.__loader__, EnamlImporter)
    assert isinstance(buttons.__spec__, ModuleSpec)

    assert_window_displays(enaml_qtbot, enaml_sleep, buttons.Main())


def test_zipimport_from_package(enaml_qtbot, enaml_sleep, zip_library):
    with enaml.imports():
        # Test import from library.zip/package/form.enaml
        from package import form

    assert_window_displays(enaml_qtbot, enaml_sleep, form.Main())


def test_zipimport_from_subpackage(enaml_qtbot, enaml_sleep, zip_library):
    with enaml.imports():
        # Test import from library.zip/package/subpackage/slider.enaml
        from package.subpackage import slider

    assert_window_displays(enaml_qtbot, enaml_sleep, slider.Main())


def test_zipimport_module_from_cache(enaml_qtbot, enaml_sleep, zip_library):
    with enaml.imports():
        # Test import from
        # library.zip/__enamlcache__/slider-enaml-py<ver>-cv<ver>.enamlc
        import splitter

    assert_window_displays(enaml_qtbot, enaml_sleep, splitter.Main())


def test_zipimport_package_from_cache(enaml_qtbot, enaml_sleep, zip_library):
    with enaml.imports():
        # Test import from enamlcache subpackage within zip
        # Test import from library.zip/package/subpackage/__enamlcache__/
        #                                 notebook-enaml-py<ver>-cv<ver>.enamlc
        from package.subpackage import notebook
    assert_window_displays(enaml_qtbot, enaml_sleep, notebook.Main())