2
# SchoolTool - common information systems platform for school administration
3
# Copyright (c) 2010 Shuttleworth Foundation
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 2 of the License, or
8
# (at your option) any later version.
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
15
# You should have received a copy of the GNU General Public License
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
from zope.testing import cleanup
25
class ModulesSnapshot(object):
28
self.originals = dict(sys.modules)
31
def mock(self, values):
33
mock({'my.module.Foo': FooClass,
34
'my.module.another.GLOBAL_VAL': 1,
37
for full_name in sorted(values):
38
names = full_name.split('.')
40
module_name = '.'.join(names[:-1])
42
self.mock_attr(module_name, attr_name, fake=values[full_name])
44
def mock_attr(self, modulename, name, fake=None):
45
module = self.get_module(modulename)
46
if modulename not in self.faked_attrs:
47
self.faked_attrs[modulename] = {
51
faked = self.faked_attrs[modulename]
52
if hasattr(module, name):
53
if (name not in faked['injected'] and
54
name not in faked['replaced']):
55
faked['replaced'][name] = getattr(module, name)
57
faked['injected'].append(name)
58
setattr(module, name, fake)
60
def mock_module(self, modulename, fake=None):
62
fake = imp.new_module(modulename)
63
names = modulename.split('.')
65
parent_name = '.'.join(names[:-1])
67
self.mock_attr(parent_name, this_name, fake)
68
sys.modules[modulename] = fake
70
def get_module(self, modulename):
72
sys.modules[modulename]
74
self.mock_module(modulename)
75
return sys.modules[modulename]
78
for module_name, faked in self.faked_attrs.items():
80
module = sys.modules[module_name]
83
for name in faked['injected']:
84
del module.__dict__[name]
85
for name, old_value in faked['replaced'].items():
86
setattr(module, name, old_value)
88
for name in list(sys.modules):
89
if name not in self.originals:
92
sys.modules[name] = self.originals[name]
100
_snapshot = ModulesSnapshot()
103
def restoreModules():
105
if _snapshot is not None:
110
cleanup.addCleanUp(restoreModules)
113
def module(module_name):
114
"""A decorator to put method or class to the given module."""
115
snapshot = getSnapshot()
116
if type(module_name) == type(sys):
117
module_name = module_name.__name__
118
def mock_something(something):
119
name = getattr(something, '__name__', None)
120
snapshot.mock_attr(module_name, name, fake=something)
122
return mock_something
125
def fake_global(module_name, name, value):
126
"""Set a global variable to a module."""
127
snapshot = getSnapshot()
128
if type(module_name) == type(sys):
129
module_name = module_name.__name__
130
snapshot.mock_attr(module_name, name, fake=value)
133
def fake_module(module_name, other=None):
134
"""Replace a module with a fake one."""
135
snapshot = getSnapshot()
136
if type(module_name) == type(sys):
137
module_name = module_name.__name__
138
snapshot.mock_module(module_name, fake=other)