~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_lazy_import.py

  • Committer: John Arbash Meinel
  • Date: 2006-09-10 20:39:26 UTC
  • mto: This revision was merged to the branch mainline in revision 2004.
  • Revision ID: john@arbash-meinel.com-20060910203926-ae731f6bb165d6fa
Adding a ScopeReplacer class, which can replace itself on demand

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2006 by Canonical Ltd
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
 
 
17
"""Test the lazy_import functionality."""
 
18
 
 
19
 
 
20
from bzrlib import (
 
21
    lazy_import,
 
22
    )
 
23
from bzrlib.tests import TestCase, TestCaseInTempDir
 
24
 
 
25
 
 
26
class InstrumentedReplacer(lazy_import.ScopeReplacer):
 
27
    """Track what actions are done"""
 
28
 
 
29
    @staticmethod
 
30
    def use_actions(actions):
 
31
        InstrumentedReplacer.actions = actions
 
32
 
 
33
    def _replace(self):
 
34
        InstrumentedReplacer.actions.append('_replace')
 
35
        return lazy_import.ScopeReplacer._replace(self)
 
36
 
 
37
    def __getattribute__(self, attr):
 
38
        InstrumentedReplacer.actions.append(('__getattribute__', attr))
 
39
        return lazy_import.ScopeReplacer.__getattribute__(self, attr)
 
40
 
 
41
    def __call__(self, *args, **kwargs):
 
42
        InstrumentedReplacer.actions.append(('__call__', args, kwargs))
 
43
        return lazy_import.ScopeReplacer.__call__(self, *args, **kwargs)
 
44
 
 
45
 
 
46
class TestClass(object):
 
47
    """Just a simple test class instrumented for the test cases"""
 
48
 
 
49
    actions = []
 
50
 
 
51
    class_member = 'class_member'
 
52
 
 
53
    @staticmethod
 
54
    def use_actions(actions):
 
55
        TestClass.actions = actions
 
56
 
 
57
    def __init__(self):
 
58
        TestClass.actions.append('init')
 
59
 
 
60
    def foo(self, x):
 
61
        TestClass.actions.append(('foo', x))
 
62
        return 'foo'
 
63
 
 
64
 
 
65
class TestScopeReplacer(TestCase):
 
66
    """Test the ability of the replacer to put itself into the correct scope.
 
67
 
 
68
    In these tests we use the global scope, because we cannot replace
 
69
    variables in the local scope. This means that we need to be careful
 
70
    and not have the replacing objects use the same name, or we would
 
71
    get collisions.
 
72
    """
 
73
 
 
74
    def test_object(self):
 
75
 
 
76
        actions = []
 
77
        InstrumentedReplacer.use_actions(actions)
 
78
        TestClass.use_actions(actions)
 
79
 
 
80
        def factory(replacer, scope, name):
 
81
            actions.append('factory')
 
82
            return TestClass()
 
83
 
 
84
        try:
 
85
            test_obj1
 
86
        except NameError:
 
87
            # test_obj1 shouldn't exist yet
 
88
            pass
 
89
        else:
 
90
            self.fail('test_obj1 was not supposed to exist yet')
 
91
 
 
92
        InstrumentedReplacer(scope=globals(), name='test_obj1',
 
93
                             factory=factory)
 
94
 
 
95
        # We can't use isinstance() because that uses test_obj1.__class__
 
96
        # and that goes through __getattribute__ which would activate
 
97
        # the replacement
 
98
        self.assertEqual(InstrumentedReplacer,
 
99
                         object.__getattribute__(test_obj1, '__class__'))
 
100
        self.assertEqual('foo', test_obj1.foo(1))
 
101
        self.assertIsInstance(test_obj1, TestClass)
 
102
        self.assertEqual('foo', test_obj1.foo(2))
 
103
        self.assertEqual([('__getattribute__', 'foo'),
 
104
                          '_replace',
 
105
                          'factory',
 
106
                          'init',
 
107
                          ('foo', 1),
 
108
                          ('foo', 2),
 
109
                         ], actions)
 
110
 
 
111
    def test_class(self):
 
112
        actions = []
 
113
        InstrumentedReplacer.use_actions(actions)
 
114
        TestClass.use_actions(actions)
 
115
 
 
116
        def factory(replacer, scope, name):
 
117
            actions.append('factory')
 
118
            return TestClass
 
119
 
 
120
        try:
 
121
            test_class1
 
122
        except NameError:
 
123
            # test_class2 shouldn't exist yet
 
124
            pass
 
125
        else:
 
126
            self.fail('test_class1 was not supposed to exist yet')
 
127
 
 
128
        InstrumentedReplacer(scope=globals(), name='test_class1',
 
129
                             factory=factory)
 
130
 
 
131
        self.assertEqual('class_member', test_class1.class_member)
 
132
        self.assertEqual(test_class1, TestClass)
 
133
        self.assertEqual([('__getattribute__', 'class_member'),
 
134
                          '_replace',
 
135
                          'factory',
 
136
                         ], actions)
 
137
 
 
138
    def test_call_class(self):
 
139
        actions = []
 
140
        InstrumentedReplacer.use_actions(actions)
 
141
        TestClass.use_actions(actions)
 
142
 
 
143
        def factory(replacer, scope, name):
 
144
            actions.append('factory')
 
145
            return TestClass
 
146
 
 
147
        try:
 
148
            test_class2
 
149
        except NameError:
 
150
            # test_class2 shouldn't exist yet
 
151
            pass
 
152
        else:
 
153
            self.fail('test_class2 was not supposed to exist yet')
 
154
 
 
155
        InstrumentedReplacer(scope=globals(), name='test_class2',
 
156
                             factory=factory)
 
157
 
 
158
        self.failIf(test_class2 is TestClass)
 
159
        obj = test_class2()
 
160
        self.assertIs(test_class2, TestClass)
 
161
        self.assertIsInstance(obj, TestClass)
 
162
        self.assertEqual('class_member', obj.class_member)
 
163
        self.assertEqual([('__call__', (), {}),
 
164
                          '_replace',
 
165
                          'factory',
 
166
                          'init',
 
167
                         ], actions)
 
168
 
 
169
    def test_call_func(self):
 
170
        actions = []
 
171
        InstrumentedReplacer.use_actions(actions)
 
172
 
 
173
        def func(a, b, c=None):
 
174
            actions.append('func')
 
175
            return (a, b, c)
 
176
 
 
177
        def factory(replacer, scope, name):
 
178
            actions.append('factory')
 
179
            return func
 
180
 
 
181
        try:
 
182
            test_func1
 
183
        except NameError:
 
184
            # test_func1 shouldn't exist yet
 
185
            pass
 
186
        else:
 
187
            self.fail('test_func1 was not supposed to exist yet')
 
188
        InstrumentedReplacer(scope=globals(), name='test_func1',
 
189
                             factory=factory)
 
190
 
 
191
        self.failIf(test_func1 is func)
 
192
        val = test_func1(1, 2, c='3')
 
193
        self.assertIs(test_func1, func)
 
194
 
 
195
        self.assertEqual((1,2,'3'), val)
 
196
        self.assertEqual([('__call__', (1,2), {'c':'3'}),
 
197
                          '_replace',
 
198
                          'factory',
 
199
                          'func',
 
200
                         ], actions)
 
201
 
 
202
class TestImportReplacer(TestCaseInTempDir):
 
203
    """Test the ability to have a lazily imported module or object"""
 
204