Merge lp:~jseutter/testresources/py3 into lp:~testresources-developers/testresources/trunk

Proposed by Jerry Seutter
Status: Needs review
Proposed branch: lp:~jseutter/testresources/py3
Merge into: lp:~testresources-developers/testresources/trunk
Diff against target: 695 lines (+526/-20)
7 files modified
distribute_setup.py (+494/-0)
lib/testresources/__init__.py (+13/-12)
lib/testresources/tests/TestUtil.py (+2/-1)
lib/testresources/tests/test_resource_graph.py (+2/-2)
lib/testresources/tests/test_resourced_test_case.py (+2/-2)
lib/testresources/tests/test_test_resource.py (+1/-1)
setup.py (+12/-2)
To merge this branch: bzr merge lp:~jseutter/testresources/py3
Reviewer Review Type Date Requested Status
Jerry Seutter (community) Disapprove
Barry Warsaw Pending
testresources developers Pending
Review via email: mp+105525@code.launchpad.net

Description of the change

This branch adds support for python 3. It uses "from __future__ import print_function", so it will not work in Python versions older than Python 2.6.

To post a comment you must log in.
Revision history for this message
Robert Collins (lifeless) wrote :

This seems to be much more than py3; whats the additional stuff for?
[and why would it be in-tree, it looks boilerplatey].

-Rob

Revision history for this message
Barry Warsaw (barry) wrote :

On May 11, 2012, at 08:49 PM, Robert Collins wrote:

>This seems to be much more than py3; whats the additional stuff for?
>[and why would it be in-tree, it looks boilerplatey].

Are you referring to the distribute_setup.py file? IME, distribute is much
better at Python 3 compatibility and is future-proof for when distutils is
removed[*], so I recommended Jerry switch to it rather than use it or
ez_setup.

[*] and not a moment too soon.

Revision history for this message
Barry Warsaw (barry) wrote :

On May 11, 2012, at 08:01 PM, Jerry Seutter wrote:

>You have been requested to review the proposed merge of
>lp:~jseutter/testresources/py3 into lp:testresources.
>
>For more details, see:
>https://code.launchpad.net/~jseutter/testresources/py3/+merge/105525
>
>This branch adds support for python 3. It uses "from __future__ import
>print_function", so it will not work in Python versions older than Python
>2.6.

+1

Revision history for this message
Robert Collins (lifeless) wrote :

I have a philospohical objection to having such massive boilerplate in
source trees. I'd put a smiley face here, but I'm not being humourous
;) It has to be maintained and updated - its dead weight.

Revision history for this message
Barry Warsaw (barry) wrote :

On May 11, 2012, at 11:40 PM, Robert Collins wrote:

>I have a philospohical objection to having such massive boilerplate in
>source trees. I'd put a smiley face here, but I'm not being humourous
>;) It has to be maintained and updated - its dead weight.

If the package is already pulling in ez_setup.py then it should definitely
convert to using distribute_setup.py. If it isn't doing the former, then just
change it back to using distutils.

Revision history for this message
Robert Collins (lifeless) wrote :

On Sat, May 12, 2012 at 2:14 PM, Barry Warsaw <email address hidden> wrote:
> On May 11, 2012, at 11:40 PM, Robert Collins wrote:
>
>>I have a philospohical objection to having such massive boilerplate in
>>source trees. I'd put a smiley face here, but I'm not being humourous
>>;) It has to be maintained and updated - its dead weight.
>
> If the package is already pulling in ez_setup.py then it should definitely
> convert to using distribute_setup.py.  If it isn't doing the former, then just
> change it back to using distutils.

Its not; ez_setup.py is terrible too :)

I'll look at this tomorrow/monday and merge just the py3 bits.

-Rob

Revision history for this message
Jerry Seutter (jseutter) wrote :

I made a new merge proposal that does not include distribute_setup. See https://code.launchpad.net/~jseutter/testresources/py3_without_distribute/+merge/105568 .

review: Disapprove

Unmerged revisions

61. By Jerry Seutter

Adding python 3 support.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'distribute_setup.py'
2--- distribute_setup.py 1970-01-01 00:00:00 +0000
3+++ distribute_setup.py 2012-05-11 19:59:18 +0000
4@@ -0,0 +1,494 @@
5+#!python
6+"""Bootstrap distribute installation
7+
8+If you want to use setuptools in your package's setup.py, just include this
9+file in the same directory with it, and add this to the top of your setup.py::
10+
11+ from distribute_setup import use_setuptools
12+ use_setuptools()
13+
14+If you want to require a specific version of setuptools, set a download
15+mirror, or use an alternate download directory, you can do so by supplying
16+the appropriate options to ``use_setuptools()``.
17+
18+This file can also be run as a script to install or upgrade setuptools.
19+"""
20+import os
21+import sys
22+import time
23+import fnmatch
24+import tempfile
25+import tarfile
26+from distutils import log
27+
28+try:
29+ from site import USER_SITE
30+except ImportError:
31+ USER_SITE = None
32+
33+try:
34+ import subprocess
35+
36+ def _python_cmd(*args):
37+ args = (sys.executable,) + args
38+ return subprocess.call(args) == 0
39+
40+except ImportError:
41+ # will be used for python 2.3
42+ def _python_cmd(*args):
43+ args = (sys.executable,) + args
44+ # quoting arguments if windows
45+ if sys.platform == 'win32':
46+ def quote(arg):
47+ if ' ' in arg:
48+ return '"%s"' % arg
49+ return arg
50+ args = [quote(arg) for arg in args]
51+ return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
52+
53+DEFAULT_VERSION = "0.6.26"
54+DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
55+SETUPTOOLS_FAKED_VERSION = "0.6c11"
56+
57+SETUPTOOLS_PKG_INFO = """\
58+Metadata-Version: 1.0
59+Name: setuptools
60+Version: %s
61+Summary: xxxx
62+Home-page: xxx
63+Author: xxx
64+Author-email: xxx
65+License: xxx
66+Description: xxx
67+""" % SETUPTOOLS_FAKED_VERSION
68+
69+
70+def _install(tarball, install_args=()):
71+ # extracting the tarball
72+ tmpdir = tempfile.mkdtemp()
73+ log.warn('Extracting in %s', tmpdir)
74+ old_wd = os.getcwd()
75+ try:
76+ os.chdir(tmpdir)
77+ tar = tarfile.open(tarball)
78+ _extractall(tar)
79+ tar.close()
80+
81+ # going in the directory
82+ subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
83+ os.chdir(subdir)
84+ log.warn('Now working in %s', subdir)
85+
86+ # installing
87+ log.warn('Installing Distribute')
88+ if not _python_cmd('setup.py', 'install', *install_args):
89+ log.warn('Something went wrong during the installation.')
90+ log.warn('See the error message above.')
91+ finally:
92+ os.chdir(old_wd)
93+
94+
95+def _build_egg(egg, tarball, to_dir):
96+ # extracting the tarball
97+ tmpdir = tempfile.mkdtemp()
98+ log.warn('Extracting in %s', tmpdir)
99+ old_wd = os.getcwd()
100+ try:
101+ os.chdir(tmpdir)
102+ tar = tarfile.open(tarball)
103+ _extractall(tar)
104+ tar.close()
105+
106+ # going in the directory
107+ subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
108+ os.chdir(subdir)
109+ log.warn('Now working in %s', subdir)
110+
111+ # building an egg
112+ log.warn('Building a Distribute egg in %s', to_dir)
113+ _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
114+
115+ finally:
116+ os.chdir(old_wd)
117+ # returning the result
118+ log.warn(egg)
119+ if not os.path.exists(egg):
120+ raise IOError('Could not build the egg.')
121+
122+
123+def _do_download(version, download_base, to_dir, download_delay):
124+ egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg'
125+ % (version, sys.version_info[0], sys.version_info[1]))
126+ if not os.path.exists(egg):
127+ tarball = download_setuptools(version, download_base,
128+ to_dir, download_delay)
129+ _build_egg(egg, tarball, to_dir)
130+ sys.path.insert(0, egg)
131+ import setuptools
132+ setuptools.bootstrap_install_from = egg
133+
134+
135+def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
136+ to_dir=os.curdir, download_delay=15, no_fake=True):
137+ # making sure we use the absolute path
138+ to_dir = os.path.abspath(to_dir)
139+ was_imported = 'pkg_resources' in sys.modules or \
140+ 'setuptools' in sys.modules
141+ try:
142+ try:
143+ import pkg_resources
144+ if not hasattr(pkg_resources, '_distribute'):
145+ if not no_fake:
146+ _fake_setuptools()
147+ raise ImportError
148+ except ImportError:
149+ return _do_download(version, download_base, to_dir, download_delay)
150+ try:
151+ pkg_resources.require("distribute>="+version)
152+ return
153+ except pkg_resources.VersionConflict:
154+ e = sys.exc_info()[1]
155+ if was_imported:
156+ sys.stderr.write(
157+ "The required version of distribute (>=%s) is not available,\n"
158+ "and can't be installed while this script is running. Please\n"
159+ "install a more recent version first, using\n"
160+ "'easy_install -U distribute'."
161+ "\n\n(Currently using %r)\n" % (version, e.args[0]))
162+ sys.exit(2)
163+ else:
164+ del pkg_resources, sys.modules['pkg_resources'] # reload ok
165+ return _do_download(version, download_base, to_dir,
166+ download_delay)
167+ except pkg_resources.DistributionNotFound:
168+ return _do_download(version, download_base, to_dir,
169+ download_delay)
170+ finally:
171+ if not no_fake:
172+ _create_fake_setuptools_pkg_info(to_dir)
173+
174+def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
175+ to_dir=os.curdir, delay=15):
176+ """Download distribute from a specified location and return its filename
177+
178+ `version` should be a valid distribute version number that is available
179+ as an egg for download under the `download_base` URL (which should end
180+ with a '/'). `to_dir` is the directory where the egg will be downloaded.
181+ `delay` is the number of seconds to pause before an actual download
182+ attempt.
183+ """
184+ # making sure we use the absolute path
185+ to_dir = os.path.abspath(to_dir)
186+ try:
187+ from urllib.request import urlopen
188+ except ImportError:
189+ from urllib2 import urlopen
190+ tgz_name = "distribute-%s.tar.gz" % version
191+ url = download_base + tgz_name
192+ saveto = os.path.join(to_dir, tgz_name)
193+ src = dst = None
194+ if not os.path.exists(saveto): # Avoid repeated downloads
195+ try:
196+ log.warn("Downloading %s", url)
197+ src = urlopen(url)
198+ # Read/write all in one block, so we don't create a corrupt file
199+ # if the download is interrupted.
200+ data = src.read()
201+ dst = open(saveto, "wb")
202+ dst.write(data)
203+ finally:
204+ if src:
205+ src.close()
206+ if dst:
207+ dst.close()
208+ return os.path.realpath(saveto)
209+
210+def _no_sandbox(function):
211+ def __no_sandbox(*args, **kw):
212+ try:
213+ from setuptools.sandbox import DirectorySandbox
214+ if not hasattr(DirectorySandbox, '_old'):
215+ def violation(*args):
216+ pass
217+ DirectorySandbox._old = DirectorySandbox._violation
218+ DirectorySandbox._violation = violation
219+ patched = True
220+ else:
221+ patched = False
222+ except ImportError:
223+ patched = False
224+
225+ try:
226+ return function(*args, **kw)
227+ finally:
228+ if patched:
229+ DirectorySandbox._violation = DirectorySandbox._old
230+ del DirectorySandbox._old
231+
232+ return __no_sandbox
233+
234+def _patch_file(path, content):
235+ """Will backup the file then patch it"""
236+ existing_content = open(path).read()
237+ if existing_content == content:
238+ # already patched
239+ log.warn('Already patched.')
240+ return False
241+ log.warn('Patching...')
242+ _rename_path(path)
243+ f = open(path, 'w')
244+ try:
245+ f.write(content)
246+ finally:
247+ f.close()
248+ return True
249+
250+_patch_file = _no_sandbox(_patch_file)
251+
252+def _same_content(path, content):
253+ return open(path).read() == content
254+
255+def _rename_path(path):
256+ new_name = path + '.OLD.%s' % time.time()
257+ log.warn('Renaming %s into %s', path, new_name)
258+ os.rename(path, new_name)
259+ return new_name
260+
261+def _remove_flat_installation(placeholder):
262+ if not os.path.isdir(placeholder):
263+ log.warn('Unkown installation at %s', placeholder)
264+ return False
265+ found = False
266+ for file in os.listdir(placeholder):
267+ if fnmatch.fnmatch(file, 'setuptools*.egg-info'):
268+ found = True
269+ break
270+ if not found:
271+ log.warn('Could not locate setuptools*.egg-info')
272+ return
273+
274+ log.warn('Removing elements out of the way...')
275+ pkg_info = os.path.join(placeholder, file)
276+ if os.path.isdir(pkg_info):
277+ patched = _patch_egg_dir(pkg_info)
278+ else:
279+ patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO)
280+
281+ if not patched:
282+ log.warn('%s already patched.', pkg_info)
283+ return False
284+ # now let's move the files out of the way
285+ for element in ('setuptools', 'pkg_resources.py', 'site.py'):
286+ element = os.path.join(placeholder, element)
287+ if os.path.exists(element):
288+ _rename_path(element)
289+ else:
290+ log.warn('Could not find the %s element of the '
291+ 'Setuptools distribution', element)
292+ return True
293+
294+_remove_flat_installation = _no_sandbox(_remove_flat_installation)
295+
296+def _after_install(dist):
297+ log.warn('After install bootstrap.')
298+ placeholder = dist.get_command_obj('install').install_purelib
299+ _create_fake_setuptools_pkg_info(placeholder)
300+
301+def _create_fake_setuptools_pkg_info(placeholder):
302+ if not placeholder or not os.path.exists(placeholder):
303+ log.warn('Could not find the install location')
304+ return
305+ pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1])
306+ setuptools_file = 'setuptools-%s-py%s.egg-info' % \
307+ (SETUPTOOLS_FAKED_VERSION, pyver)
308+ pkg_info = os.path.join(placeholder, setuptools_file)
309+ if os.path.exists(pkg_info):
310+ log.warn('%s already exists', pkg_info)
311+ return
312+
313+ log.warn('Creating %s', pkg_info)
314+ f = open(pkg_info, 'w')
315+ try:
316+ f.write(SETUPTOOLS_PKG_INFO)
317+ finally:
318+ f.close()
319+
320+ pth_file = os.path.join(placeholder, 'setuptools.pth')
321+ log.warn('Creating %s', pth_file)
322+ f = open(pth_file, 'w')
323+ try:
324+ f.write(os.path.join(os.curdir, setuptools_file))
325+ finally:
326+ f.close()
327+
328+_create_fake_setuptools_pkg_info = _no_sandbox(_create_fake_setuptools_pkg_info)
329+
330+def _patch_egg_dir(path):
331+ # let's check if it's already patched
332+ pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
333+ if os.path.exists(pkg_info):
334+ if _same_content(pkg_info, SETUPTOOLS_PKG_INFO):
335+ log.warn('%s already patched.', pkg_info)
336+ return False
337+ _rename_path(path)
338+ os.mkdir(path)
339+ os.mkdir(os.path.join(path, 'EGG-INFO'))
340+ pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
341+ f = open(pkg_info, 'w')
342+ try:
343+ f.write(SETUPTOOLS_PKG_INFO)
344+ finally:
345+ f.close()
346+ return True
347+
348+_patch_egg_dir = _no_sandbox(_patch_egg_dir)
349+
350+def _before_install():
351+ log.warn('Before install bootstrap.')
352+ _fake_setuptools()
353+
354+
355+def _under_prefix(location):
356+ if 'install' not in sys.argv:
357+ return True
358+ args = sys.argv[sys.argv.index('install')+1:]
359+ for index, arg in enumerate(args):
360+ for option in ('--root', '--prefix'):
361+ if arg.startswith('%s=' % option):
362+ top_dir = arg.split('root=')[-1]
363+ return location.startswith(top_dir)
364+ elif arg == option:
365+ if len(args) > index:
366+ top_dir = args[index+1]
367+ return location.startswith(top_dir)
368+ if arg == '--user' and USER_SITE is not None:
369+ return location.startswith(USER_SITE)
370+ return True
371+
372+
373+def _fake_setuptools():
374+ log.warn('Scanning installed packages')
375+ try:
376+ import pkg_resources
377+ except ImportError:
378+ # we're cool
379+ log.warn('Setuptools or Distribute does not seem to be installed.')
380+ return
381+ ws = pkg_resources.working_set
382+ try:
383+ setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools',
384+ replacement=False))
385+ except TypeError:
386+ # old distribute API
387+ setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools'))
388+
389+ if setuptools_dist is None:
390+ log.warn('No setuptools distribution found')
391+ return
392+ # detecting if it was already faked
393+ setuptools_location = setuptools_dist.location
394+ log.warn('Setuptools installation detected at %s', setuptools_location)
395+
396+ # if --root or --preix was provided, and if
397+ # setuptools is not located in them, we don't patch it
398+ if not _under_prefix(setuptools_location):
399+ log.warn('Not patching, --root or --prefix is installing Distribute'
400+ ' in another location')
401+ return
402+
403+ # let's see if its an egg
404+ if not setuptools_location.endswith('.egg'):
405+ log.warn('Non-egg installation')
406+ res = _remove_flat_installation(setuptools_location)
407+ if not res:
408+ return
409+ else:
410+ log.warn('Egg installation')
411+ pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO')
412+ if (os.path.exists(pkg_info) and
413+ _same_content(pkg_info, SETUPTOOLS_PKG_INFO)):
414+ log.warn('Already patched.')
415+ return
416+ log.warn('Patching...')
417+ # let's create a fake egg replacing setuptools one
418+ res = _patch_egg_dir(setuptools_location)
419+ if not res:
420+ return
421+ log.warn('Patched done.')
422+ _relaunch()
423+
424+
425+def _relaunch():
426+ log.warn('Relaunching...')
427+ # we have to relaunch the process
428+ # pip marker to avoid a relaunch bug
429+ if sys.argv[:3] == ['-c', 'install', '--single-version-externally-managed']:
430+ sys.argv[0] = 'setup.py'
431+ args = [sys.executable] + sys.argv
432+ sys.exit(subprocess.call(args))
433+
434+
435+def _extractall(self, path=".", members=None):
436+ """Extract all members from the archive to the current working
437+ directory and set owner, modification time and permissions on
438+ directories afterwards. `path' specifies a different directory
439+ to extract to. `members' is optional and must be a subset of the
440+ list returned by getmembers().
441+ """
442+ import copy
443+ import operator
444+ from tarfile import ExtractError
445+ directories = []
446+
447+ if members is None:
448+ members = self
449+
450+ for tarinfo in members:
451+ if tarinfo.isdir():
452+ # Extract directories with a safe mode.
453+ directories.append(tarinfo)
454+ tarinfo = copy.copy(tarinfo)
455+ tarinfo.mode = 448 # decimal for oct 0700
456+ self.extract(tarinfo, path)
457+
458+ # Reverse sort directories.
459+ if sys.version_info < (2, 4):
460+ def sorter(dir1, dir2):
461+ return cmp(dir1.name, dir2.name)
462+ directories.sort(sorter)
463+ directories.reverse()
464+ else:
465+ directories.sort(key=operator.attrgetter('name'), reverse=True)
466+
467+ # Set correct owner, mtime and filemode on directories.
468+ for tarinfo in directories:
469+ dirpath = os.path.join(path, tarinfo.name)
470+ try:
471+ self.chown(tarinfo, dirpath)
472+ self.utime(tarinfo, dirpath)
473+ self.chmod(tarinfo, dirpath)
474+ except ExtractError:
475+ e = sys.exc_info()[1]
476+ if self.errorlevel > 1:
477+ raise
478+ else:
479+ self._dbg(1, "tarfile: %s" % e)
480+
481+def _build_install_args(argv):
482+ install_args = []
483+ user_install = '--user' in argv
484+ if user_install and sys.version_info < (2,6):
485+ log.warn("--user requires Python 2.6 or later")
486+ raise SystemExit(1)
487+ if user_install:
488+ install_args.append('--user')
489+ return install_args
490+
491+def main(argv, version=DEFAULT_VERSION):
492+ """Install or upgrade setuptools and EasyInstall"""
493+ tarball = download_setuptools()
494+ _install(tarball, _build_install_args(argv))
495+
496+
497+if __name__ == '__main__':
498+ main(sys.argv[1:])
499
500=== modified file 'lib/testresources/__init__.py'
501--- lib/testresources/__init__.py 2011-05-03 18:38:27 +0000
502+++ lib/testresources/__init__.py 2012-05-11 19:59:18 +0000
503@@ -21,6 +21,7 @@
504 import inspect
505 import operator
506 import unittest
507+import collections
508
509
510 def test_suite():
511@@ -41,12 +42,12 @@
512 No other edges are created.
513 """
514 result = {}
515- for from_node, from_prime_node in prime_node_mapping.iteritems():
516+ for from_node, from_prime_node in prime_node_mapping.items():
517 result[from_node] = {from_prime_node:0}
518 result[from_prime_node] = {from_node:0}
519- for from_node, to_nodes in digraph.iteritems():
520+ for from_node, to_nodes in digraph.items():
521 from_prime = prime_node_mapping[from_node]
522- for to_node, value in to_nodes.iteritems():
523+ for to_node, value in to_nodes.items():
524 to_prime = prime_node_mapping[to_node]
525 result[from_prime][to_node] = value
526 result[to_node][from_prime] = value
527@@ -72,8 +73,8 @@
528 # collect edges: every edge is present twice (due to the graph
529 # representation), so normalise.
530 edges = set()
531- for from_node, to_nodes in graph.iteritems():
532- for to_node, value in to_nodes.iteritems():
533+ for from_node, to_nodes in graph.items():
534+ for to_node, value in to_nodes.items():
535 edge = (value,) + tuple(sorted([from_node, to_node]))
536 edges.add(edge)
537 edges = list(edges)
538@@ -87,7 +88,7 @@
539 continue # already joined
540 # combine g1 and g2 into g1
541 graphs -= 1
542- for from_node, to_nodes in g2.iteritems():
543+ for from_node, to_nodes in g2.items():
544 #remember its symmetric, don't need to do 'to'.
545 forest[from_node] = g1
546 g1.setdefault(from_node, {}).update(to_nodes)
547@@ -96,10 +97,10 @@
548 g1[edge[2]][edge[1]] = edge[0]
549 # union the remaining graphs
550 _, result = forest.popitem()
551- for _, g2 in forest.iteritems():
552+ for _, g2 in forest.items():
553 if g2 is result: # common case
554 continue
555- for from_node, to_nodes in g2.iteritems():
556+ for from_node, to_nodes in g2.items():
557 result.setdefault(from_node, {}).update(to_nodes)
558 return result
559
560@@ -120,7 +121,7 @@
561 for resource in resource_set:
562 edges.setdefault(resource, []).append(node)
563 # populate the adjacent members of nodes
564- for node, connected in nodes.iteritems():
565+ for node, connected in nodes.items():
566 for resource in node:
567 connected.update(edges[resource])
568 connected.discard(node)
569@@ -361,7 +362,7 @@
570 node = root
571 cycle = [node]
572 steps = 2 * (len(mst) - 1)
573- for step in xrange(steps):
574+ for step in range(steps):
575 found = False
576 outgoing = None # For clearer debugging.
577 for outgoing in mst[node]:
578@@ -438,7 +439,7 @@
579 def _call_result_method_if_exists(self, result, methodname, *args):
580 """Call a method on a TestResult that may exist."""
581 method = getattr(result, methodname, None)
582- if callable(method):
583+ if isinstance(method, collections.Callable):
584 method(*args)
585
586 def _clean_all(self, resource, result):
587@@ -518,7 +519,7 @@
588 for name, resource in self.resources:
589 dependency_resources[name] = resource.getResource()
590 resource = self.make(dependency_resources)
591- for name, value in dependency_resources.items():
592+ for name, value in list(dependency_resources.items()):
593 setattr(resource, name, value)
594 self._call_result_method_if_exists(result, "stopMakeResource", self)
595 return resource
596
597=== modified file 'lib/testresources/tests/TestUtil.py'
598--- lib/testresources/tests/TestUtil.py 2008-08-16 07:10:40 +0000
599+++ lib/testresources/tests/TestUtil.py 2012-05-11 19:59:18 +0000
600@@ -15,6 +15,7 @@
601 # along with this program; if not, write to the Free Software
602 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
603 #
604+from __future__ import print_function
605
606 import sys
607 import logging
608@@ -56,7 +57,7 @@
609 visitor.visitSuite(test)
610 visitTests(test, visitor)
611 else:
612- print "unvisitable non-unittest.TestCase element %r (%r)" % (test, test.__class__)
613+ print("unvisitable non-unittest.TestCase element %r (%r)" % (test, test.__class__))
614
615
616 class TestSuite(unittest.TestSuite):
617
618=== modified file 'lib/testresources/tests/test_resource_graph.py'
619--- lib/testresources/tests/test_resource_graph.py 2010-02-26 22:40:43 +0000
620+++ lib/testresources/tests/test_resource_graph.py 2012-05-11 19:59:18 +0000
621@@ -132,8 +132,8 @@
622 F:{ D:6},
623 G:{ E:9}}
624 result = testresources._kruskals_graph_MST(graph)
625- e_weight = sum(sum(row.itervalues()) for row in expected.itervalues())
626- r_weight = sum(sum(row.itervalues()) for row in result.itervalues())
627+ e_weight = sum(sum(row.values()) for row in expected.values())
628+ r_weight = sum(sum(row.values()) for row in result.values())
629 self.assertEqual(e_weight, r_weight)
630 self.assertEqual(expected,
631 testresources._kruskals_graph_MST(graph))
632
633=== modified file 'lib/testresources/tests/test_resourced_test_case.py'
634--- lib/testresources/tests/test_resourced_test_case.py 2011-05-04 22:08:24 +0000
635+++ lib/testresources/tests/test_resourced_test_case.py 2012-05-11 19:59:18 +0000
636@@ -129,7 +129,7 @@
637 self.resourced_case.resources = [("foo", self.resource_manager)]
638 self.resourced_case.setUpResources()
639 self.resourced_case.tearDownResources()
640- self.failIf(hasattr(self.resourced_case, "foo"))
641+ self.assertFalse(hasattr(self.resourced_case, "foo"))
642
643 def testTearDownResourcesStopsUsingResource(self):
644 # tearDownResources records that there is one less use of each
645@@ -158,5 +158,5 @@
646 self.assertEqual(self.resourced_case.foo, self.resource)
647 self.assertEqual(self.resource_manager._uses, 1)
648 self.resourced_case.tearDown()
649- self.failIf(hasattr(self.resourced_case, "foo"))
650+ self.assertFalse(hasattr(self.resourced_case, "foo"))
651 self.assertEqual(self.resource_manager._uses, 0)
652
653=== modified file 'lib/testresources/tests/test_test_resource.py'
654--- lib/testresources/tests/test_test_resource.py 2010-11-14 17:43:44 +0000
655+++ lib/testresources/tests/test_test_resource.py 2012-05-11 19:59:18 +0000
656@@ -127,7 +127,7 @@
657 def testGetResourceReturnsMakeResource(self):
658 resource_manager = MockResource()
659 resource = resource_manager.getResource()
660- self.assertEqual(resource_manager.make({}), resource)
661+ self.assertEqual(type(resource_manager.make({})), type(resource))
662
663 def testGetResourceIncrementsUses(self):
664 resource_manager = MockResource()
665
666=== modified file 'setup.py'
667--- setup.py 2012-01-27 04:59:50 +0000
668+++ setup.py 2012-05-11 19:59:18 +0000
669@@ -1,9 +1,13 @@
670 #!/usr/bin/env python
671
672-from distutils.core import setup
673+from distribute_setup import use_setuptools
674+use_setuptools()
675+
676+from setuptools import setup
677 import os.path
678
679-description = file(os.path.join(os.path.dirname(__file__), 'README'), 'rb').read()
680+description = open(os.path.join(os.path.dirname(__file__), 'README'), 'rb').read()
681+description = description.decode('utf-8')
682
683 setup(name="testresources",
684 version="0.2.5",
685@@ -25,4 +29,10 @@
686 'Topic :: Software Development :: Quality Assurance',
687 'Topic :: Software Development :: Testing',
688 ],
689+ extras_require = dict(
690+ test=[
691+ 'testtools',
692+ ]
693+ ),
694+ test_suite="testresources.tests",
695 )

Subscribers

People subscribed via source and target branches