Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / python / test / test_dist.py
1 # Copyright (c) Twisted Matrix Laboratories.
2 # See LICENSE for details.
3
4 """
5 Tests for parts of our release automation system.
6 """
7
8
9 import os
10
11 from distutils.core import Distribution
12
13 from twisted.trial.unittest import TestCase
14
15 from twisted.python import dist
16 from twisted.python.dist import get_setup_args, ConditionalExtension
17 from twisted.python.filepath import FilePath
18
19
20 class SetupTest(TestCase):
21     """
22     Tests for L{get_setup_args}.
23     """
24     def test_conditionalExtensions(self):
25         """
26         Passing C{conditionalExtensions} as a list of L{ConditionalExtension}
27         objects to get_setup_args inserts a custom build_ext into the result
28         which knows how to check whether they should be built.
29         """
30         good_ext = ConditionalExtension("whatever", ["whatever.c"],
31                                         condition=lambda b: True)
32         bad_ext = ConditionalExtension("whatever", ["whatever.c"],
33                                         condition=lambda b: False)
34         args = get_setup_args(conditionalExtensions=[good_ext, bad_ext])
35         # ext_modules should be set even though it's not used.  See comment
36         # in get_setup_args
37         self.assertEqual(args["ext_modules"], [good_ext, bad_ext])
38         cmdclass = args["cmdclass"]
39         build_ext = cmdclass["build_ext"]
40         builder = build_ext(Distribution())
41         builder.prepare_extensions()
42         self.assertEqual(builder.extensions, [good_ext])
43
44
45     def test_win32Definition(self):
46         """
47         When building on Windows NT, the WIN32 macro will be defined as 1.
48         """
49         ext = ConditionalExtension("whatever", ["whatever.c"],
50                                    define_macros=[("whatever", 2)])
51         args = get_setup_args(conditionalExtensions=[ext])
52         builder = args["cmdclass"]["build_ext"](Distribution())
53         self.patch(os, "name", "nt")
54         builder.prepare_extensions()
55         self.assertEqual(ext.define_macros, [("whatever", 2), ("WIN32", 1)])
56
57
58
59 class GetVersionTest(TestCase):
60     """
61     Tests for L{dist.getVersion}.
62     """
63
64     def setUp(self):
65         self.dirname = self.mktemp()
66         os.mkdir(self.dirname)
67
68     def test_getVersionCore(self):
69         """
70         Test that getting the version of core reads from the
71         [base]/_version.py file.
72         """
73         f = open(os.path.join(self.dirname, "_version.py"), "w")
74         f.write("""
75 from twisted.python import versions
76 version = versions.Version("twisted", 0, 1, 2)
77 """)
78         f.close()
79         self.assertEqual(dist.getVersion("core", base=self.dirname), "0.1.2")
80
81     def test_getVersionOther(self):
82         """
83         Test that getting the version of a non-core project reads from
84         the [base]/[projname]/_version.py file.
85         """
86         os.mkdir(os.path.join(self.dirname, "blat"))
87         f = open(os.path.join(self.dirname, "blat", "_version.py"), "w")
88         f.write("""
89 from twisted.python import versions
90 version = versions.Version("twisted.blat", 9, 8, 10)
91 """)
92         f.close()
93         self.assertEqual(dist.getVersion("blat", base=self.dirname), "9.8.10")
94
95
96 class GetScriptsTest(TestCase):
97     """
98     Tests for L{dist.getScripts} which returns the scripts which should be
99     included in the distribution of a project.
100     """
101
102     def test_scriptsInSVN(self):
103         """
104         getScripts should return the scripts associated with a project
105         in the context of Twisted SVN.
106         """
107         basedir = self.mktemp()
108         os.mkdir(basedir)
109         os.mkdir(os.path.join(basedir, 'bin'))
110         os.mkdir(os.path.join(basedir, 'bin', 'proj'))
111         f = open(os.path.join(basedir, 'bin', 'proj', 'exy'), 'w')
112         f.write('yay')
113         f.close()
114         scripts = dist.getScripts('proj', basedir=basedir)
115         self.assertEqual(len(scripts), 1)
116         self.assertEqual(os.path.basename(scripts[0]), 'exy')
117
118
119     def test_excludedPreamble(self):
120         """
121         L{dist.getScripts} includes neither C{"_preamble.py"} nor
122         C{"_preamble.pyc"}.
123         """
124         basedir = FilePath(self.mktemp())
125         bin = basedir.child('bin')
126         bin.makedirs()
127         bin.child('_preamble.py').setContent('some preamble code\n')
128         bin.child('_preamble.pyc').setContent('some preamble byte code\n')
129         bin.child('program').setContent('good program code\n')
130         scripts = dist.getScripts("", basedir=basedir.path)
131         self.assertEqual(scripts, [bin.child('program').path])
132
133
134     def test_scriptsInRelease(self):
135         """
136         getScripts should return the scripts associated with a project
137         in the context of a released subproject tarball.
138         """
139         basedir = self.mktemp()
140         os.mkdir(basedir)
141         os.mkdir(os.path.join(basedir, 'bin'))
142         f = open(os.path.join(basedir, 'bin', 'exy'), 'w')
143         f.write('yay')
144         f.close()
145         scripts = dist.getScripts('proj', basedir=basedir)
146         self.assertEqual(len(scripts), 1)
147         self.assertEqual(os.path.basename(scripts[0]), 'exy')
148
149
150     def test_noScriptsInSVN(self):
151         """
152         When calling getScripts for a project which doesn't actually
153         have any scripts, in the context of an SVN checkout, an
154         empty list should be returned.
155         """
156         basedir = self.mktemp()
157         os.mkdir(basedir)
158         os.mkdir(os.path.join(basedir, 'bin'))
159         os.mkdir(os.path.join(basedir, 'bin', 'otherproj'))
160         scripts = dist.getScripts('noscripts', basedir=basedir)
161         self.assertEqual(scripts, [])
162
163
164     def test_getScriptsTopLevel(self):
165         """
166         Passing the empty string to getScripts returns scripts that are (only)
167         in the top level bin directory.
168         """
169         basedir = FilePath(self.mktemp())
170         basedir.createDirectory()
171         bindir = basedir.child("bin")
172         bindir.createDirectory()
173         included = bindir.child("included")
174         included.setContent("yay included")
175         subdir = bindir.child("subdir")
176         subdir.createDirectory()
177         subdir.child("not-included").setContent("not included")
178
179         scripts = dist.getScripts("", basedir=basedir.path)
180         self.assertEqual(scripts, [included.path])
181
182
183     def test_noScriptsInSubproject(self):
184         """
185         When calling getScripts for a project which doesn't actually
186         have any scripts in the context of that project's individual
187         project structure, an empty list should be returned.
188         """
189         basedir = self.mktemp()
190         os.mkdir(basedir)
191         scripts = dist.getScripts('noscripts', basedir=basedir)
192         self.assertEqual(scripts, [])
193
194
195
196 class FakeModule(object):
197     """
198     A fake module, suitable for dependency injection in testing.
199     """
200     def __init__(self, attrs):
201         """
202         Initializes a fake module.
203
204         @param attrs: The attrs that will be accessible on the module.
205         @type attrs: C{dict} of C{str} (Python names) to objects
206         """
207         self._attrs = attrs
208
209     def __getattr__(self, name):
210         """
211         Gets an attribute of this fake module from its attrs.
212
213         @raise AttributeError: When the requested attribute is missing.
214         """
215         try:
216             return self._attrs[name]
217         except KeyError:
218             raise AttributeError()
219
220
221
222 fakeCPythonPlatform = FakeModule({"python_implementation": lambda: "CPython"})
223 fakeOtherPlatform = FakeModule({"python_implementation": lambda: "lvhpy"})
224 emptyPlatform = FakeModule({})
225
226
227
228 class WithPlatformTests(TestCase):
229     """
230     Tests for L{_checkCPython} when used with a (fake) recent C{platform}
231     module.
232     """
233     def test_cpython(self):
234         """
235         L{_checkCPython} returns C{True} when C{platform.python_implementation}
236         says we're running on CPython.
237         """
238         self.assertTrue(dist._checkCPython(platform=fakeCPythonPlatform))
239
240
241     def test_other(self):
242         """
243         L{_checkCPython} returns C{False} when C{platform.python_implementation}
244         says we're not running on CPython.
245         """
246         self.assertFalse(dist._checkCPython(platform=fakeOtherPlatform))
247
248
249
250 fakeCPythonSys = FakeModule({"subversion": ("CPython", None, None)})
251 fakeOtherSys = FakeModule({"subversion": ("lvhpy", None, None)})
252
253
254 def _checkCPythonWithEmptyPlatform(sys):
255     """
256     A partially applied L{_checkCPython} that uses an empty C{platform}
257     module (otherwise the code this test case is supposed to test won't
258     even be called).
259     """
260     return dist._checkCPython(platform=emptyPlatform, sys=sys)
261
262
263
264 class WithSubversionTest(TestCase):
265     """
266     Tests for L{_checkCPython} when used with a (fake) recent (2.5+)
267     C{sys.subversion}. This is effectively only relevant for 2.5, since 2.6 and
268     beyond have L{platform.python_implementation}, which is tried first.
269     """
270     def test_cpython(self):
271         """
272         L{_checkCPython} returns C{True} when C{platform.python_implementation}
273         is unavailable and C{sys.subversion} says we're running on CPython.
274         """
275         isCPython = _checkCPythonWithEmptyPlatform(fakeCPythonSys)
276         self.assertTrue(isCPython)
277
278
279     def test_other(self):
280         """
281         L{_checkCPython} returns C{False} when C{platform.python_implementation}
282         is unavailable and C{sys.subversion} says we're not running on CPython.
283         """
284         isCPython = _checkCPythonWithEmptyPlatform(fakeOtherSys)
285         self.assertFalse(isCPython)
286
287
288
289 oldCPythonSys = FakeModule({"modules": {}})
290 oldPypySys = FakeModule({"modules": {"__pypy__": None}})
291
292
293 class OldPythonsFallbackTest(TestCase):
294     """
295     Tests for L{_checkCPython} when used on a Python 2.4-like platform, when
296     neither C{platform.python_implementation} nor C{sys.subversion} is
297     available.
298     """
299     def test_cpython(self):
300         """
301         L{_checkCPython} returns C{True} when both
302         C{platform.python_implementation} and C{sys.subversion} are unavailable
303         and there is no C{__pypy__} module in C{sys.modules}.
304         """
305         isCPython = _checkCPythonWithEmptyPlatform(oldCPythonSys)
306         self.assertTrue(isCPython)
307
308
309     def test_pypy(self):
310         """
311         L{_checkCPython} returns C{False} when both
312         C{platform.python_implementation} and C{sys.subversion} are unavailable
313         and there is a C{__pypy__} module in C{sys.modules}.
314         """
315         isCPython = _checkCPythonWithEmptyPlatform(oldPypySys)
316         self.assertFalse(isCPython)