Merge lp:~barry/ubuntu/natty/python-distutils-extra/670188-ftbfs into lp:ubuntu/natty/python-distutils-extra

Proposed by Barry Warsaw on 2010-11-03
Status: Merged
Merge reported by: Barry Warsaw
Merged at revision: not available
Proposed branch: lp:~barry/ubuntu/natty/python-distutils-extra/670188-ftbfs
Merge into: lp:ubuntu/natty/python-distutils-extra
Diff against target: 1183 lines (+71/-1041)
10 files modified
.bzrignore (+1/-0)
.pc/.version (+0/-1)
.pc/applied-patches (+0/-1)
.pc/debian-changes-2.22-2/DistUtilsExtra/command/check.py (+0/-105)
.pc/debian-changes-2.22-2/test/auto.py (+0/-930)
DistUtilsExtra/command/check.py (+13/-0)
debian/changelog (+7/-0)
debian/patches/fix-pythonpath (+49/-0)
debian/patches/series (+1/-0)
test/auto.py (+0/-4)
To merge this branch: bzr merge lp:~barry/ubuntu/natty/python-distutils-extra/670188-ftbfs
Reviewer Review Type Date Requested Status
Martin Pitt 2010-11-03 Needs Fixing on 2010-11-04
Ubuntu branches 2010-11-03 Pending
Review via email: mp+39993@code.launchpad.net

Description of the change

Handles the case that $PYTHONPATH is in the user's environment. Probably not important for the buildd's but it makes sbuilds less sensitive to environmental differences. This branch also cleans up a few pyflakes warnings.

With this branch, I can build the binary package in my sbuilds for natty.

To post a comment you must log in.
Martin Pitt (pitti) wrote :

Barry,

unfortuately this merge went totally wrong (see generated diff). Even looking at r21 in your branch doesn't give me a sensible patch.

Perhaps you can re-do this against lp:python-distutils-extra, or just send me a plain patch?

review: Needs Fixing
Barry Warsaw (barry) wrote :

Hi Martin,

The merge only looks crazy because it removes the .pc directory from version control. IIUC, that quilt artifact should not be in bzr, but you're probably right that it was too much distraction from the meat of the change.

