@@ -64,9 +64,10 @@ def test_named_config_file(self, file_class: FilePathType) -> None:
6464        assert  not  cov .config .branch 
6565        assert  cov .config .data_file  ==  "delete.me" 
6666
67-     def  test_toml_config_file (self ) ->  None :
68-         # A pyproject.toml file will be read into the configuration. 
69-         self .make_file ("pyproject.toml" , """\  
67+     @pytest .mark .parametrize ("filename" , ["pyproject.toml" , ".coveragerc.toml" ]) 
68+     def  test_toml_config_file (self , filename ) ->  None :
69+         # A pyproject.toml and coveragerc.toml will be read into the configuration. 
70+         self .make_file (filename , """\  
7071             # This is just a bogus toml file for testing.
7172            [tool.somethingelse] 
7273            authors = ["Joe D'Ávila <[email protected] >"] @@ -94,9 +95,10 @@ def test_toml_config_file(self) -> None:
9495        assert  cov .config .fail_under  ==  90.5 
9596        assert  cov .config .get_plugin_options ("plugins.a_plugin" ) ==  {"hello" : "world" }
9697
97-     def  test_toml_ints_can_be_floats (self ) ->  None :
98+     @pytest .mark .parametrize ("filename" , ["pyproject.toml" , ".coveragerc.toml" ]) 
99+     def  test_toml_ints_can_be_floats (self , filename ) ->  None :
98100        # Test that our class doesn't reject integers when loading floats 
99-         self .make_file ("pyproject.toml" , """\  
101+         self .make_file (filename , """\  
100102             # This is just a bogus toml file for testing.
101103            [tool.coverage.report] 
102104            fail_under = 90 
@@ -205,7 +207,8 @@ def test_parse_errors(self, bad_config: str, msg: str) -> None:
205207        self .make_file (".coveragerc" , bad_config )
206208        with  pytest .raises (ConfigError , match = msg ):
207209            coverage .Coverage ()
208- 
210+     
211+     @pytest .mark .parametrize ("filename" , ["pyproject.toml" , ".coveragerc.toml" ]) 
209212    @pytest .mark .parametrize ("bad_config, msg" , [ 
210213        ("[tool.coverage.run]\n timid = \" maybe?\" \n " , r"maybe[?]" ), 
211214        ("[tool.coverage.run\n " , None ), 
@@ -223,9 +226,9 @@ def test_parse_errors(self, bad_config: str, msg: str) -> None:
223226        ("[tool.coverage.report]\n precision=1.23" , "not an integer" ), 
224227        ('[tool.coverage.report]\n fail_under="s"' , "couldn't convert to a float" ), 
225228    ]) 
226-     def  test_toml_parse_errors (self , bad_config : str , msg : str ) ->  None :
229+     def  test_toml_parse_errors (self , filename ,  bad_config : str , msg : str ) ->  None :
227230        # Im-parsable values raise ConfigError, with details. 
228-         self .make_file ("pyproject.toml" , bad_config )
231+         self .make_file (filename , bad_config )
229232        with  pytest .raises (ConfigError , match = msg ):
230233            coverage .Coverage ()
231234
@@ -251,9 +254,10 @@ def test_environment_vars_in_config(self) -> None:
251254        assert  cov .config .branch  is  True 
252255        assert  cov .config .exclude_list  ==  ["the_$one" , "anotherZZZ" , "xZZZy" , "xy" , "huh${X}what" ]
253256
254-     def  test_environment_vars_in_toml_config (self ) ->  None :
257+     @pytest .mark .parametrize ("filename" , ["pyproject.toml" , ".coveragerc.toml" ]) 
258+     def  test_environment_vars_in_toml_config (self , filename ) ->  None :
255259        # Config files can have $envvars in them. 
256-         self .make_file ("pyproject.toml" , """\  
260+         self .make_file (filename , """\  
257261             [tool.coverage.run]
258262            data_file = "$DATA_FILE.fooey" 
259263            branch = "$BRANCH" 
@@ -325,9 +329,10 @@ def expanduser(s: str) -> str:
325329        assert  cov .config .exclude_list  ==  ["~/data.file" , "~joe/html_dir" ]
326330        assert  cov .config .paths  ==  {'mapping' : ['/Users/me/src' , '/Users/joe/source' ]}
327331
328-     def  test_tilde_in_toml_config (self ) ->  None :
332+     @pytest .mark .parametrize ("filename" , ["pyproject.toml" , ".coveragerc.toml" ]) 
333+     def  test_tilde_in_toml_config (self , filename ) ->  None :
329334        # Config entries that are file paths can be tilde-expanded. 
330-         self .make_file ("pyproject.toml" , """\  
335+         self .make_file (filename , """\  
331336             [tool.coverage.run]
332337            data_file = "~/data.file" 
333338
@@ -441,22 +446,14 @@ def test_unknown_option(self) -> None:
441446        msg  =  r"Unrecognized option '\[run\] xyzzy=' in config file .coveragerc" 
442447        with  pytest .warns (CoverageWarning , match = msg ):
443448            _  =  coverage .Coverage ()
444- 
445-     def  test_unknown_option_toml (self ) ->  None :
446-         self .make_file ("pyproject.toml" , """\  
449+     
450+     @pytest .mark .parametrize ("filename" , ["pyproject.toml" , ".coveragerc.toml" ]) 
451+     def  test_unknown_option_toml (self , filename ) ->  None :
452+         self .make_file (filename , """\  
447453             [tool.coverage.run]
448454            xyzzy = 17 
449455            """ )
450-         msg  =  r"Unrecognized option '\[tool.coverage.run\] xyzzy=' in config file pyproject.toml" 
451-         with  pytest .warns (CoverageWarning , match = msg ):
452-             _  =  coverage .Coverage ()
453- 
454-     def  test_misplaced_option (self ) ->  None :
455-         self .make_file (".coveragerc" , """\  
456-              [report]
457-             branch = True 
458-             """ )
459-         msg  =  r"Unrecognized option '\[report\] branch=' in config file .coveragerc" 
456+         msg  =  f"Unrecognized option '\\ [tool.coverage.run\\ ] xyzzy=' in config file { filename }  " 
460457        with  pytest .warns (CoverageWarning , match = msg ):
461458            _  =  coverage .Coverage ()
462459
@@ -468,7 +465,7 @@ def test_unknown_option_in_other_ini_file(self) -> None:
468465        msg  =  r"Unrecognized option '\[coverage:run\] huh=' in config file setup.cfg" 
469466        with  pytest .warns (CoverageWarning , match = msg ):
470467            _  =  coverage .Coverage ()
471- 
468+      
472469    def  test_exceptions_from_missing_things (self ) ->  None :
473470        self .make_file ("config.ini" , """\  
474471             [run]
@@ -481,8 +478,10 @@ def test_exceptions_from_missing_things(self) -> None:
481478        with  pytest .raises (ConfigError , match = "No option 'foo' in section: 'xyzzy'" ):
482479            config .get ("xyzzy" , "foo" )
483480
484-     def  test_exclude_also (self ) ->  None :
485-         self .make_file ("pyproject.toml" , """\  
481+     
482+     @pytest .mark .parametrize ("filename" , ["pyproject.toml" , ".coveragerc.toml" ]) 
483+     def  test_exclude_also (self , filename ) ->  None :
484+         self .make_file (filename , """\  
486485             [tool.coverage.report]
487486            exclude_also = ["foobar", "raise .*Error"] 
488487            """ )
@@ -775,35 +774,39 @@ def test_no_toml_installed_explicit_toml(self) -> None:
775774                coverage .Coverage (config_file = "cov.toml" )
776775
777776    @pytest .mark .skipif (env .PYVERSION  >=  (3 , 11 ), reason = "Python 3.11 has toml in stdlib" ) 
778-     def  test_no_toml_installed_pyproject_toml (self ) ->  None :
779-         # Can't have coverage config in pyproject.toml without toml installed. 
780-         self .make_file ("pyproject.toml" , """\  
777+     @pytest .mark .parametrize ("filename" , ["pyproject.toml" , ".coveragerc.toml" ]) 
778+     def  test_no_toml_installed_pyproject_toml (self , filename ) ->  None :
779+         # Can't have coverage config in pyproject.toml and .coveragerc.toml without toml installed. 
780+         self .make_file (filename , """\  
781781             # A toml file!
782782            [tool.coverage.run] 
783783            xyzzy = 17 
784784            """ )
785785        with  mock .patch .object (coverage .tomlconfig , "has_tomllib" , False ):
786-             msg  =  "Can't read 'pyproject.toml ' without TOML support" 
786+             msg  =  "Can't read '{filename} ' without TOML support" 
787787            with  pytest .raises (ConfigError , match = msg ):
788788                coverage .Coverage ()
789789
790790    @pytest .mark .skipif (env .PYVERSION  >=  (3 , 11 ), reason = "Python 3.11 has toml in stdlib" ) 
791-     def  test_no_toml_installed_pyproject_toml_shorter_syntax (self ) ->  None :
791+     @pytest .mark .parametrize ("filename" , ["pyproject.toml" , ".coveragerc.toml" ]) 
792+     def  test_no_toml_installed_pyproject_toml_shorter_syntax (self , filename ) ->  None :
792793        # Can't have coverage config in pyproject.toml without toml installed. 
793-         self .make_file ("pyproject.toml" , """\  
794+         self .make_file (filename , """\  
794795             # A toml file!
795796            [tool.coverage] 
796797            run.parallel = true 
797798            """ )
798799        with  mock .patch .object (coverage .tomlconfig , "has_tomllib" , False ):
799-             msg  =  "Can't read 'pyproject.toml ' without TOML support" 
800+             msg  =  "Can't read '{filename} ' without TOML support" 
800801            with  pytest .raises (ConfigError , match = msg ):
801802                coverage .Coverage ()
802803
804+ 
803805    @pytest .mark .skipif (env .PYVERSION  >=  (3 , 11 ), reason = "Python 3.11 has toml in stdlib" ) 
804-     def  test_no_toml_installed_pyproject_no_coverage (self ) ->  None :
806+     @pytest .mark .parametrize ("filename" , ["pyproject.toml" , ".coveragerc.toml" ]) 
807+     def  test_no_toml_installed_pyproject_no_coverage (self , filename ) ->  None :
805808        # It's ok to have non-coverage pyproject.toml without toml installed. 
806-         self .make_file ("pyproject.toml" , """\  
809+         self .make_file (filename , """\  
807810             # A toml file!
808811            [tool.something] 
809812            xyzzy = 17 
@@ -814,17 +817,39 @@ def test_no_toml_installed_pyproject_no_coverage(self) -> None:
814817            assert  not  cov .config .timid 
815818            assert  not  cov .config .branch 
816819            assert  cov .config .data_file  ==  ".coverage" 
817- 
818-     def  test_exceptions_from_missing_toml_things (self ) ->  None :
819-         self .make_file ("pyproject.toml" , """\  
820+     
821+     @pytest .mark .parametrize ("filename" , ["pyproject.toml" , ".coveragerc.toml" ]) 
822+     def  test_exceptions_from_missing_toml_things (self , filename ) ->  None :
823+         self .make_file (filename , """\  
820824             [tool.coverage.run]
821825            branch = true 
822826            """ )
823827        config  =  TomlConfigParser (False )
824-         config .read ("pyproject.toml" )
828+         config .read (filename )
825829        with  pytest .raises (ConfigError , match = "No section: 'xyzzy'" ):
826830            config .options ("xyzzy" )
827831        with  pytest .raises (ConfigError , match = "No section: 'xyzzy'" ):
828832            config .get ("xyzzy" , "foo" )
829833        with  pytest .raises (ConfigError , match = "No option 'foo' in section: 'tool.coverage.run'" ):
830834            config .get ("run" , "foo" )
835+             
836+     def  test_coveragerc_toml_priority (self ) ->  None :
837+         """Test that .coveragerc.toml has priority over pyproject.toml.""" 
838+         self .make_file (".coveragerc.toml" , """\  
839+              [tool.coverage.run]
840+             timid = true 
841+             data_file = ".toml-data.dat" 
842+             branch = true 
843+             """ )
844+     
845+         self .make_file ("pyproject.toml" , """\  
846+              [tool.coverage.run]
847+             timid = false 
848+             data_file = "pyproject-data.dat" 
849+             branch = false 
850+             """ )
851+         cov  =  coverage .Coverage ()
852+     
853+         assert  cov .config .timid  is  True 
854+         assert  cov .config .data_file  ==  ".toml-data.dat" 
855+         assert  cov .config .branch  is  True 
0 commit comments