File: test__all__.py

package info (click to toggle)
kitchen 1.2.4-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 2,044 kB
  • ctags: 1,493
  • sloc: python: 10,651; makefile: 14; sh: 4
file content (193 lines) | stat: -rw-r--r-- 7,946 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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# -*- coding: utf-8 -*-
from nose import tools

import os
import types
import warnings

def logit(msg):
    log = open('/var/tmp/test.log', 'a')
    log.write('%s\n' % msg)
    log.close()

class NoAll(RuntimeError):
    pass

class FailedImport(RuntimeError):
    pass

class Test__all__(object):
    '''Test that every function in __all__ exists and that no public methods
    are missing from __all__
    '''
    known_private = set([('kitchen', 'collections', 'version_tuple_to_string'),
        ('kitchen.collections', 'strictdict', 'defaultdict'),
        ('kitchen', 'i18n', 'version_tuple_to_string'),
        ('kitchen', 'i18n', 'to_bytes'),
        ('kitchen', 'i18n', 'to_unicode'),
        ('kitchen', 'i18n', 'ENOENT'),
        ('kitchen', 'i18n', 'byte_string_valid_encoding'),
        ('kitchen', 'i18n', 'isbasestring'),
        ('kitchen', 'i18n', 'partial'),
        ('kitchen', 'iterutils', 'isbasestring'),
        ('kitchen', 'iterutils', 'version_tuple_to_string'),
        ('kitchen', 'pycompat24', 'version_tuple_to_string'),
        ('kitchen', 'pycompat25', 'version_tuple_to_string'),
        ('kitchen.pycompat25.collections', '_defaultdict', 'b_'),
        ('kitchen', 'pycompat27', 'version_tuple_to_string'),
        ('kitchen.pycompat27', 'subprocess', 'MAXFD'),
        ('kitchen.pycompat27', 'subprocess', 'list2cmdline'),
        ('kitchen.pycompat27', 'subprocess', 'mswindows'),
        ('kitchen', 'text', 'version_tuple_to_string'),
        ('kitchen.text', 'converters', 'b_'),
        ('kitchen.text', 'converters', 'b64decode'),
        ('kitchen.text', 'converters', 'b64encode'),
        ('kitchen.text', 'converters', 'ControlCharError'),
        ('kitchen.text', 'converters', 'guess_encoding'),
        ('kitchen.text', 'converters', 'html_entities_unescape'),
        ('kitchen.text', 'converters', 'isbytestring'),
        ('kitchen.text', 'converters', 'isunicodestring'),
        ('kitchen.text', 'converters', 'process_control_chars'),
        ('kitchen.text', 'converters', 'XmlEncodeError'),
        ('kitchen.text', 'misc', 'b_'),
        ('kitchen.text', 'misc', 'chardet'),
        ('kitchen.text', 'misc', 'ControlCharError'),
        ('kitchen.text', 'display', 'b_'),
        ('kitchen.text', 'display', 'ControlCharError'),
        ('kitchen.text', 'display', 'to_bytes'),
        ('kitchen.text', 'display', 'to_unicode'),
        ('kitchen.text', 'utf8', 'b_'),
        ('kitchen.text', 'utf8', 'byte_string_textual_width_fill'),
        ('kitchen.text', 'utf8', 'byte_string_valid_encoding'),
        ('kitchen.text', 'utf8', 'fill'),
        ('kitchen.text', 'utf8', 'isunicodestring'),
        ('kitchen.text', 'utf8', 'textual_width'),
        ('kitchen.text', 'utf8', 'textual_width_chop'),
        ('kitchen.text', 'utf8', 'to_bytes'),
        ('kitchen.text', 'utf8', 'to_unicode'),
        ('kitchen.text', 'utf8', 'wrap'),
        ])
    lib_dir = os.path.join(os.path.dirname(__file__), '..', 'kitchen')

    def setUp(self):
        # Silence deprecation warnings
        warnings.simplefilter('ignore', DeprecationWarning)
    def tearDown(self):
        warnings.simplefilter('default', DeprecationWarning)

    def walk_modules(self, basedir, modpath):
        files = os.listdir(basedir)
        files.sort()
        for fn in files:
            path = os.path.join(basedir, fn)
            if os.path.isdir(path):
                pkg_init = os.path.join(path, '__init__.py')
                if os.path.exists(pkg_init):
                    yield pkg_init, modpath + fn
                    for p, m in self.walk_modules(path, modpath + fn + '.'):
                        yield p, m
                continue
            if not fn.endswith('.py') or fn == '__init__.py':
                continue
            yield path, modpath + fn[:-3]

    def check_has__all__(self, modpath):
        # This heuristic speeds up the process by removing, de facto,
        # most test modules (and avoiding the auto-executing ones).
        f = None
        try:
            try:
                f = open(modpath, 'r', encoding='utf-8')
                tools.ok_('__all__' in f.read(), '%s does not contain __all__' % modpath)
            except IOError as e:
                tools.ok_(False, '%s' % e)
        finally:
            if f:
                f.close()

    def test_has__all__(self):
        '''
        For each module, check that it has an __all__
        '''
        # Blacklisted modules and packages
        blacklist = set([ ])

        for path, modname in [m for m in self.walk_modules(self.lib_dir, '')
                if m[1] not in blacklist]:
            # Check that it has an __all__
            yield self.check_has__all__, path

    def check_everything_in__all__exists(self, modname, modpath):
        names = {}
        exec('from %s import %s' % (modpath, modname), names)
        if not hasattr(names[modname], '__all__'):
            # This should have been reported by test_has__all__
            return

        interior_names = {}
        try:
            exec('from %s.%s import *' % (modpath, modname), interior_names)
        except Exception as e:
            # Include the module name in the exception string
            tools.ok_(False, '__all__ failure in %s: %s: %s' % (
                      modname, e.__class__.__name__, e))
        if '__builtins__' in interior_names:
            del interior_names['__builtins__']
        keys = set(interior_names)
        all = set(names[modname].__all__)
        tools.ok_(keys == all)

    def test_everything_in__all__exists(self):
        '''
        For each name in module's __all__, check that it exists
        '''
        # Blacklisted modules and packages
        blacklist = set([ ])

        for path, modname in [m for m in self.walk_modules(self.lib_dir, '')
                if m[1] not in blacklist]:
            # From path, deduce the module name
            from_name = path[path.find('../kitchen') + 3:]
            if from_name.endswith('__init__.py'):
                # Remove __init__.py as well as the filename
                from_name = os.path.dirname(from_name)
            from_name = os.path.dirname(from_name)
            from_name = from_name.translate({ord('/'): '.'})
            yield self.check_everything_in__all__exists, modname.split('.')[-1], from_name


    def check__all__is_complete(self, modname, modpath):
        names = {}
        exec('from %s import %s' % (modpath, modname), names)
        if not hasattr(names[modname], '__all__'):
            # This should have been reported by test_has__all__
            return

        mod = names[modname]
        expected_public = [k for k in mod.__dict__ if (modpath, modname, k)
                not in self.known_private and not k.startswith("_") and not
                isinstance(mod.__dict__[k], types.ModuleType)]

        all = set(mod.__all__)
        public = set(expected_public)
        tools.ok_(all.issuperset(public), 'These public names are not in %s.__all__: %s'
                % (modname, ', '.join(public.difference(all))))

    def test__all__is_complete(self):
        '''
        For each module, check that every public name is in __all__
        '''
        # Blacklisted modules and packages
        blacklist = set(['pycompat27.subprocess._subprocess',
            'pycompat24.base64._base64'])

        for path, modname in [m for m in self.walk_modules(self.lib_dir, '')
                if m[1] not in blacklist]:
            # From path, deduce the module name
            from_name = path[path.find('../kitchen') + 3:]
            if from_name.endswith('__init__.py'):
                # Remove __init__.py as well as the filename
                from_name = os.path.dirname(from_name)
            from_name = os.path.dirname(from_name)
            from_name = from_name.translate({ord('/'): '.'})
            yield self.check__all__is_complete, modname.split('.')[-1], from_name