Hello community, here is the log from the commit of package python3-coverage for openSUSE:Factory checked in at 2015-12-01 09:16:36 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python3-coverage (Old) and /work/SRC/openSUSE:Factory/.python3-coverage.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python3-coverage" Changes: -------- --- /work/SRC/openSUSE:Factory/python3-coverage/python3-coverage.changes 2015-11-16 18:51:15.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.python3-coverage.new/python3-coverage.changes 2015-12-01 09:16:38.000000000 +0100 @@ -1,0 +2,16 @@ +Wed Nov 25 07:11:38 UTC 2015 - a...@gmx.de + +- update to version 4.0.3: + * Fixed a mysterious problem that manifested in different ways: + sometimes hanging the process (issue 420), sometimes making + database connections fail (issue 445). + * The XML report now has correct <source> elements when using a + --source= option somewhere besides the current directory. This + fixes issue 439. Thanks, Arcady Ivanov. + * Fixed an unusual edge case of detecting source encodings, + described in issue 443. + * Help messages that mention the command to use now properly use the + actual command name, which might be different than + "coverage". Thanks to Ben Finney, this closes issue 438. + +------------------------------------------------------------------- Old: ---- coverage-4.0.2.tar.gz New: ---- coverage-4.0.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python3-coverage.spec ++++++ --- /var/tmp/diff_new_pack.wGaEIs/_old 2015-12-01 09:16:39.000000000 +0100 +++ /var/tmp/diff_new_pack.wGaEIs/_new 2015-12-01 09:16:39.000000000 +0100 @@ -17,7 +17,7 @@ Name: python3-coverage -Version: 4.0.2 +Version: 4.0.3 Release: 0 Url: http://nedbatchelder.com/code/coverage/%{version} Summary: Code coverage measurement for Python ++++++ coverage-4.0.2.tar.gz -> coverage-4.0.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/coverage-4.0.2/AUTHORS.txt new/coverage-4.0.3/AUTHORS.txt --- old/coverage-4.0.2/AUTHORS.txt 2015-08-26 15:31:15.000000000 +0200 +++ new/coverage-4.0.3/AUTHORS.txt 2015-11-22 15:45:07.000000000 +0100 @@ -7,6 +7,7 @@ Alex Gaynor Alexander Todorov Anthony Sottile +Arcadiy Ivanov Ben Finney Bill Hart Brandon Rhodes diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/coverage-4.0.2/CHANGES.rst new/coverage-4.0.3/CHANGES.rst --- old/coverage-4.0.2/CHANGES.rst 2015-11-04 11:08:12.000000000 +0100 +++ new/coverage-4.0.3/CHANGES.rst 2015-11-24 12:55:29.000000000 +0100 @@ -6,6 +6,31 @@ ============================== +Version 4.0.3, 24 November 2015 +------------------------------- + +- Fixed a mysterious problem that manifested in different ways: sometimes + hanging the process (`issue 420`_), sometimes making database connections + fail (`issue 445`_). + +- The XML report now has correct ``<source>`` elements when using a + ``--source=`` option somewhere besides the current directory. This fixes + `issue 439`_. Thanks, Arcady Ivanov. + +- Fixed an unusual edge case of detecting source encodings, described in + `issue 443`_. + +- Help messages that mention the command to use now properly use the actual + command name, which might be different than "coverage". Thanks to Ben Finney, + this closes `issue 438`_. + +.. _issue 420: https://bitbucket.org/ned/coveragepy/issues/420/coverage-40-hangs-indefinitely-on-python27 +.. _issue 438: https://bitbucket.org/ned/coveragepy/issues/438/parameterise-coverage-command-name +.. _issue 439: https://bitbucket.org/ned/coveragepy/issues/439/incorrect-cobertura-file-sources-generated +.. _issue 443: https://bitbucket.org/ned/coveragepy/issues/443/coverage-gets-confused-when-encoding +.. _issue 445: https://bitbucket.org/ned/coveragepy/issues/445/django-app-cannot-connect-to-cassandra + + Version 4.0.2 --- 4 November 2015 --------------------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/coverage-4.0.2/Makefile new/coverage-4.0.3/Makefile --- old/coverage-4.0.2/Makefile 2015-09-20 16:22:27.000000000 +0200 +++ new/coverage-4.0.3/Makefile 2015-11-22 14:19:38.000000000 +0100 @@ -72,6 +72,9 @@ pypi: python setup.py register +build_ext: + python setup.py build_ext + install: python setup.py install diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/coverage-4.0.2/PKG-INFO new/coverage-4.0.3/PKG-INFO --- old/coverage-4.0.2/PKG-INFO 2015-11-04 11:22:56.000000000 +0100 +++ new/coverage-4.0.3/PKG-INFO 2015-11-24 13:05:03.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: coverage -Version: 4.0.2 +Version: 4.0.3 Summary: Code coverage measurement for Python Home-page: https://coverage.readthedocs.org Author: Ned Batchelder and others diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/coverage-4.0.2/coverage/backward.py new/coverage-4.0.3/coverage/backward.py --- old/coverage-4.0.2/coverage/backward.py 2015-09-30 04:06:26.000000000 +0200 +++ new/coverage-4.0.3/coverage/backward.py 2015-11-22 15:35:05.000000000 +0100 @@ -49,6 +49,15 @@ except NameError: range = range +# shlex.quote is new, but there's an undocumented implementation in "pipes", +# who knew!? +try: + from shlex import quote as shlex_quote +except ImportError: + # Useful function, available under a different (undocumented) name + # in Python versions earlier than 3.3. + from pipes import quote as shlex_quote + # A function to iterate listlessly over a dict's items. try: {}.iteritems @@ -142,11 +151,12 @@ PYC_MAGIC_NUMBER = imp.get_magic() -def import_local_file(modname): +def import_local_file(modname, modfile=None): """Import a local file as a module. Opens a file in the current directory named `modname`.py, imports it - as `modname`, and returns the module object. + as `modname`, and returns the module object. `modfile` is the file to + import if it isn't in the current directory. """ try: @@ -154,7 +164,8 @@ except ImportError: SourceFileLoader = None - modfile = modname + '.py' + if modfile is None: + modfile = modname + '.py' if SourceFileLoader: mod = SourceFileLoader(modname, modfile).load_module() else: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/coverage-4.0.2/coverage/cmdline.py new/coverage-4.0.3/coverage/cmdline.py --- old/coverage-4.0.2/coverage/cmdline.py 2015-10-04 16:53:19.000000000 +0200 +++ new/coverage-4.0.3/coverage/cmdline.py 2015-11-22 14:19:38.000000000 +0100 @@ -228,7 +228,6 @@ if usage: usage = "%prog " + usage super(CmdOptionParser, self).__init__( - prog="coverage %s" % action, usage=usage, description=description, ) @@ -242,6 +241,14 @@ # results, and they will compare equal to objects. return (other == "<CmdOptionParser:%s>" % self.cmd) + def get_prog_name(self): + """Override of an undocumented function in optparse.OptionParser.""" + program_name = super(CmdOptionParser, self).get_prog_name() + + # Include the sub-command for this parser as part of the command. + return "%(command)s %(subcommand)s" % {'command': program_name, 'subcommand': self.cmd} + + GLOBAL_ARGS = [ Opts.debug, Opts.help, @@ -390,6 +397,17 @@ self.coverage = None + self.program_name = os.path.basename(sys.argv[0]) + if env.WINDOWS: + # entry_points={'console_scripts':...} on Windows makes files + # called coverage.exe, coverage3.exe, and coverage-3.5.exe. These + # invoke coverage-script.py, coverage3-script.py, and + # coverage-3.5-script.py. argv[0] is the .py file, but we want to + # get back to the original form. + auto_suffix = "-script.py" + if self.program_name.endswith(auto_suffix): + self.program_name = self.program_name[:-len(auto_suffix)] + def command_line(self, argv): """The bulk of the command line interface to coverage.py. @@ -523,13 +541,15 @@ assert error or topic or parser if error: print(error) - print("Use 'coverage help' for help.") + print("Use '%s help' for help." % (self.program_name,)) elif parser: print(parser.format_help().strip()) else: + help_params = dict(self.covpkg.__dict__) + help_params['program_name'] = self.program_name help_msg = textwrap.dedent(HELP_TOPICS.get(topic, '')).strip() if help_msg: - print(help_msg % self.covpkg.__dict__) + print(help_msg % help_params) else: print("Don't know topic %r" % topic) @@ -682,7 +702,7 @@ Coverage.py, version %(__version__)s Measure, collect, and report on code coverage in Python programs. - usage: coverage <command> [options] [args] + usage: %(program_name)s <command> [options] [args] Commands: annotate Annotate source files with execution information. @@ -694,12 +714,12 @@ run Run a Python program and measure code execution. xml Create an XML report of coverage results. - Use "coverage help <command>" for detailed help on any command. + Use "%(program_name)s help <command>" for detailed help on any command. For full documentation, see %(__url__)s """, 'minimum_help': """\ - Code coverage for Python. Use 'coverage help' for help. + Code coverage for Python. Use '%(program_name)s help' for help. """, 'version': """\ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/coverage-4.0.2/coverage/ctracer/datastack.c new/coverage-4.0.3/coverage/ctracer/datastack.c --- old/coverage-4.0.2/coverage/ctracer/datastack.c 2015-09-30 04:06:26.000000000 +0200 +++ new/coverage-4.0.3/coverage/ctracer/datastack.c 2015-11-24 12:06:53.000000000 +0100 @@ -26,10 +26,10 @@ { pdata_stack->depth++; if (pdata_stack->depth >= pdata_stack->alloc) { - STATS( pstats->stack_reallocs++; ) /* We've outgrown our data_stack array: make it bigger. */ int bigger = pdata_stack->alloc + STACK_DELTA; DataStackEntry * bigger_data_stack = PyMem_Realloc(pdata_stack->stack, bigger * sizeof(DataStackEntry)); + STATS( pstats->stack_reallocs++; ) if (bigger_data_stack == NULL) { PyErr_NoMemory(); pdata_stack->depth--; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/coverage-4.0.2/coverage/ctracer/tracer.c new/coverage-4.0.3/coverage/ctracer/tracer.c --- old/coverage-4.0.2/coverage/ctracer/tracer.c 2015-11-02 03:52:28.000000000 +0100 +++ new/coverage-4.0.3/coverage/ctracer/tracer.c 2015-11-22 14:19:38.000000000 +0100 @@ -64,24 +64,11 @@ CTracer_init(CTracer *self, PyObject *args_unused, PyObject *kwds_unused) { int ret = RET_ERROR; - PyObject * weakref = NULL; if (DataStack_init(&self->stats, &self->data_stack) < 0) { goto error; } - weakref = PyImport_ImportModule("weakref"); - if (weakref == NULL) { - goto error; - } - STATS( self->stats.pycalls++; ) - self->data_stack_index = PyObject_CallMethod(weakref, "WeakKeyDictionary", NULL); - Py_XDECREF(weakref); - - if (self->data_stack_index == NULL) { - goto error; - } - self->pdata_stack = &self->data_stack; self->cur_entry.last_line = -1; @@ -212,6 +199,22 @@ if (self->concur_id_func != Py_None) { int the_index = 0; + if (self->data_stack_index == NULL) { + PyObject * weakref = NULL; + + weakref = PyImport_ImportModule("weakref"); + if (weakref == NULL) { + goto error; + } + STATS( self->stats.pycalls++; ) + self->data_stack_index = PyObject_CallMethod(weakref, "WeakKeyDictionary", NULL); + Py_XDECREF(weakref); + + if (self->data_stack_index == NULL) { + goto error; + } + } + STATS( self->stats.pycalls++; ) co_obj = PyObject_CallObject(self->concur_id_func, NULL); if (co_obj == NULL) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/coverage-4.0.2/coverage/phystokens.py new/coverage-4.0.3/coverage/phystokens.py --- old/coverage-4.0.2/coverage/phystokens.py 2015-10-18 16:50:23.000000000 +0200 +++ new/coverage-4.0.3/coverage/phystokens.py 2015-11-22 14:19:38.000000000 +0100 @@ -153,7 +153,7 @@ generate_tokens = CachedTokenizer().generate_tokens -COOKIE_RE = re.compile(r"^\s*#.*coding[:=]\s*([-\w.]+)", flags=re.MULTILINE) +COOKIE_RE = re.compile(r"^[ \t]*#.*coding[:=][ \t]*([-\w.]+)", flags=re.MULTILINE) @contract(source='bytes') def _source_encoding_py2(source): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/coverage-4.0.2/coverage/version.py new/coverage-4.0.3/coverage/version.py --- old/coverage-4.0.2/coverage/version.py 2015-11-04 11:05:27.000000000 +0100 +++ new/coverage-4.0.3/coverage/version.py 2015-11-22 14:19:38.000000000 +0100 @@ -5,7 +5,7 @@ # This file is exec'ed in setup.py, don't import anything! # Same semantics as sys.version_info. -version_info = (4, 0, 2, 'final', 0) +version_info = (4, 0, 3, 'final', 0) def _make_version(major, minor, micro, releaselevel, serial): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/coverage-4.0.2/coverage/xmlreport.py new/coverage-4.0.3/coverage/xmlreport.py --- old/coverage-4.0.2/coverage/xmlreport.py 2015-10-19 04:25:34.000000000 +0200 +++ new/coverage-4.0.3/coverage/xmlreport.py 2015-11-22 18:48:16.000000000 +0100 @@ -4,6 +4,7 @@ """XML reporting for coverage.py""" import os +import os.path import sys import time import xml.dom.minidom @@ -38,6 +39,10 @@ super(XmlReporter, self).__init__(coverage, config) self.source_paths = set() + if config.source: + for src in config.source: + if os.path.exists(src): + self.source_paths.add(files.canonical_filename(src)) self.packages = {} self.xml_out = None self.has_arcs = coverage.data.has_arcs() @@ -141,9 +146,10 @@ parts = dirname.split("/") dirname = "/".join(parts[:self.config.xml_package_depth]) package_name = dirname.replace("/", ".") - className = fr.relative_filename() + rel_name = fr.relative_filename() - self.source_paths.add(files.relative_directory().rstrip('/')) + if rel_name != fr.filename: + self.source_paths.add(fr.filename[:-len(rel_name)].rstrip(r"\/")) package = self.packages.setdefault(package_name, [{}, 0, 0, 0, 0]) xclass = self.xml_out.createElement("class") @@ -201,7 +207,7 @@ branch_rate = "0" xclass.setAttribute("branch-rate", branch_rate) - package[0][className] = xclass + package[0][rel_name] = xclass package[1] += class_hits package[2] += class_lines package[3] += class_br_hits diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/coverage-4.0.2/coverage.egg-info/PKG-INFO new/coverage-4.0.3/coverage.egg-info/PKG-INFO --- old/coverage-4.0.2/coverage.egg-info/PKG-INFO 2015-11-04 11:22:55.000000000 +0100 +++ new/coverage-4.0.3/coverage.egg-info/PKG-INFO 2015-11-24 13:05:01.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: coverage -Version: 4.0.2 +Version: 4.0.3 Summary: Code coverage measurement for Python Home-page: https://coverage.readthedocs.org Author: Ned Batchelder and others diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/coverage-4.0.2/doc/changes.rst new/coverage-4.0.3/doc/changes.rst --- old/coverage-4.0.2/doc/changes.rst 2015-11-04 11:09:17.000000000 +0100 +++ new/coverage-4.0.3/doc/changes.rst 2015-11-24 12:58:49.000000000 +0100 @@ -35,6 +35,8 @@ .. :history: 20150822T092800, updated for 4.0b2 .. :history: 20150919T072700, updated for 4.0 .. :history: 20151013T103000, updated for 4.0.1 +.. :history: 20151104T050900, updated for 4.0.2 +.. :history: 20151124T065800, updated for 4.0.3 These are the major changes for coverage.py. For a more complete change @@ -44,6 +46,32 @@ .. module:: coverage +.. _changes_403: + +Version 4.0.3 --- 24 November 2015 +---------------------------------- + +- Fixed a mysterious problem that manifested in different ways: sometimes + hanging the process (`issue 420`_), sometimes making database connections + fail (`issue 445`_). + +- The XML report now has correct ``<source>`` elements when using a + ``--source=`` option somewhere besides the current directory. This fixes + `issue 439`_. Thanks, Arcady Ivanov. + +- Fixed an unusual edge case of detecting source encodings, described in + `issue 443`_. + +- Help messages that mention the command to use now properly use the actual + command name, which might be different than "coverage". Thanks to Ben Finney, + this closes `issue 438`_. + +.. _issue 420: https://bitbucket.org/ned/coveragepy/issues/420/coverage-40-hangs-indefinitely-on-python27 +.. _issue 438: https://bitbucket.org/ned/coveragepy/issues/438/parameterise-coverage-command-name +.. _issue 439: https://bitbucket.org/ned/coveragepy/issues/439/incorrect-cobertura-file-sources-generated +.. _issue 443: https://bitbucket.org/ned/coveragepy/issues/443/coverage-gets-confused-when-encoding +.. _issue 445: https://bitbucket.org/ned/coveragepy/issues/445/django-app-cannot-connect-to-cassandra + .. _changes_402: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/coverage-4.0.2/doc/conf.py new/coverage-4.0.3/doc/conf.py --- old/coverage-4.0.2/doc/conf.py 2015-11-04 11:10:32.000000000 +0100 +++ new/coverage-4.0.3/doc/conf.py 2015-11-24 13:00:17.000000000 +0100 @@ -58,7 +58,7 @@ # The short X.Y version. version = '4.0' # The full version, including alpha/beta/rc tags. -release = '4.0.2' +release = '4.0.3' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/coverage-4.0.2/doc/index.rst new/coverage-4.0.3/doc/index.rst --- old/coverage-4.0.2/doc/index.rst 2015-11-04 11:10:06.000000000 +0100 +++ new/coverage-4.0.3/doc/index.rst 2015-11-24 12:59:13.000000000 +0100 @@ -42,6 +42,7 @@ .. :history: 20150918T072700, Updated for 4.0 .. :history: 20151013T103200, Updated for 4.0.1 .. :history: 20151104T050900, updated for 4.0.2 +.. :history: 20151124T065900, updated for 4.0.3 Coverage.py is a tool for measuring code coverage of Python programs. It @@ -54,7 +55,7 @@ .. ifconfig:: not prerelease - The latest version is coverage.py 4.0.2, released 4 November 2015. + The latest version is coverage.py 4.0.3, released 24 November 2015. It is supported on: * Python versions 2.6, 2.7, 3.3, 3.4, and 3.5 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/coverage-4.0.2/howto.txt new/coverage-4.0.3/howto.txt --- old/coverage-4.0.2/howto.txt 2015-11-04 11:22:03.000000000 +0100 +++ new/coverage-4.0.3/howto.txt 2015-11-24 12:54:31.000000000 +0100 @@ -1,10 +1,5 @@ * Release checklist -- Test on: - - Windows - - Ubuntu - - Mac - - Pythons 2.6, 2.7, 3.3, 3.4, 3.5 - Version number in coverage/version.py version_info = (4, 0, 2, 'alpha', 1) version_info = (4, 0, 2, 'beta', 1) @@ -48,7 +43,7 @@ - $ make wheel - Windows kits - $ hg push - - wait about 35 minutes for Appveyor to build kits. + - wait about an hour for Appveyor to build kits. - $ make download_appveyor - examine the dist directory, and remove anything that looks malformed. - Update PyPi: @@ -62,11 +57,11 @@ - Update nedbatchelder.com - Blog post? - Update readthedocs - - Coverage / versions + - visit https://readthedocs.org/projects/coverage/versions/ - find the latest tag in the inactive list, edit it, make it active. - IF NOT BETA: - visit https://readthedocs.org/dashboard/coverage/advanced/ - - change the default version + - change the default version to the new version - Update bitbucket: - Issue tracker should get new version number in picker. # Note: don't delete old version numbers: it marks changes on the tickets diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/coverage-4.0.2/tests/coveragetest.py new/coverage-4.0.3/tests/coveragetest.py --- old/coverage-4.0.2/tests/coveragetest.py 2015-11-02 02:04:05.000000000 +0100 +++ new/coverage-4.0.3/tests/coveragetest.py 2015-11-22 15:34:42.000000000 +0100 @@ -15,7 +15,7 @@ import coverage from coverage.backunittest import TestCase -from coverage.backward import StringIO, import_local_file, string_class +from coverage.backward import StringIO, import_local_file, string_class, shlex_quote from coverage.cmdline import CoverageScript from coverage.debug import _TEST_NAME_FILE, DebugControl from coverage.test_helpers import ( @@ -81,20 +81,22 @@ if os.path.exists("__pycache__"): shutil.rmtree("__pycache__") - def import_local_file(self, modname): + def import_local_file(self, modname, modfile=None): """Import a local file as a module. Opens a file in the current directory named `modname`.py, imports it - as `modname`, and returns the module object. + as `modname`, and returns the module object. `modfile` is the file to + import if it isn't in the current directory. """ - return import_local_file(modname) + return import_local_file(modname, modfile) - def start_import_stop(self, cov, modname): + def start_import_stop(self, cov, modname, modfile=None): """Start coverage, import a file, then stop coverage. `cov` is started and stopped, with an `import_local_file` of - `modname` in the middle. + `modname` in the middle. `modfile` is the file to import as `modname` + if it isn't in the current directory. The imported module is returned. @@ -102,7 +104,7 @@ cov.start() try: # pragma: nested # Import the Python file, executing it. - mod = self.import_local_file(modname) + mod = self.import_local_file(modname, modfile) finally: # pragma: nested # Stop coverage.py. cov.stop() @@ -332,25 +334,48 @@ ret_actual = script.command_line(shlex.split(args)) self.assertEqual(ret_actual, ret) + coverage_command = "coverage" + def run_command(self, cmd): - """Run the command-line `cmd` in a sub-process, and print its output. + """Run the command-line `cmd` in a sub-process. + + `cmd` is the command line to invoke in a sub-process. Returns the + combined content of `stdout` and `stderr` output streams from the + sub-process. Use this when you need to test the process behavior of coverage. Compare with `command_line`. - Returns the process' stdout text. + Handles the following command name specially: + + * "python" is replaced with the command name of the current + Python interpreter. + + * "coverage" is replaced with the command name for the main + Coverage.py program. """ - # Running Python sub-processes can be tricky. Use the real name of our - # own executable. So "python foo.py" might get executed as - # "python3.3 foo.py". This is important because Python 3.x doesn't - # install as "python", so you might get a Python 2 executable instead - # if you don't use the executable's basename. - if cmd.startswith("python "): - cmd = os.path.basename(sys.executable) + cmd[6:] + split_commandline = cmd.split(" ", 1) + command_name = split_commandline[0] + command_args = split_commandline[1:] + + if command_name == "python": + # Running a Python interpreter in a sub-processes can be tricky. + # Use the real name of our own executable. So "python foo.py" might + # get executed as "python3.3 foo.py". This is important because + # Python 3.x doesn't install as "python", so you might get a Python + # 2 executable instead if you don't use the executable's basename. + command_name = os.path.basename(sys.executable) + + if command_name == "coverage": + # The invocation requests the Coverage.py program. Substitute the + # actual Coverage.py main command name. + command_name = self.coverage_command + + full_commandline = " ".join([shlex_quote(command_name)] + command_args) - _, output = self.run_command_status(cmd) + _, output = self.run_command_status(full_commandline) return output def run_command_status(self, cmd): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/coverage-4.0.2/tests/test_phystokens.py new/coverage-4.0.3/tests/test_phystokens.py --- old/coverage-4.0.2/tests/test_phystokens.py 2015-10-15 22:37:51.000000000 +0200 +++ new/coverage-4.0.3/tests/test_phystokens.py 2015-11-22 14:19:38.000000000 +0100 @@ -102,6 +102,7 @@ b"#!/usr/bin/python\n# vim: set fileencoding=cp850:\n", b"# This Python file uses this encoding: cp850\n", b"# This file uses a different encoding:\n# coding: cp850\n", + b"\n# coding=cp850\n\n", ] class SourceEncodingTest(CoverageTest): @@ -126,11 +127,6 @@ source = b'def parse(src, encoding=None):\n pass' self.assertEqual(source_encoding(source), DEF_ENCODING) - def test_detect_source_encoding_on_second_line(self): - # A coding declaration should be found despite a first blank line. - source = b"\n# coding=cp850\n\n" - self.assertEqual(source_encoding(source), 'cp850') - def test_dont_detect_source_encoding_on_third_line(self): # A coding declaration doesn't count on the third line. source = b"\n\n# coding=cp850\n\n" @@ -160,6 +156,18 @@ for source in ENCODING_DECLARATION_SOURCES: neutered = neuter_encoding_declaration(source.decode("ascii")) neutered = neutered.encode("ascii") + + # The neutered source should have the same number of lines. + source_lines = source.splitlines() + neutered_lines = neutered.splitlines() + self.assertEqual(len(source_lines), len(neutered_lines)) + + # Only one of the lines should be different. + lines_different = sum( + int(nline != sline) for nline, sline in zip(neutered_lines, source_lines) + ) + self.assertEqual(lines_different, 1) + self.assertEqual( source_encoding(neutered), DEF_ENCODING, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/coverage-4.0.2/tests/test_process.py new/coverage-4.0.3/tests/test_process.py --- old/coverage-4.0.2/tests/test_process.py 2015-10-31 16:56:19.000000000 +0100 +++ new/coverage-4.0.3/tests/test_process.py 2015-11-22 14:19:38.000000000 +0100 @@ -757,6 +757,17 @@ out = self.run_command(cmd) self.assertIn("Code coverage for Python", out) + def test_aliases_used_in_messages(self): + cmds = [ + "coverage", + "coverage%d" % sys.version_info[0], + "coverage-%d.%d" % sys.version_info[:2], + ] + for cmd in cmds: + out = self.run_command("%s foobar" % cmd) + self.assertIn("Unknown command: 'foobar'", out) + self.assertIn("Use '%s help' for help" % cmd, out) + class PydocTest(CoverageTest): """Test that pydoc can get our information.""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/coverage-4.0.2/tests/test_xml.py new/coverage-4.0.3/tests/test_xml.py --- old/coverage-4.0.2/tests/test_xml.py 2015-09-05 03:55:14.000000000 +0200 +++ new/coverage-4.0.3/tests/test_xml.py 2015-11-22 18:48:52.000000000 +0100 @@ -4,9 +4,11 @@ """Tests for XML reports from coverage.py.""" import os +import os.path import re import coverage +from coverage.files import abs_file from tests.coveragetest import CoverageTest from tests.goldtest import CoverageGoldTest @@ -141,6 +143,47 @@ init_line = re_line(xml, 'filename="sub/__init__.py"') self.assertIn('line-rate="1"', init_line) + def assert_source(self, xml, src): + """Assert that the XML has a <source> element with `src`.""" + src = abs_file(src) + self.assertRegex(xml, r'<source>\s*{0}\s*</source>'.format(re.escape(src))) + + def test_curdir_source(self): + # With no source= option, the XML report should explain that the source + # is in the current directory. + cov = self.run_doit() + cov.xml_report(outfile="-") + xml = self.stdout() + self.assert_source(xml, ".") + self.assertEqual(xml.count('<source>'), 1) + + def test_deep_source(self): + # When using source=, the XML report needs to mention those directories + # in the <source> elements. + # https://bitbucket.org/ned/coveragepy/issues/439/incorrect-cobertura-file-sources-generated + self.make_file("src/main/foo.py", "a = 1") + self.make_file("also/over/there/bar.py", "b = 2") + cov = coverage.Coverage(source=["src/main", "also/over/there", "not/really"]) + cov.start() + mod_foo = self.import_local_file("foo", "src/main/foo.py") + mod_bar = self.import_local_file("bar", "also/over/there/bar.py") + cov.stop() + cov.xml_report([mod_foo, mod_bar], outfile="-") + xml = self.stdout() + + self.assert_source(xml, "src/main") + self.assert_source(xml, "also/over/there") + self.assertEqual(xml.count('<source>'), 2) + + self.assertIn( + '<class branch-rate="0" complexity="0" filename="foo.py" line-rate="1" name="foo.py">', + xml + ) + self.assertIn( + '<class branch-rate="0" complexity="0" filename="bar.py" line-rate="1" name="bar.py">', + xml + ) + class XmlPackageStructureTest(XmlTestHelpers, CoverageTest): """Tests about the package structure reported in the coverage.xml file.""" @@ -272,7 +315,7 @@ import a # pragma: nested cov.stop() # pragma: nested cov.xml_report(a, outfile="../out/xml_1/coverage.xml") - source_path = coverage.files.relative_directory().rstrip('/') + source_path = coverage.files.relative_directory().rstrip(r"\/") compare("gold_x_xml", "out/xml_1", scrubs=[ (r' timestamp="\d+"', ' timestamp="TIMESTAMP"'), @@ -291,7 +334,7 @@ import a # pragma: nested cov.stop() # pragma: nested cov.xml_report(a) - source_path = coverage.files.relative_directory().rstrip('/') + source_path = coverage.files.relative_directory().rstrip(r"\/") compare("gold_x_xml", "out/xml_2", scrubs=[ (r' timestamp="\d+"', ' timestamp="TIMESTAMP"'), @@ -310,7 +353,7 @@ import y # pragma: nested cov.stop() # pragma: nested cov.xml_report(y, outfile="../out/y_xml_branch/coverage.xml") - source_path = coverage.files.relative_directory().rstrip('/') + source_path = coverage.files.relative_directory().rstrip(r"\/") compare("gold_y_xml_branch", "out/y_xml_branch", scrubs=[ (r' timestamp="\d+"', ' timestamp="TIMESTAMP"'),