| Index: third_party/logilab/common/pytest.py
 | 
| ===================================================================
 | 
| --- third_party/logilab/common/pytest.py	(revision 292986)
 | 
| +++ third_party/logilab/common/pytest.py	(working copy)
 | 
| @@ -92,6 +92,9 @@
 | 
|   * ``tata`` and ``titi`` match``rouge ^ carre``
 | 
|   * ``titi`` match ``rouge and not carre``
 | 
|  """
 | 
| +
 | 
| +from __future__ import print_function
 | 
| +
 | 
|  __docformat__ = "restructuredtext en"
 | 
|  
 | 
|  PYTEST_DOC = """%prog [OPTIONS] [testfile [testpattern]]
 | 
| @@ -105,9 +108,6 @@
 | 
|  
 | 
|  pytest one (will run both test_thisone and test_thatone)
 | 
|  pytest path/to/mytests.py -s not (will skip test_notthisone)
 | 
| -
 | 
| -pytest --coverage test_foo.py
 | 
| -  (only if logilab.devtools is available)
 | 
|  """
 | 
|  
 | 
|  ENABLE_DBC = False
 | 
| @@ -118,6 +118,7 @@
 | 
|  from time import time, clock
 | 
|  import warnings
 | 
|  import types
 | 
| +from inspect import isgeneratorfunction, isclass
 | 
|  
 | 
|  from logilab.common.fileutils import abspath_listdir
 | 
|  from logilab.common import textutils
 | 
| @@ -124,7 +125,6 @@
 | 
|  from logilab.common import testlib, STD_BLACKLIST
 | 
|  # use the same unittest module as testlib
 | 
|  from logilab.common.testlib import unittest, start_interactive_mode
 | 
| -from logilab.common.compat import any
 | 
|  import doctest
 | 
|  
 | 
|  import unittest as unittest_legacy
 | 
| @@ -206,7 +206,7 @@
 | 
|      and / or tester.
 | 
|      """
 | 
|      namespace = {}
 | 
| -    execfile(path, namespace)
 | 
| +    exec(open(path, 'rb').read(), namespace)
 | 
|      if 'update_parser' in namespace:
 | 
|          namespace['update_parser'](parser)
 | 
|      return namespace.get('CustomPyTester', PyTester)
 | 
| @@ -309,7 +309,7 @@
 | 
|      we **have** to clean sys.modules to make sure the correct test_utils
 | 
|      module is ran in B
 | 
|      """
 | 
| -    for modname, mod in sys.modules.items():
 | 
| +    for modname, mod in list(sys.modules.items()):
 | 
|          if mod is None:
 | 
|              continue
 | 
|          if not hasattr(mod, '__file__'):
 | 
| @@ -336,8 +336,8 @@
 | 
|      def show_report(self):
 | 
|          """prints the report and returns appropriate exitcode"""
 | 
|          # everything has been ran, print report
 | 
| -        print "*" * 79
 | 
| -        print self.report
 | 
| +        print("*" * 79)
 | 
| +        print(self.report)
 | 
|  
 | 
|      def get_errcode(self):
 | 
|          # errcode set explicitly
 | 
| @@ -360,13 +360,13 @@
 | 
|                      dirs.remove(skipped)
 | 
|              basename = osp.basename(dirname)
 | 
|              if this_is_a_testdir(basename):
 | 
| -                print "going into", dirname
 | 
| +                print("going into", dirname)
 | 
|                  # we found a testdir, let's explore it !
 | 
|                  if not self.testonedir(dirname, exitfirst):
 | 
|                      break
 | 
|                  dirs[:] = []
 | 
|          if self.report.ran == 0:
 | 
| -            print "no test dir found testing here:", here
 | 
| +            print("no test dir found testing here:", here)
 | 
|              # if no test was found during the visit, consider
 | 
|              # the local directory as a test directory even if
 | 
|              # it doesn't have a traditional test directory name
 | 
| @@ -385,10 +385,11 @@
 | 
|                      try:
 | 
|                          restartfile = open(FILE_RESTART, "w")
 | 
|                          restartfile.close()
 | 
| -                    except Exception, e:
 | 
| -                        print >> sys.__stderr__, "Error while overwriting \
 | 
| -succeeded test file :", osp.join(os.getcwd(), FILE_RESTART)
 | 
| -                        raise e
 | 
| +                    except Exception:
 | 
| +                        print("Error while overwriting succeeded test file :",
 | 
| +                              osp.join(os.getcwd(), FILE_RESTART),
 | 
| +                              file=sys.__stderr__)
 | 
| +                        raise
 | 
|                  # run test and collect information
 | 
|                  prog = self.testfile(filename, batchmode=True)
 | 
|                  if exitfirst and (prog is None or not prog.result.wasSuccessful()):
 | 
| @@ -412,16 +413,14 @@
 | 
|              try:
 | 
|                  restartfile = open(FILE_RESTART, "w")
 | 
|                  restartfile.close()
 | 
| -            except Exception, e:
 | 
| -                print >> sys.__stderr__, "Error while overwriting \
 | 
| -succeeded test file :", osp.join(os.getcwd(), FILE_RESTART)
 | 
| -                raise e
 | 
| +            except Exception:
 | 
| +                print("Error while overwriting succeeded test file :",
 | 
| +                      osp.join(os.getcwd(), FILE_RESTART), file=sys.__stderr__)
 | 
| +                raise
 | 
|          modname = osp.basename(filename)[:-3]
 | 
| +        print(('  %s  ' % osp.basename(filename)).center(70, '='),
 | 
| +              file=sys.__stderr__)
 | 
|          try:
 | 
| -            print >> sys.stderr, ('  %s  ' % osp.basename(filename)).center(70, '=')
 | 
| -        except TypeError: # < py 2.4 bw compat
 | 
| -            print >> sys.stderr, ('  %s  ' % osp.basename(filename)).center(70)
 | 
| -        try:
 | 
|              tstart, cstart = time(), clock()
 | 
|              try:
 | 
|                  testprog = SkipAwareTestProgram(modname, batchmode=batchmode, cvg=self.cvg,
 | 
| @@ -428,16 +427,17 @@
 | 
|                                                   options=self.options, outstream=sys.stderr)
 | 
|              except KeyboardInterrupt:
 | 
|                  raise
 | 
| -            except SystemExit, exc:
 | 
| +            except SystemExit as exc:
 | 
|                  self.errcode = exc.code
 | 
|                  raise
 | 
|              except testlib.SkipTest:
 | 
| -                print "Module skipped:", filename
 | 
| +                print("Module skipped:", filename)
 | 
|                  self.report.skip_module(filename)
 | 
|                  return None
 | 
|              except Exception:
 | 
|                  self.report.failed_to_test_module(filename)
 | 
| -                print >> sys.stderr, 'unhandled exception occurred while testing', modname
 | 
| +                print('unhandled exception occurred while testing', modname,
 | 
| +                      file=sys.stderr)
 | 
|                  import traceback
 | 
|                  traceback.print_exc(file=sys.stderr)
 | 
|                  return None
 | 
| @@ -488,7 +488,7 @@
 | 
|          from django.test.utils import teardown_test_environment
 | 
|          from django.test.utils import destroy_test_db
 | 
|          teardown_test_environment()
 | 
| -        print 'destroying', self.dbname
 | 
| +        print('destroying', self.dbname)
 | 
|          destroy_test_db(self.dbname, verbosity=0)
 | 
|  
 | 
|      def testall(self, exitfirst=False):
 | 
| @@ -506,7 +506,7 @@
 | 
|              else:
 | 
|                  basename = osp.basename(dirname)
 | 
|                  if basename in ('test', 'tests'):
 | 
| -                    print "going into", dirname
 | 
| +                    print("going into", dirname)
 | 
|                      # we found a testdir, let's explore it !
 | 
|                      if not self.testonedir(dirname, exitfirst):
 | 
|                          break
 | 
| @@ -547,7 +547,8 @@
 | 
|              os.chdir(dirname)
 | 
|          self.load_django_settings(dirname)
 | 
|          modname = osp.basename(filename)[:-3]
 | 
| -        print >>sys.stderr, ('  %s  ' % osp.basename(filename)).center(70, '=')
 | 
| +        print(('  %s  ' % osp.basename(filename)).center(70, '='),
 | 
| +              file=sys.stderr)
 | 
|          try:
 | 
|              try:
 | 
|                  tstart, cstart = time(), clock()
 | 
| @@ -559,12 +560,12 @@
 | 
|                  return testprog
 | 
|              except SystemExit:
 | 
|                  raise
 | 
| -            except Exception, exc:
 | 
| +            except Exception as exc:
 | 
|                  import traceback
 | 
|                  traceback.print_exc()
 | 
|                  self.report.failed_to_test_module(filename)
 | 
| -                print 'unhandled exception occurred while testing', modname
 | 
| -                print 'error: %s' % exc
 | 
| +                print('unhandled exception occurred while testing', modname)
 | 
| +                print('error: %s' % exc)
 | 
|                  return None
 | 
|          finally:
 | 
|              self.after_testfile()
 | 
| @@ -604,7 +605,7 @@
 | 
|                        action="callback", help="Verbose output")
 | 
|      parser.add_option('-i', '--pdb', callback=rebuild_and_store,
 | 
|                        dest="pdb", action="callback",
 | 
| -                      help="Enable test failure inspection (conflicts with --coverage)")
 | 
| +                      help="Enable test failure inspection")
 | 
|      parser.add_option('-x', '--exitfirst', callback=rebuild_and_store,
 | 
|                        dest="exitfirst", default=False,
 | 
|                        action="callback", help="Exit on first failure "
 | 
| @@ -631,14 +632,6 @@
 | 
|      parser.add_option('-m', '--match', default=None, dest='tags_pattern',
 | 
|                        help="only execute test whose tag match the current pattern")
 | 
|  
 | 
| -    try:
 | 
| -        from logilab.devtools.lib.coverage import Coverage
 | 
| -        parser.add_option('--coverage', dest="coverage", default=False,
 | 
| -                          action="store_true",
 | 
| -                          help="run tests with pycoverage (conflicts with --pdb)")
 | 
| -    except ImportError:
 | 
| -        pass
 | 
| -
 | 
|      if DJANGO_FOUND:
 | 
|          parser.add_option('-J', '--django', dest='django', default=False,
 | 
|                            action="store_true",
 | 
| @@ -652,8 +645,6 @@
 | 
|      """
 | 
