~ubuntu-branches/ubuntu/oneiric/python-distutils-extra/oneiric

« back to all changes in this revision

Viewing changes to .pc/debian-changes-2.22-2/test/auto.py

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt, Martin Pitt, Didier Roche
  • Date: 2010-11-03 22:37:27 UTC
  • Revision ID: james.westby@ubuntu.com-20101103223727-myfre6qawqa7ok9v
Tags: 2.22-3
[ Martin Pitt ]
* auto.py: Skip setup.py when calculating automatic requires, since
  modules from that script are just build dependencies. Thanks Michael
  Terry! (LP: #643655)
* python-mkdebian: Update python-mkdebian's generated copyright fields with
  latest names/values from http://dep.debian.net/deps/dep5/. Thanks Michael
  Terry!
* Rebuild against Python 2.7 in Ubuntu. (LP: #670188)

[ Didier Roche ]
* Return an error when can't update changelog (LP: #656950)
* Add --force-copyright to force copyright file to be recreated
  (LP: #656943)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/python
2
 
 
3
 
# test DistUtilsExtra.auto
4
 
 
5
 
import sys, unittest, shutil, tempfile, os, os.path, subprocess, re
6
 
 
7
 
class T(unittest.TestCase):
8
 
    def setUp(self):
9
 
        self.src = tempfile.mkdtemp()
10
 
 
11
 
        self._mksrc('setup.py', '''
12
 
from DistUtilsExtra.auto import setup
13
 
 
14
 
setup(
15
 
    name='foo',
16
 
    version='0.1',
17
 
    description='Test suite package',
18
 
    url='https://foo.example.com',
19
 
    license='GPL v2 or later',
20
 
    author='Martin Pitt',
21
 
    author_email='martin.pitt@example.com',
22
 
)
23
 
''')
24
 
        self.snapshot = None
25
 
        self.install_tree = None
26
 
 
27
 
    def tearDown(self):
28
 
        try:
29
 
            # check that setup.py clean removes everything
30
 
            (o, e, s) = self.setup_py(['clean', '-a'])
31
 
            self.assertEqual(s, 0)
32
 
            cruft = self.diff_snapshot()
33
 
            self.assertEqual(cruft, '', 'no cruft after cleaning:\n' + cruft)
34
 
        finally:
35
 
            shutil.rmtree(self.src)
36
 
            if self.snapshot:
37
 
                shutil.rmtree(self.snapshot)
38
 
            if self.install_tree:
39
 
                shutil.rmtree(self.install_tree)
40
 
            self.src = None
41
 
            self.snapshot = None
42
 
            self.install_tree = None
43
 
 
44
 
    #
45
 
    # actual tests come here
46
 
    #
47
 
 
48
 
    def test_empty(self):
49
 
        '''empty source tree (just setup.py)'''
50
 
 
51
 
        (o, e, s) = self.do_install()
52
 
        self.assertEqual(e, '')
53
 
        self.assertEqual(s, 0)
54
 
        self.failIf('following files are not recognized' in o)
55
 
 
56
 
        f = self.installed_files()
57
 
        # just installs the .egg_info
58
 
        self.assertEqual(len(f), 1)
59
 
        self.assert_(f[0].endswith('.egg-info'))
60
 
 
61
 
    def test_vcs(self):
62
 
        '''Ignores revision control files'''
63
 
 
64
 
        self._mksrc('.shelf/1')
65
 
        self._mksrc('.bzr/revs')
66
 
        self._mksrc('.git/config')
67
 
        self._mksrc('.svn/revs')
68
 
 
69
 
        (o, e, s) = self.do_install()
70
 
        self.assertEqual(e, '')
71
 
        self.assertEqual(s, 0)
72
 
        self.failIf('following files are not recognized' in o)
73
 
 
74
 
        f = self.installed_files()
75
 
        # just installs the .egg_info
76
 
        self.assertEqual(len(f), 1)
77
 
        self.assert_(f[0].endswith('.egg-info'))
78
 
 
79
 
    def test_modules(self):
80
 
        '''Python modules'''
81
 
 
82
 
        self._mksrc('yesme.py')
83
 
        self._mksrc('stuff/notme.py')
84
 
 
85
 
        (o, e, s) = self.do_install()
86
 
        self.assertEqual(e, '')
87
 
        self.assertEqual(s, 0)
88
 
        self.assert_('following files are not recognized' in o)
89
 
        self.assert_('\n  stuff/notme.py\n' in o)
90
 
 
91
 
        f = '\n'.join(self.installed_files())
92
 
        self.assert_('-packages/yesme.py' in f)
93
 
        self.failIf('notme' in f)
94
 
 
95
 
    def test_packages(self):
96
 
        '''Python packages'''
97
 
 
98
 
        self._mksrc('foopkg/__init__.py', '')
99
 
        self._mksrc('foopkg/bar.py')
100
 
        self._mksrc('foopkg/baz.py')
101
 
        self._mksrc('noinit/notme.py')
102
 
 
103
 
        (o, e, s) = self.do_install()
104
 
        self.assertEqual(e, '')
105
 
        self.assertEqual(s, 0)
106
 
        self.assert_('following files are not recognized' in o)
107
 
        self.assert_('\n  noinit/notme.py\n' in o)
108
 
 
109
 
        f = '\n'.join(self.installed_files())
110
 
        self.assert_('foopkg/__init__.py' in f)
111
 
        self.assert_('foopkg/bar.py' in f)
112
 
        self.failIf('noinit' in f)
113
 
 
114
 
    def test_dbus(self):
115
 
        '''D-BUS configuration and service files'''
116
 
 
117
 
        # D-BUS ACL configuration file
118
 
        self._mksrc('daemon/com.example.foo.conf', '''<!DOCTYPE busconfig PUBLIC
119
 
 "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
120
 
 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
121
 
<busconfig>
122
 
</busconfig>''')
123
 
 
124
 
        # non-D-BUS configuration file
125
 
        self._mksrc('daemon/defaults.conf', 'start = True\nlog = syslog')
126
 
 
127
 
        # D-BUS system service
128
 
        self._mksrc('daemon/com.example.foo.service', '''[D-BUS Service]
129
 
Name=com.example.Foo
130
 
Exec=/usr/lib/foo/foo_daemon
131
 
User=root''')
132
 
 
133
 
        # D-BUS session service
134
 
        self._mksrc('gui/com.example.foo.gui.service', '''[D-BUS Service]
135
 
Name=com.example.Foo.GUI
136
 
Exec=/usr/bin/foo-gtk
137
 
''')
138
 
 
139
 
        # non-D-BUS .service file
140
 
        self._mksrc('stuff/super.service', 'I am a file')
141
 
 
142
 
        (o, e, s) = self.do_install()
143
 
        self.assertEqual(e, '')
144
 
        self.assertEqual(s, 0)
145
 
        self.assert_('following files are not recognized' in o)
146
 
        self.assert_('\n  stuff/super.service\n' in o)
147
 
 
148
 
        f = self.installed_files()
149
 
        self.assertEqual(len(f), 4) # 3 D-BUS files plus .egg-info
150
 
        self.assert_('/etc/dbus-1/system.d/com.example.foo.conf' in f)
151
 
        self.assert_('/usr/share/dbus-1/system-services/com.example.foo.service' in f)
152
 
        self.assert_('/usr/share/dbus-1/services/com.example.foo.gui.service' in f)
153
 
        self.failIf('super.service' in '\n'.join(f))
154
 
 
155
 
    def test_apport_hook(self):
156
 
        '''Apport hooks'''
157
 
 
158
 
        self._mksrc('apport/foo.py', '''import os, apport
159
 
def add_info(report):
160
 
    pass
161
 
''')
162
 
 
163
 
        self._mksrc('apport/source_foo.py', '''import os, apport
164
 
def add_info(report):
165
 
    pass
166
 
''')
167
 
 
168
 
        (o, e, s) = self.do_install()
169
 
        self.failIf('following files are not recognized' in o, o)
170
 
        
171
 
        f = self.installed_files()
172
 
        self.assertEqual(len(f), 3, f) # 2 hook files plus .egg-info
173
 
        self.assert_('/usr/share/apport/package-hooks/foo.py' in f, f)
174
 
        self.assert_('/usr/share/apport/package-hooks/source_foo.py' in f, f)
175
 
        
176
 
    def test_po(self):
177
 
        '''gettext *.po files'''
178
 
 
179
 
        self._mkpo()
180
 
 
181
 
        (o, e, s) = self.do_install()
182
 
        self.assertEqual(e, '')
183
 
        self.assertEqual(s, 0)
184
 
        self.failIf('following files are not recognized' in o)
185
 
        f = self.installed_files()
186
 
        self.assert_('/usr/share/locale/de/LC_MESSAGES/foo.mo' in f)
187
 
        self.assert_('/usr/share/locale/fr/LC_MESSAGES/foo.mo' in f)
188
 
        self.failIf('junk' in '\n'.join(f))
189
 
 
190
 
        msgunfmt = subprocess.Popen(['msgunfmt',
191
 
            os.path.join(self.install_tree,
192
 
            'usr/share/locale/de/LC_MESSAGES/foo.mo')],
193
 
            stdout=subprocess.PIPE)
194
 
        out = msgunfmt.communicate()[0].decode()
195
 
        self.assertEqual(out, open(os.path.join(self.src, 'po/de.po')).read())
196
 
 
197
 
    def test_policykit(self):
198
 
        '''*.policy.in PolicyKit files'''
199
 
 
200
 
        self._mksrc('daemon/com.example.foo.policy.in', '''<?xml version="1.0" encoding="UTF-8"?>
201
 
<!DOCTYPE policyconfig PUBLIC
202
 
 "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
203
 
 "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
204
 
<policyconfig>
205
 
  <vendor>Foo project</vendor>
206
 
  <vendor_url>https://foo.example.com</vendor_url>
207
 
 
208
 
  <action id="com.example.foo.greet">
209
 
    <_description>Good morning</_description>
210
 
    <_message>Hello</_message>
211
 
    <defaults>
212
 
      <allow_active>yes</allow_active>
213
 
    </defaults>
214
 
  </action>
215
 
</policyconfig>''')
216
 
 
217
 
        self._mkpo()
218
 
        (o, e, s) = self.do_install()
219
 
        self.assertEqual(e, '')
220
 
        self.assertEqual(s, 0)
221
 
        self.failIf('following files are not recognized' in o)
222
 
 
223
 
        f = self.installed_files()
224
 
        self.assert_('/usr/share/PolicyKit/policy/com.example.foo.policy' in f)
225
 
        p = open(os.path.join(self.install_tree,
226
 
            'usr/share/PolicyKit/policy/com.example.foo.policy')).read()
227
 
        self.assert_('<description>Good morning</description>' in p)
228
 
        self.assert_('<description xml:lang="de">Guten Morgen</description>' in p)
229
 
        self.assert_('<message>Hello</message>' in p)
230
 
        self.assert_('<message xml:lang="de">Hallo</message>' in p)
231
 
 
232
 
        # polkit-1
233
 
        self._mksrc('foo.py', '''polkit = dbus.Interface(dbus.SystemBus().get_object(
234
 
    'org.freedesktop.PolicyKit1',
235
 
    '/org/freedesktop/PolicyKit1/Authority', False),
236
 
    'org.freedesktop.PolicyKit1.Authority')
237
 
''')
238
 
        self.setup_py(['clean', '-a'])
239
 
        self.snapshot = None
240
 
        (o, e, s) = self.do_install()
241
 
        self.assertEqual(e, '')
242
 
        self.assertEqual(s, 0)
243
 
        self.failIf('following files are not recognized' in o)
244
 
 
245
 
        f = self.installed_files()
246
 
        self.failIf('/usr/share/PolicyKit/policy/com.example.foo.policy' in f)
247
 
        self.assert_('/usr/share/polkit-1/actions/com.example.foo.policy' in f)
248
 
 
249
 
    def test_desktop(self):
250
 
        '''*.desktop.in files'''
251
 
 
252
 
        self._mksrc('gui/foogtk.desktop.in', '''[Desktop Entry]
253
 
_Name=Hello
254
 
_Comment=Good morning
255
 
Exec=/bin/foo''')
256
 
        self._mksrc('gui/autostart/fooapplet.desktop.in', '''[Desktop Entry]
257
 
_Name=Hello
258
 
_Comment=Good morning
259
 
Exec=/usr/bin/fooapplet''')
260
 
        self._mkpo()
261
 
        self._mksrc('data/foosettings.desktop.in', '''[Desktop Entry]
262
 
_Name=Hello
263
 
_Comment=Good morning
264
 
Exec=/bin/foosettings''')
265
 
 
266
 
        (o, e, s) = self.do_install()
267
 
        self.assertEqual(e, '')
268
 
        self.assertEqual(s, 0)
269
 
        self.failIf('following files are not recognized' in o)
270
 
 
271
 
        f = self.installed_files()
272
 
        self.assert_('/usr/share/autostart/fooapplet.desktop' in f)
273
 
        self.assert_('/usr/share/applications/foogtk.desktop' in f)
274
 
        self.assert_('/usr/share/applications/foosettings.desktop' in f)
275
 
        # data/*.desktop.in shouldn't go to data dir
276
 
        self.failIf('/usr/share/foo/' in f)
277
 
 
278
 
        p = open(os.path.join(self.install_tree,
279
 
            'usr/share/autostart/fooapplet.desktop')).read()
280
 
        self.assert_('\nName=Hello\n' in p)
281
 
        self.assert_('\nName[de]=Hallo\n' in p)
282
 
        self.assert_('\nComment[fr]=Bonjour\n' in p)
283
 
 
284
 
    def test_icons(self):
285
 
        '''data/icons/'''
286
 
 
287
 
        self._mksrc('data/icons/scalable/actions/press.png')
288
 
        self._mksrc('data/icons/48x48/apps/foo.png')
289
 
        action_icon_path = os.path.join(self.src, 'data', 'icons', 'scalable',
290
 
                'actions')
291
 
        os.symlink(os.path.join(action_icon_path, 'press.png'),
292
 
                os.path.join(action_icon_path, 'crunch.png'))
293
 
 
294
 
        (o, e, s) = self.do_install()
295
 
        self.assertEqual(e, '')
296
 
        self.assertEqual(s, 0)
297
 
        self.failIf('following files are not recognized' in o)
298
 
 
299
 
        f = self.installed_files()
300
 
        self.assert_('/usr/share/icons/hicolor/scalable/actions/press.png' in f)
301
 
        self.assert_('/usr/share/icons/hicolor/scalable/actions/crunch.png' in f)
302
 
        self.assert_('/usr/share/icons/hicolor/48x48/apps/foo.png' in f)
303
 
        self.assert_(os.path.islink(os.path.join(self.install_tree, 
304
 
           'usr/share/icons/hicolor/scalable/actions/crunch.png')))
305
 
 
306
 
    def test_data(self):
307
 
        '''Auxiliary files in data/'''
308
 
 
309
 
        # have some explicitly covered files, to check that they don't get
310
 
        # installed into prefix/share/foo/ again
311
 
        self._mksrc('setup.py', '''
312
 
from DistUtilsExtra.auto import setup
313
 
from glob import glob
314
 
 
315
 
setup(
316
 
    name='foo',
317
 
    version='0.1',
318
 
    description='Test suite package',
319
 
    url='https://foo.example.com',
320
 
    license='GPL v2 or later',
321
 
    author='Martin Pitt',
322
 
    author_email='martin.pitt@example.com',
323
 
 
324
 
    data_files = [
325
 
      ('/lib/udev/rules.d', ['data/40-foo.rules']),
326
 
      ('/etc/foo', glob('data/*.conf')),
327
 
    ]
328
 
)
329
 
''')
330
 
 
331
 
        self._mksrc('data/stuff')
332
 
        self._mksrc('data/handlers/red.py', 'import sys\nprint ("RED")')
333
 
        self._mksrc('data/handlers/blue.py', 'import sys\nprint ("BLUE")')
334
 
        self._mksrc('data/40-foo.rules')
335
 
        self._mksrc('data/blob1.conf')
336
 
        self._mksrc('data/blob2.conf')
337
 
        os.symlink('stuff', os.path.join(self.src, 'data', 'stufflink'))
338
 
 
339
 
        (o, e, s) = self.do_install()
340
 
        self.assertEqual(e, '')
341
 
        self.assertEqual(s, 0)
342
 
        self.failIf('following files are not recognized' in o)
343
 
 
344
 
        f = self.installed_files()
345
 
        self.assert_('/usr/share/foo/stuff' in f)
346
 
        self.assert_('/usr/share/foo/stufflink' in f)
347
 
        self.assert_(os.path.islink(os.path.join(self.install_tree, 'usr',
348
 
            'share', 'foo', 'stufflink')))
349
 
        self.assert_('/usr/share/foo/handlers/red.py' in f)
350
 
        self.assert_('/usr/share/foo/handlers/blue.py' in f)
351
 
        self.assert_('/lib/udev/rules.d/40-foo.rules' in f)
352
 
        self.assert_('/etc/foo/blob1.conf' in f)
353
 
        self.assert_('/etc/foo/blob2.conf' in f)
354
 
        self.failIf('/usr/share/foo/blob1.conf' in f)
355
 
        self.failIf('/usr/share/foo/40-foo.rules' in f)
356
 
 
357
 
    def test_scripts(self):
358
 
        '''scripts'''
359
 
 
360
 
        # these should get autoinstalled
361
 
        self._mksrc('bin/yell', '#!/bin/sh', True)
362
 
        self._mksrc('bin/shout', '#!/bin/sh', True)
363
 
        self._mksrc('bin/foo', '#!/bin/sh', True)
364
 
        os.symlink('shout', os.path.join(self.src, 'bin', 'shoutlink'))
365
 
 
366
 
        # these shouldn't
367
 
        self._mksrc('daemon/food', '#!/bin/sh', True) # not in bin/
368
 
        self._mksrc('foob', '#!/bin/sh', True) # not named like project
369
 
        self._mksrc('bin/whisper', '#!/bin/sh') # not executable
370
 
 
371
 
        (o, e, s) = self.do_install()
372
 
        self.assertEqual(e, '')
373
 
        self.assertEqual(s, 0)
374
 
        self.assert_('following files are not recognized' in o)
375
 
        self.assert_('\n  foob' in o)
376
 
        self.assert_('\n  bin/whisper' in o)
377
 
        self.assert_('\n  daemon/food' in o)
378
 
 
379
 
        f = self.installed_files()
380
 
        self.assert_('/usr/bin/yell' in f)
381
 
        self.assert_('/usr/bin/shout' in f)
382
 
        self.assert_('/usr/bin/shoutlink' in f)
383
 
        self.assert_(os.path.islink(os.path.join(self.install_tree, 'usr',
384
 
            'bin', 'shoutlink')))
385
 
        self.assert_('/usr/bin/foo' in f)
386
 
        ftext = '\n'.join(f)
387
 
        self.failIf('food' in ftext)
388
 
        self.failIf('foob' in ftext)
389
 
        self.failIf('whisper' in ftext)
390
 
 
391
 
        # verify that they are executable
392
 
        binpath = os.path.join(self.install_tree, 'usr', 'bin')
393
 
        self.assert_(os.access(os.path.join(binpath, 'yell'), os.X_OK))
394
 
        self.assert_(os.access(os.path.join(binpath, 'shout'), os.X_OK))
395
 
        self.assert_(os.access(os.path.join(binpath, 'foo'), os.X_OK))
396
 
 
397
 
    def test_pot_manual(self):
398
 
        '''PO template creation with manual POTFILES.in'''
399
 
 
400
 
        self._mk_i18n_source()
401
 
        self._mksrc('po/foo.pot', '')
402
 
        # only do a subset here
403
 
        self._mksrc('po/POTFILES.in', '''
404
 
gtk/main.py
405
 
gui/foo.desktop.in
406
 
[type: gettext/glade]gtk/test.ui''')
407
 
 
408
 
        (o, e, s) = self.setup_py(['build'])
409
 
        self.assertEqual(e, '')
410
 
        self.assertEqual(s, 0)
411
 
        # POT file should not be shown as not recognized
412
 
        self.failIf('\n  po/foo.pot\n' in o)
413
 
 
414
 
        pot_path = os.path.join(self.src, 'po', 'foo.pot')
415
 
        self.assert_(os.path.exists(pot_path))
416
 
        pot = open(pot_path).read()
417
 
 
418
 
        self.failIf('msgid "no"' in pot)
419
 
        self.assert_('msgid "yes1"' in pot)
420
 
        self.assert_('msgid "yes2 %s"' in pot)
421
 
        self.failIf('msgid "yes5"' in pot) # we didn't add helpers.py
422
 
        self.assert_('msgid "yes7"' in pot) # we did include the desktop file
423
 
        self.failIf('msgid "yes5"' in pot) # we didn't add helpers.py
424
 
        self.assert_('msgid "yes11"' in pot) # we added one GTKBuilder file
425
 
        self.failIf('msgid "yes12"' in pot) # ... but not the other
426
 
 
427
 
    def test_pot_auto(self):
428
 
        '''PO template creation with automatic POTFILES.in'''
429
 
 
430
 
        self._mk_i18n_source()
431
 
 
432
 
        (o, e, s) = self.setup_py(['build'])
433
 
        self.assertEqual(e, '')
434
 
        self.assertEqual(s, 0)
435
 
        # POT file should not be shown as not recognized
436
 
        self.failIf('\n  po/foo.pot\n' in o)
437
 
 
438
 
        pot_path = os.path.join(self.src, 'po', 'foo.pot')
439
 
        self.assert_(os.path.exists(pot_path))
440
 
        pot = open(pot_path).read()
441
 
 
442
 
        self.failIf('msgid "no"' in pot)
443
 
        for i in range(2, 15):
444
 
            self.assert_('msgid "yes%i' % i in pot or 
445
 
                   'msgid ""\n"yes%i' % i in pot,
446
 
                   'yes%i' % i)
447
 
        # above loop would match yes11 to yes1 as well, so test it explicitly
448
 
        self.assert_('msgid "yes1"' in pot)
449
 
 
450
 
    def test_pot_auto_explicit(self):
451
 
        '''PO template creation with automatic POTFILES.in and explicit scripts'''
452
 
 
453
 
        self._mk_i18n_source()
454
 
 
455
 
        # add some additional binaries here which aren't caught by default
456
 
        self._mksrc('cli/client-cli', "#!/usr/bin/python\nprint (_('yes15'))", True)
457
 
        self._mksrc('gtk/client-gtk', '#!/usr/bin/python\nprint (_("yes16"))', True)
458
 
        # this is the most tricky case: intltool doesn't consider them Python
459
 
        # files by default and thus just looks for _(""):
460
 
        self._mksrc('kde/client-kde', "#!/usr/bin/python\nprint (_('yes17'))", True)
461
 
        self._mksrc('po/POTFILES.in.in', 'gtk/client-gtk\nkde/client-kde')
462
 
        self._mksrc('setup.py', '''
463
 
from DistUtilsExtra.auto import setup
464
 
 
465
 
setup(
466
 
    name='foo',
467
 
    version='0.1',
468
 
    data_files=[('share/foo', ['gtk/client-gtk', 'kde/client-kde'])],
469
 
    scripts=['cli/client-cli'],
470
 
)
471
 
''')
472
 
 
473
 
        (o, e, s) = self.setup_py(['build'])
474
 
        self.assertEqual(e, '')
475
 
        self.assertEqual(s, 0)
476
 
        # POT file should not be shown as not recognized
477
 
        self.failIf('\n  po/foo.pot\n' in o)
478
 
 
479
 
        pot_path = os.path.join(self.src, 'po', 'foo.pot')
480
 
        self.assert_(os.path.exists(pot_path))
481
 
        pot = open(pot_path).read()
482
 
 
483
 
        self.failIf('msgid "no"' in pot)
484
 
        for i in range(2, 18):
485
 
            self.assert_('msgid "yes%i' % i in pot or 
486
 
                   'msgid ""\n"yes%i' % i in pot,
487
 
                   'yes%i' % i)
488
 
        # above loop would match yes11 to yes1 as well, so test it explicitly
489
 
        self.assert_('msgid "yes1"' in pot)
490
 
 
491
 
    def test_standard_files(self):
492
 
        '''Standard files (MANIFEST.in, COPYING, etc.)'''
493
 
 
494
 
        self._mksrc('AUTHORS')
495
 
        self._mksrc('COPYING')
496
 
        self._mksrc('LICENSE')
497
 
        self._mksrc('COPYING.LIB')
498
 
        self._mksrc('README.txt')
499
 
        self._mksrc('MANIFEST.in')
500
 
        self._mksrc('MANIFEST')
501
 
        self._mksrc('NEWS')
502
 
        self._mksrc('TODO')
503
 
 
504
 
        (o, e, s) = self.do_install()
505
 
        self.assertEqual(e, '')
506
 
        self.assertEqual(s, 0)
507
 
        self.failIf('following files are not recognized' in o, o)
508
 
 
509
 
        f = self.installed_files()
510
 
        self.assert_('/usr/share/doc/foo/README.txt' in f)
511
 
        self.assert_('/usr/share/doc/foo/NEWS' in f)
512
 
        ftext = '\n'.join(f)
513
 
        self.failIf('MANIFEST' in ftext)
514
 
        self.failIf('COPYING' in ftext)
515
 
        self.failIf('COPYING' in ftext)
516
 
        self.failIf('AUTHORS' in ftext)
517
 
        self.failIf('TODO' in ftext)
518
 
 
519
 
        # sub-dir READMEs shouldn't be installed by default
520
 
        self.snapshot = None
521
 
        self._mksrc('extra/README')
522
 
        (o, e, s) = self.do_install()
523
 
        self.assertEqual(e, '')
524
 
        self.assertEqual(s, 0)
525
 
        self.assert_('following files are not recognized' in o)
526
 
        self.assert_('\n  extra/README\n' in o)
527
 
 
528
 
    def test_sdist(self):
529
 
        '''default MANIFEST'''
530
 
 
531
 
        good = ['AUTHORS', 'README.txt', 'COPYING', 'helpers.py',
532
 
                'foo/__init__.py', 'foo/bar.py', 'tests/all.py',
533
 
                'gui/x.desktop.in', 'backend/foo.policy.in',
534
 
                'daemon/backend.conf', 'x/y', 'po/de.po', 'po/foo.pot',
535
 
                '.quickly', 'data/icons/16x16/apps/foo.png', 'bin/foo',
536
 
                'backend/food', 'backend/com.example.foo.service',
537
 
                'gtk/main.glade', 'dist/extra.tar.gz']
538
 
        bad = ['po/de.mo', '.helpers.py.swp', '.bzr/index', '.svn/index',
539
 
               '.git/index', 'bin/foo~', 'backend/foo.pyc', 
540
 
               'dist/foo-0.1.tar.gz', '.shelf/1', '.bzr/revs', '.git/config']
541
 
 
542
 
        for f in good + bad:
543
 
            self._mksrc(f)
544
 
 
545
 
        (o, e, s) = self.setup_py(['sdist', '-o'])
546
 
        self.assert_("'MANIFEST.in' does not exist" in e)
547
 
        self.assertEqual(s, 0)
548
 
 
549
 
        manifest = open(os.path.join(self.src, 'MANIFEST')).read().splitlines()
550
 
 
551
 
        for f in good:
552
 
            self.assert_(f in manifest, '%s in manifest' % f)
553
 
        for f in bad:
554
 
            self.failIf(f in manifest, '%s not in manifest' % f)
555
 
        os.unlink(os.path.join(self.src, 'MANIFEST'))
556
 
 
557
 
    def test_gtkbuilder(self):
558
 
        '''GtkBuilder *.ui'''
559
 
 
560
 
        self._mksrc('gtk/test.ui', '''<?xml version="1.0"?>
561
 
<interface>
562
 
  <requires lib="gtk+" version="2.16"/>
563
 
  <object class="GtkWindow" id="window1">
564
 
    <property name="title" translatable="yes">yes11</property>
565
 
    <child><placeholder/></child>
566
 
  </object>
567
 
</interface>''')
568
 
 
569
 
        self._mksrc('gtk/settings.ui', '''<?xml version="1.0"?>
570
 
<interface domain="foobar">
571
 
  <requires lib="gtk+" version="2.16"/>
572
 
  <object class="GtkWindow" id="window2">
573
 
    <property name="title" translatable="yes">yes12</property>
574
 
    <child><placeholder/></child>
575
 
  </object>
576
 
</interface>''')
577
 
 
578
 
        self._mksrc('someweird.ui')
579
 
 
580
 
        (o, e, s) = self.do_install()
581
 
        self.assertEqual(e, '')
582
 
        self.assertEqual(s, 0)
583
 
        self.assert_('following files are not recognized' in o)
584
 
        self.assert_('\n  someweird.ui\n' in o)
585
 
 
586
 
        f = self.installed_files()
587
 
        self.assert_('/usr/share/foo/test.ui' in f)
588
 
        self.assert_('/usr/share/foo/settings.ui' in f)
589
 
        ftext = '\n'.join(f)
590
 
        self.failIf('someweird' in ftext)
591
 
 
592
 
    def test_manpages(self):
593
 
        '''manpages'''
594
 
 
595
 
        self._mksrc('man/foo.1', '.TH foo 1 "Jan 01, 1900" "Joe Developer"')
596
 
        self._mksrc('daemon/food.8', '.TH food 8 "Jan 01, 1900" "Joe Developer"')
597
 
        self._mksrc('cruft/food.1', '')
598
 
        self._mksrc('daemon/notme.s', '.TH food 8 "Jan 01, 1900" "Joe Developer"')
599
 
 
600
 
        (o, e, s) = self.do_install()
601
 
        self.assertEqual(e, '')
602
 
        self.assertEqual(s, 0)
603
 
        self.assert_('following files are not recognized' in o)
604
 
        self.assert_('\n  cruft/food.1\n' in o)
605
 
        self.assert_('\n  daemon/notme.s\n' in o)
606
 
 
607
 
        f = self.installed_files()
608
 
        self.assert_('/usr/share/man/man1/foo.1' in f)
609
 
        self.assert_('/usr/share/man/man8/food.8' in f)
610
 
        ftext = '\n'.join(f)
611
 
        self.failIf('food.1' in ftext)
612
 
        self.failIf('notme' in ftext)
613
 
 
614
 
    def test_etc(self):
615
 
        '''etc/*'''
616
 
 
617
 
        self._mksrc('etc/cron.daily/foo')
618
 
        self._mksrc('etc/foo.conf')
619
 
        self._mksrc('etc/init.d/foo', executable=True)
620
 
        d = os.path.join(self.src, 'etc', 'cron.weekly')
621
 
        os.mkdir(d)
622
 
        os.symlink(os.path.join('..', 'cron.daily', 'foo'),
623
 
                os.path.join(d, 'foo'))
624
 
 
625
 
        (o, e, s) = self.do_install()
626
 
        self.assertEqual(e, '')
627
 
        self.assertEqual(s, 0)
628
 
        self.failIf('following files are not recognized' in o, o)
629
 
 
630
 
        f = self.installed_files()
631
 
        self.assert_('/etc/cron.daily/foo' in f)
632
 
        self.assert_('/etc/cron.weekly/foo' in f)
633
 
        self.assert_('/etc/init.d/foo' in f)
634
 
        self.assert_('/etc/foo.conf' in f)
635
 
 
636
 
        # verify that init script is executable
637
 
        self.assert_(os.access(os.path.join(self.install_tree, 'etc', 'init.d',
638
 
            'foo'), os.X_OK))
639
 
        # verify that symlinks get preserved
640
 
        self.assert_(os.path.islink(os.path.join(self.install_tree, 'etc',
641
 
            'cron.weekly', 'foo')))
642
 
 
643
 
        # check that we can install again into the same source tree
644
 
        (o, e, s) = self.setup_py(['install', '--no-compile', '--prefix=/usr', 
645
 
            '--root=' + self.install_tree])
646
 
        self.assertEqual(e, '')
647
 
        self.assertEqual(s, 0)
648
 
        self.failIf('following files are not recognized' in o, o)
649
 
 
650
 
    def test_requires_provides(self):
651
 
        '''automatic requires/provides'''
652
 
 
653
 
        try:
654
 
            __import__('pkg_resources')
655
 
            __import__('httplib2')
656
 
        except ImportError:
657
 
            self.fail('You need to have pkg_resources and httplib2 installed for this test suite to work')
658
 
 
659
 
        self._mksrc('foo/__init__.py', '')
660
 
        self._mksrc('foo/stuff.py', '''import xml.parsers.expat
661
 
import os, os.path, email.mime, distutils.command.register
662
 
from email import header as h
663
 
import httplib2.iri2uri, unknown
664
 
''')
665
 
 
666
 
        self._mksrc('foo/bar/__init__.py', '')
667
 
        self._mksrc('foo/bar/poke.py', 'def x(): pass')
668
 
 
669
 
        self._mksrc('mymod.py', 'import foo\nfrom foo.bar.poke import x')
670
 
 
671
 
        self._mksrc('bin/foo-cli', '''#!/usr/bin/python
672
 
import sys
673
 
import pkg_resources
674
 
import foo.bar
675
 
from httplib2 import iri2uri
676
 
 
677
 
print ('import iamnota.module')
678
 
''', executable=True)
679
 
 
680
 
        # this shouldn't be treated specially
681
 
        self._mksrc('data/example-code/template.py', 'import example.module')
682
 
        self._mksrc('data/example-code/mymod/__init__.py', '')
683
 
        self._mksrc('data/example-code/mymod/shiny.py', 'import example.othermod')
684
 
 
685
 
        (o, e, s) = self.do_install()
686
 
        self.assertEqual(s, 0)
687
 
        self.assertEqual(e, 'ERROR: Python module unknown not found\n')
688
 
        self.failIf('following files are not recognized' in o)
689
 
 
690
 
        inst = self.installed_files()
691
 
        self.assert_('/usr/share/foo/example-code/template.py' in inst)
692
 
        self.assert_('/usr/share/foo/example-code/mymod/shiny.py' in inst)
693
 
        for f in inst:
694
 
            if 'template.py' in f or 'shiny' in f:
695
 
                self.failIf('packages' in f)
696
 
 
697
 
        # parse .egg-info
698
 
        (o, e, s) = self.setup_py(['install_egg_info', '-d', self.install_tree])
699
 
        self.assertEqual(e, 'ERROR: Python module unknown not found\n')
700
 
        egg = open(os.path.join(self.install_tree,
701
 
            'foo-0.1.egg-info')).read().splitlines()
702
 
        self.assert_('Name: foo' in egg)
703
 
 
704
 
        # check provides
705
 
        prov = [prop.split(' ', 1)[1] for prop in egg if prop.startswith('Provides: ')]
706
 
        self.assertEqual(set(prov), set(['foo', 'mymod']))
707
 
 
708
 
        # check requires
709
 
        req = [prop.split(' ', 1)[1] for prop in egg if prop.startswith('Requires: ')]
710
 
        self.assertEqual(set(req), set(['DistUtilsExtra.auto', 'httplib2', 'pkg_resources']))
711
 
 
712
 
    def test_help(self):
713
 
        '''Docbook XML help'''
714
 
 
715
 
        self._mksrc('help/C/myprogram-C.omf')
716
 
        self._mksrc('help/C/myprogram.xml')
717
 
        self._mksrc('help/C/legal.xml')
718
 
        self._mksrc('help/C/figures/mainscreen.png')
719
 
        self._mksrc('help/de/myprogram-de.omf')
720
 
        self._mksrc('help/de/myprogram.xml')
721
 
        self._mksrc('help/de/legal.xml')
722
 
        self._mksrc('help/de/figures/mainscreen.png')
723
 
 
724
 
        self._mksrc('help/weird.xml')
725
 
        self._mksrc('help/notme.png')
726
 
 
727
 
        (o, e, s) = self.do_install()
728
 
        self.assertEqual(e, '')
729
 
        self.assertEqual(s, 0)
730
 
        self.assert_('following files are not recognized' in o)
731
 
        self.assert_('\n  help/weird.xml\n' in o)
732
 
        self.assert_('\n  help/notme.png\n' in o)
733
 
 
734
 
        f = self.installed_files()
735
 
        self.assert_('/usr/share/omf/foo/myprogram-C.omf' in f)
736
 
        self.assert_('/usr/share/omf/foo/myprogram-de.omf' in f)
737
 
        self.assert_('/usr/share/gnome/help/foo/C/myprogram.xml' in f)
738
 
        self.assert_('/usr/share/gnome/help/foo/C/legal.xml' in f)
739
 
        self.assert_('/usr/share/gnome/help/foo/C/figures/mainscreen.png' in f)
740
 
        self.assert_('/usr/share/gnome/help/foo/de/myprogram.xml' in f)
741
 
        self.assert_('/usr/share/gnome/help/foo/de/legal.xml' in f)
742
 
        self.assert_('/usr/share/gnome/help/foo/de/figures/mainscreen.png' in f)
743
 
 
744
 
    #
745
 
    # helper methods
746
 
    #
747
 
 
748
 
    def setup_py(self, args):
749
 
        '''Run setup.py with given arguments.
750
 
 
751
 
        For convenience, this snapshots the tree if no snapshot exists yet.
752
 
 
753
 
        Return (out, err, exitcode) triple.
754
 
        '''
755
 
        if not self.snapshot:
756
 
            self.do_snapshot()
757
 
 
758
 
        env = os.environ
759
 
        oldcwd = os.getcwd()
760
 
        if 'PYTHONPATH' not in env:
761
 
            env['PYTHONPATH'] = oldcwd
762
 
        os.chdir(self.src)
763
 
        s = subprocess.Popen(['/proc/self/exe', 'setup.py'] + args, env=env,
764
 
            stdout=subprocess.PIPE, stderr=subprocess.PIPE)
765
 
        (out, err) = s.communicate()
766
 
        out = out.decode()
767
 
        err = err.decode()
768
 
        os.chdir(oldcwd)
769
 
 
770
 
        # python3 distutils bug workaround, filter out bogus errors
771
 
        bogus_re = re.compile('^file .* \(for module .*\) not found$')
772
 
        err = '\n'.join([l for l in err.splitlines() if not bogus_re.match(l)])
773
 
        if err:
774
 
            err += '\n'
775
 
 
776
 
        return (out, err, s.returncode)
777
 
 
778
 
    def do_install(self):
779
 
        '''Run setup.py install into temporary tree.
780
 
 
781
 
        Return (out, err, exitcode) triple.
782
 
        '''
783
 
        self.install_tree = tempfile.mkdtemp()
784
 
 
785
 
        return self.setup_py(['install', '--no-compile', '--prefix=/usr', 
786
 
            '--root=' + self.install_tree])
787
 
 
788
 
    def installed_files(self):
789
 
        '''Return list of file paths in install tree.'''
790
 
 
791
 
        result = []
792
 
        for root, _, files in os.walk(self.install_tree):
793
 
            assert root.startswith(self.install_tree)
794
 
            r = root[len(self.install_tree):]
795
 
            for f in files:
796
 
                result.append(os.path.join(r, f))
797
 
        return result
798
 
 
799
 
    def _mksrc(self, path, content=None, executable=False):
800
 
        '''Create a file in the test source tree.'''
801
 
 
802
 
        path = os.path.join(self.src, path)
803
 
        dir = os.path.dirname(path)
804
 
        if not os.path.isdir(dir):
805
 
            os.makedirs(dir)
806
 
        f = open(path, 'w')
807
 
        if content is None:
808
 
            # default content, to spot with diff
809
 
            f.write('dummy')
810
 
        else:
811
 
            f.write(content + '\n')
812
 
        f.close()
813
 
 
814
 
        if executable:
815
 
            os.chmod(path, 0o755)
816
 
 
817
 
    def do_snapshot(self):
818
 
        '''Snapshot source tree.
819
 
 
820
 
        This should be called after a test set up all source files.
821
 
        '''
822
 
        assert self.snapshot is None, 'snapshot already taken'
823
 
 
824
 
        self.snapshot = tempfile.mkdtemp()
825
 
        shutil.copytree(self.src, os.path.join(self.snapshot, 's'))
826
 
 
827
 
    def diff_snapshot(self):
828
 
        '''Compare source tree to snapshot.
829
 
 
830
 
        Return diff -Nur output.
831
 
        '''
832
 
        assert self.snapshot, 'no snapshot taken'
833
 
        diff = subprocess.Popen(['diff', '-x', 'foo.pot', '-Nur', os.path.join(self.snapshot, 's'), 
834
 
            self.src], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
835
 
        (out, err) = diff.communicate()
836
 
        out = out.decode()
837
 
        self.assertEqual(err, b'', 'diff error messages')
838
 
        return out
839
 
 
840
 
    def _mkpo(self):
841
 
        '''Create some example po files.'''
842
 
 
843
 
        self._mksrc('po/POTFILES.in', '')
844
 
        self._mksrc('po/de.po', '''msgid ""
845
 
msgstr "Content-Type: text/plain; charset=UTF-8\\n"
846
 
 
847
 
msgid "Good morning"
848
 
msgstr "Guten Morgen"
849
 
 
850
 
msgid "Hello"
851
 
msgstr "Hallo"''')
852
 
        self._mksrc('po/fr.po', '''msgid ""
853
 
msgstr "Content-Type: text/plain; charset=UTF-8\\n"
854
 
        
855
 
msgid "Good morning"
856
 
msgstr "Bonjour"''')
857
 
 
858
 
    def _mk_i18n_source(self):
859
 
        '''Create some example source files with gettext calls'''
860
 
 
861
 
        self._mksrc('gtk/main.py', '''print (_("yes1"))
862
 
print ("no1")
863
 
print (__("no2"))
864
 
x = _('yes2 %s') % y
865
 
 
866
 
def f():
867
 
    print (_("yes3"))
868
 
    return _('yes6')''')
869
 
 
870
 
        self._mksrc('helpers.py', '''
871
 
print (f(_("yes4")))
872
 
print (_(\'\'\'yes5
873
 
even more
874
 
lines\'\'\'))
875
 
print (_("""yes6
876
 
more lines"""))
877
 
print (\'\'\'no3
878
 
boo\'\'\')
879
 
print ("""no4
880
 
more""")''')
881
 
 
882
 
        self._mksrc('gui/foo.desktop.in', '''[Desktop Entry]
883
 
_Name=yes7
884
 
_Comment=yes8
885
 
Icon=no5
886
 
Exec=/usr/bin/foo''')
887
 
 
888
 
        self._mksrc('daemon/com.example.foo.policy.in', '''<?xml version="1.0" encoding="UTF-8"?>
889
 
<!DOCTYPE policyconfig PUBLIC
890
 
 "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
891
 
 "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
892
 
<policyconfig>
893
 
  <action id="com.example.foo.greet">
894
 
    <_description>yes9</_description>
895
 
    <_message>yes10</_message>
896
 
    <defaults>
897
 
      <allow_active>no6</allow_active>
898
 
    </defaults>
899
 
  </action>
900
 
</policyconfig>''')
901
 
 
902
 
        self._mksrc('gtk/test.ui', '''<?xml version="1.0"?>
903
 
<interface>
904
 
  <requires lib="gtk+" version="2.16"/>
905
 
  <object class="GtkWindow" id="window1">
906
 
    <property name="title" translatable="yes">yes11</property>
907
 
    <child><placeholder/></child>
908
 
  </object>
909
 
</interface>''')
910
 
 
911
 
        self._mksrc('data/settings.ui', '''<?xml version="1.0"?>
912
 
<interface domain="foobar">
913
 
  <requires lib="gtk+" version="2.16"/>
914
 
  <object class="GtkWindow" id="window1">
915
 
    <property name="title" translatable="yes">yes12</property>
916
 
    <child><placeholder/></child>
917
 
  </object>
918
 
</interface>''')
919
 
 
920
 
        self._mksrc('Makefile', 'echo _("no7")')
921
 
 
922
 
        # Executables without *.py extension
923
 
        self._mksrc('gtk/foo-gtk', '#!/usr/bin/python\nprint (_("yes13"))',
924
 
                executable=True)
925
 
        self._mksrc('cli/foo-cli', '#!/usr/bin/env python\nprint (_(\'yes14\'))',
926
 
                executable=True)
927
 
        self._mksrc('daemon/foobarize', '#!/usr/bin/flex\np _("no8")',
928
 
                executable=True)
929
 
 
930
 
unittest.main()