I'll redo the patch against lp:python-distutils-extra and submit a merge proposal against that.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file '.bzrignore'
--- .bzrignore 1970-01-01 00:00:00 +0000
+++ .bzrignore 2010-11-03 17:39:44 +0000
@@ -0,0 +1,1 @@
1.pc
02
=== removed directory '.pc'
=== removed file '.pc/.version'
--- .pc/.version 2010-09-23 16:00:58 +0000
+++ .pc/.version 1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
12
20
=== removed file '.pc/applied-patches'
--- .pc/applied-patches 2010-09-23 16:00:58 +0000
+++ .pc/applied-patches 1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
1debian-changes-2.22-2
20
=== removed directory '.pc/debian-changes-2.22-2'
=== removed directory '.pc/debian-changes-2.22-2/DistUtilsExtra'
=== removed directory '.pc/debian-changes-2.22-2/DistUtilsExtra/command'
=== removed file '.pc/debian-changes-2.22-2/DistUtilsExtra/command/check.py'
--- .pc/debian-changes-2.22-2/DistUtilsExtra/command/check.py 2010-09-23 16:00:58 +0000
+++ .pc/debian-changes-2.22-2/DistUtilsExtra/command/check.py 1970-01-01 00:00:00 +0000
@@ -1,105 +0,0 @@
1# DistUtilsExtra.command.check - check command for DistUtilsExtra
2#
3# Author: Rodney Dawes <rodney.dawes@canonical.com>
4#
5# Copyright 2009 Canonical Ltd.
6#
7# This program is free software: you can redistribute it and/or modify it
8# under the terms of the GNU General Public License version 3, as published
9# by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful, but
12# WITHOUT ANY WARRANTY; without even the implied warranties of
13# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14# PURPOSE. See the GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program. If not, see <http://www.gnu.org/licenses/>.
18
19"""DistUtilsExtra.command.check
20
21Implements the DistUtilsExtra 'check' command.
22"""
23
24import os
25import subprocess
26
27from distutils.core import Command
28
29
30class check (Command):
31 """Command to run lint and tests on a module."""
32
33 description = "integrate pylint checks"
34
35 user_options = [("config-file=", None,
36 "pylint config file to use"),
37 ("exclude-files=", None,
38 "list of files to exclude from lint checks"),
39 ("lint-files=", None,
40 "list of modules or packages to run lint checks on")
41 ]
42
43 def initialize_options (self):
44 self.config_file = None
45 self.exclude_files = None
46 self.lint_files = None
47
48 def finalize_options (self):
49 if self.config_file is None:
50 self.config_file = ""
51 if self.exclude_files is None:
52 self.exclude_files = "[]"
53 if self.lint_files is None:
54 self.lint_files = "[" + self.__find_files() + "]"
55
56 def run (self):
57 pylint_args = ["--output-format=parseable",
58 "--include-ids=yes"]
59
60 if self.config_file:
61 pylint_args.append("--rcfile=" + self.config_file)
62
63 for file in eval(self.lint_files):
64 pylint_args.append(file)
65
66 p = subprocess.Popen(["pylint"] + pylint_args,
67 bufsize=4096, stdout=subprocess.PIPE)
68 notices = p.stdout
69
70 output = "".join(notices.readlines())
71 if output != "":
72 print "== Pylint notices =="
73 print self.__group_lines_by_file(output)
74
75 def __group_lines_by_file(self, input):
76 """Format file:line:message output as lines grouped by file."""
77 outputs = []
78 filename = ""
79 excludes = eval(self.exclude_files)
80 for line in input.splitlines():
81 current = line.split(":", 3)
82 if line.startswith(" "):
83 outputs.append(" " + current[0] + "")
84 elif line.startswith("build/") or current[0] in excludes or \
85 len(current) < 3:
86 pass
87 elif filename == current[0]:
88 outputs.append(" " + current[1] + ": " + current[2])
89 elif filename != current[0]:
90 filename = current[0]
91 outputs.append("")
92 outputs.append(filename + ":")
93 outputs.append(" " + current[1] + ": " + current[2])
94
95 return "\n".join(outputs)
96
97 def __find_files(self):
98 """Find all Python files under the current tree."""
99 pyfiles = []
100 for root, dirs, files in os.walk(os.getcwd(), topdown=False):
101 for file in files:
102 if file.endswith(".py"):
103 pyfiles.append("'" + os.path.join(root, file) + "'")
104 pyfiles.sort()
105 return ",".join(pyfiles)
1060
=== removed directory '.pc/debian-changes-2.22-2/test'
=== removed file '.pc/debian-changes-2.22-2/test/auto.py'
--- .pc/debian-changes-2.22-2/test/auto.py 2010-09-23 16:00:58 +0000
+++ .pc/debian-changes-2.22-2/test/auto.py 1970-01-01 00:00:00 +0000
@@ -1,930 +0,0 @@
1#!/usr/bin/python
2
3# test DistUtilsExtra.auto
4
5import sys, unittest, shutil, tempfile, os, os.path, subprocess, re
6
7class T(unittest.TestCase):
8 def setUp(self):
9 self.src = tempfile.mkdtemp()
10
11 self._mksrc('setup.py', '''
12from DistUtilsExtra.auto import setup
13
14setup(
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]
129Name=com.example.Foo
130Exec=/usr/lib/foo/foo_daemon
131User=root''')
132
133 # D-BUS session service
134 self._mksrc('gui/com.example.foo.gui.service', '''[D-BUS Service]
135Name=com.example.Foo.GUI
136Exec=/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
159def add_info(report):
160 pass
161''')
162
163 self._mksrc('apport/source_foo.py', '''import os, apport
164def 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
255Exec=/bin/foo''')
256 self._mksrc('gui/autostart/fooapplet.desktop.in', '''[Desktop Entry]
257_Name=Hello
258_Comment=Good morning
259Exec=/usr/bin/fooapplet''')
260 self._mkpo()
261 self._mksrc('data/foosettings.desktop.in', '''[Desktop Entry]
262_Name=Hello
263_Comment=Good morning
264Exec=/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', '''
312from DistUtilsExtra.auto import setup
313from glob import glob
314
315setup(
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', '''
404gtk/main.py
405gui/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', '''
463from DistUtilsExtra.auto import setup
464
465setup(
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
661import os, os.path, email.mime, distutils.command.register
662from email import header as h
663import 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
672import sys
673import pkg_resources
674import foo.bar
675from httplib2 import iri2uri
676
677print ('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 ""
845msgstr "Content-Type: text/plain; charset=UTF-8\\n"
846
847msgid "Good morning"
848msgstr "Guten Morgen"
849
850msgid "Hello"
851msgstr "Hallo"''')
852 self._mksrc('po/fr.po', '''msgid ""
853msgstr "Content-Type: text/plain; charset=UTF-8\\n"
854
855msgid "Good morning"
856msgstr "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"))
862print ("no1")
863print (__("no2"))
864x = _('yes2 %s') % y
865
866def f():
867 print (_("yes3"))
868 return _('yes6')''')
869
870 self._mksrc('helpers.py', '''
871print (f(_("yes4")))
872print (_(\'\'\'yes5
873even more
874lines\'\'\'))
875print (_("""yes6
876more lines"""))
877print (\'\'\'no3
878boo\'\'\')
879print ("""no4
880more""")''')
881
882 self._mksrc('gui/foo.desktop.in', '''[Desktop Entry]
883_Name=yes7
884_Comment=yes8
885Icon=no5
886Exec=/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
930unittest.main()
9310
=== modified file 'DistUtilsExtra/command/check.py'
--- DistUtilsExtra/command/check.py 2010-09-23 16:00:58 +0000
+++ DistUtilsExtra/command/check.py 2010-11-03 17:39:44 +0000
@@ -1,7 +1,20 @@
1# DistUtilsExtra.command.check - check command for DistUtilsExtra1# DistUtilsExtra.command.check - check command for DistUtilsExtra
2#2#
3# Author: Rodney Dawes <rodney.dawes@canonical.com>3# Author: Rodney Dawes <rodney.dawes@canonical.com>
4#
4# Copyright 2009 Canonical Ltd.5# Copyright 2009 Canonical Ltd.
6#
7# This program is free software: you can redistribute it and/or modify it
8# under the terms of the GNU General Public License version 3, as published
9# by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful, but
12# WITHOUT ANY WARRANTY; without even the implied warranties of
13# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14# PURPOSE. See the GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program. If not, see <http://www.gnu.org/licenses/>.
518
6"""DistUtilsExtra.command.check19"""DistUtilsExtra.command.check
720
821
=== modified file 'debian/changelog'
--- debian/changelog 2010-09-23 16:00:58 +0000
+++ debian/changelog 2010-11-03 17:39:44 +0000
@@ -1,3 +1,10 @@
1python-distutils-extra (2.22-2ubuntu1) natty; urgency=low
2
3 * When the environment has $PYTHONPATH in it, we still need to prepend
4 oldcwd so that the DistUtilsExtra package can be found. (LP: #670188)
5
6 -- Barry Warsaw <barry@ubuntu.com> Wed, 03 Nov 2010 13:31:44 -0400
7
1python-distutils-extra (2.22-2) unstable; urgency=low8python-distutils-extra (2.22-2) unstable; urgency=low
29
3 * Upload to unstable, now that the current python3 is in unstable.10 * Upload to unstable, now that the current python3 is in unstable.
411
=== added file 'debian/patches/fix-pythonpath'
--- debian/patches/fix-pythonpath 1970-01-01 00:00:00 +0000
+++ debian/patches/fix-pythonpath 2010-11-03 17:39:44 +0000
@@ -0,0 +1,49 @@
1=== modified file 'setup.py'
2--- setup.py 2010-09-17 13:42:32 +0000
3+++ setup.py 2010-11-03 16:46:34 +0000
4@@ -1,7 +1,7 @@
5 #!/usr/bin/env python
6
7 from setuptools import setup
8-import glob, os, sys
9+import sys
10
11 sys.path.insert(0, '.')
12 from DistUtilsExtra import __version__ as pkgversion
13
14=== modified file 'test/auto.py'
15--- test/auto.py 2010-09-23 16:00:58 +0000
16+++ test/auto.py 2010-11-03 17:19:17 +0000
17@@ -2,7 +2,7 @@
18
19 # test DistUtilsExtra.auto
20
21-import sys, unittest, shutil, tempfile, os, os.path, subprocess, re
22+import unittest, shutil, tempfile, os, os.path, subprocess, re
23
24 class T(unittest.TestCase):
25 def setUp(self):
26@@ -32,7 +32,7 @@
27 try:
28 # check that setup.py clean removes everything
29 (o, e, s) = self.setup_py(['clean', '-a'])
30- self.assertEqual(s, 0)
31+ self.assertEqual(s, 0, o+e)
32 cruft = self.diff_snapshot()
33 self.assertEqual(cruft, '', 'no cruft after cleaning:\n' + cruft)
34 finally:
35@@ -759,9 +759,11 @@
36 if not self.snapshot:
37 self.do_snapshot()
38
39- env = os.environ
40+ env = os.environ.copy()
41 oldcwd = os.getcwd()
42- if 'PYTHONPATH' not in env:
43+ if 'PYTHONPATH' in env:
44+ env['PYTHONPATH'] = oldcwd + os.pathsep + env['PYTHONPATH']
45+ else:
46 env['PYTHONPATH'] = oldcwd
47 os.chdir(self.src)
48 s = subprocess.Popen(['/proc/self/exe', 'setup.py'] + args, env=env,
49
050
=== modified file 'debian/patches/series'
--- debian/patches/series 2010-09-23 16:00:58 +0000
+++ debian/patches/series 2010-11-03 17:39:44 +0000
@@ -1,1 +1,2 @@
1debian-changes-2.22-21debian-changes-2.22-2
2fix-pythonpath -p0
23
=== modified file 'test/auto.py'
--- test/auto.py 2010-09-23 16:00:58 +0000
+++ test/auto.py 2010-11-03 17:39:44 +0000
@@ -9,10 +9,6 @@
9 self.src = tempfile.mkdtemp()9 self.src = tempfile.mkdtemp()
1010
11 self._mksrc('setup.py', '''11 self._mksrc('setup.py', '''
12# ignore warning about import from local path
13import warnings
14warnings.filterwarnings('ignore', 'Module DistUtilsExtra was already imported from.*')
15
16from DistUtilsExtra.auto import setup12from DistUtilsExtra.auto import setup
1713
18setup(14setup(

Subscribers

People subscribed via source and target branches

to all changes: