From 7f68a21d4ba330cac84afadfbadb4f1ab750637e Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Sun, 1 Dec 2019 14:27:30 -0500 Subject: [PATCH] The [paths] setting is ordered. #649 --- CHANGES.rst | 5 +++++ coverage/config.py | 7 +++++-- doc/config.rst | 3 +++ tests/test_api.py | 43 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 59c89f6da..e58ca9e65 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -33,12 +33,17 @@ Unreleased fixes `issue 745`_ (about not being able to run unittest tests that spawn subprocesses), and `issue 838`_, which described the problem directly. +- The ``[paths]`` configuration section is now ordered. If you specify more + than one list of patterns, the first one that matches will be used. Fixes + `issue 649`_. + - The :func:`.coverage.numbits.register_sqlite_functions` function now also registers `numbits_to_nums` for use in SQLite queries. Thanks, Simon Willison. - Python 3.9a1 is supported. +.. _issue 649: https://github.com/nedbat/coveragepy/issues/649 .. _issue 745: https://github.com/nedbat/coveragepy/issues/745 .. _issue 838: https://github.com/nedbat/coveragepy/issues/838 diff --git a/coverage/config.py b/coverage/config.py index 997fc0366..6372f4c05 100644 --- a/coverage/config.py +++ b/coverage/config.py @@ -226,7 +226,7 @@ def __init__(self): self.json_show_contexts = False # Defaults for [paths] - self.paths = {} + self.paths = collections.OrderedDict() # Options for plugins self.plugin_options = {} @@ -536,6 +536,9 @@ def read_coverage_config(config_file, **kwargs): config.data_file = os.path.expanduser(config.data_file) config.html_dir = os.path.expanduser(config.html_dir) config.xml_output = os.path.expanduser(config.xml_output) - config.paths = {k: [os.path.expanduser(f) for f in v] for k, v in config.paths.items()} + config.paths = collections.OrderedDict( + (k, [os.path.expanduser(f) for f in v]) + for k, v in config.paths.items() + ) return config diff --git a/doc/config.rst b/doc/config.rst index 052bb023c..8277cc76d 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -238,6 +238,9 @@ In this example, data collected for "/jenkins/build/1234/src/module.py" will be combined with data for "c:\myproj\src\module.py", and will be reported against the source file found at "src/module.py". +If you specify more than one list of paths, they will be considered in order. +The first list that has a match will be used. + See :ref:`cmd_combining` for more information. diff --git a/tests/test_api.py b/tests/test_api.py index eb022ae36..228f01475 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -425,6 +425,49 @@ def test_combining_with_a_used_coverage(self): cov.combine() self.check_code1_code2(cov) + def test_ordered_combine(self): + # https://github.com/nedbat/coveragepy/issues/649 + # The order of the [paths] setting matters + def make_data_file(): + data = coverage.CoverageData(".coverage.1") + data.add_lines({os.path.abspath('ci/girder/g1.py'): dict.fromkeys(range(10))}) + data.add_lines({os.path.abspath('ci/girder/plugins/p1.py'): dict.fromkeys(range(10))}) + data.write() + + def get_combined_filenames(): + cov = coverage.Coverage() + cov.combine() + cov.save() + data = cov.get_data() + filenames = {os.path.relpath(f).replace("\\", "/") for f in data.measured_files()} + return filenames + + # Case 1: get the order right. + make_data_file() + self.make_file(".coveragerc", """\ + [paths] + plugins = + plugins/ + ci/girder/plugins/ + girder = + girder/ + ci/girder/ + """) + assert get_combined_filenames() == {'girder/g1.py', 'plugins/p1.py'} + + # Case 2: get the order wrong. + make_data_file() + self.make_file(".coveragerc", """\ + [paths] + girder = + girder/ + ci/girder/ + plugins = + plugins/ + ci/girder/plugins/ + """) + assert get_combined_filenames() == {'girder/g1.py', 'girder/plugins/p1.py'} + def test_warnings(self): self.make_file("hello.py", """\ import sys, os