|      # parse the command line
 | 
|      options, args = parser.parse_args()
 | 
| -    if options.pdb and getattr(options, 'coverage', False):
 | 
| -        parser.error("'pdb' and 'coverage' options are exclusive")
 | 
|      filenames = [arg for arg in args if arg.endswith('.py')]
 | 
|      if filenames:
 | 
|          if len(filenames) > 1:
 | 
| @@ -683,16 +674,9 @@
 | 
|      options, explicitfile = parseargs(parser)
 | 
|      # mock a new command line
 | 
|      sys.argv[1:] = parser.newargs
 | 
| -    covermode = getattr(options, 'coverage', None)
 | 
|      cvg = None
 | 
|      if not '' in sys.path:
 | 
|          sys.path.insert(0, '')
 | 
| -    if covermode:
 | 
| -        # control_import_coverage(rootdir)
 | 
| -        from logilab.devtools.lib.coverage import Coverage
 | 
| -        cvg = Coverage([rootdir])
 | 
| -        cvg.erase()
 | 
| -        cvg.start()
 | 
|      if DJANGO_FOUND and options.django:
 | 
|          tester = DjangoTester(cvg, options)
 | 
|      else:
 | 
| @@ -710,7 +694,7 @@
 | 
|                  prof = hotshot.Profile(options.profile)
 | 
|                  prof.runcall(cmd, *args)
 | 
|                  prof.close()
 | 
| -                print 'profile data saved in', options.profile
 | 
| +                print('profile data saved in', options.profile)
 | 
|              else:
 | 
|                  cmd(*args)
 | 
|          except SystemExit:
 | 
| @@ -719,12 +703,7 @@
 | 
|              import traceback
 | 
|              traceback.print_exc()
 | 
|      finally:
 | 
| -        if covermode:
 | 
| -            cvg.stop()
 | 
| -            cvg.save()
 | 
|          tester.show_report()
 | 
| -        if covermode:
 | 
| -            print 'coverage information stored, use it with pycoverage -ra'
 | 
|          sys.exit(tester.errcode)
 | 
|  
 | 
|  class SkipAwareTestProgram(unittest.TestProgram):
 | 
| @@ -816,7 +795,7 @@
 | 
|              else:
 | 
|                  self.testNames = (self.defaultTest, )
 | 
|              self.createTests()
 | 
| -        except getopt.error, msg:
 | 
| +        except getopt.error as msg:
 | 
|              self.usageExit(msg)
 | 
|  
 | 
|      def runTests(self):
 | 
| @@ -865,7 +844,7 @@
 | 
|                      removeSucceededTests(self.test, succeededtests)
 | 
|                  finally:
 | 
|                      restartfile.close()
 | 
| -            except Exception, ex:
 | 
| +            except Exception as ex:
 | 
|                  raise Exception("Error while reading succeeded tests into %s: %s"
 | 
|                                  % (osp.join(os.getcwd(), FILE_RESTART), ex))
 | 
|  
 | 
| @@ -907,17 +886,16 @@
 | 
|          else:
 | 
|              if isinstance(test, testlib.TestCase):
 | 
|                  meth = test._get_test_method()
 | 
| -                func = meth.im_func
 | 
| -                testname = '%s.%s' % (meth.im_class.__name__, func.__name__)
 | 
| +                testname = '%s.%s' % (test.__name__, meth.__name__)
 | 
|              elif isinstance(test, types.FunctionType):
 | 
|                  func = test
 | 
|                  testname = func.__name__
 | 
|              elif isinstance(test, types.MethodType):
 | 
| -                func = test.im_func
 | 
| -                testname = '%s.%s' % (test.im_class.__name__, func.__name__)
 | 
| +                cls = test.__self__.__class__
 | 
| +                testname = '%s.%s' % (cls.__name__, test.__name__)
 | 
|              else:
 | 
|                  return True # Not sure when this happens
 | 
| -            if testlib.is_generator(test) and skipgenerator:
 | 
| +            if isgeneratorfunction(test) and skipgenerator:
 | 
|                  return self.does_match_tags(test) # Let inner tests decide at run time
 | 
|          if self._this_is_skipped(testname):
 | 
|              return False # this was explicitly skipped
 | 
| @@ -1025,8 +1003,7 @@
 | 
|      def _collect_tests(self, module):
 | 
|          tests = {}
 | 
|          for obj in vars(module).values():
 | 
| -            if (issubclass(type(obj), (types.ClassType, type)) and
 | 
| -                 issubclass(obj, unittest.TestCase)):
 | 
| +            if isclass(obj) and issubclass(obj, unittest.TestCase):
 | 
|                  classname = obj.__name__
 | 
|                  if classname[0] == '_' or self._this_is_skipped(classname):
 | 
|                      continue
 | 
| 
 |