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"'),


Reply via email to