Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: generate xml report packages correctly on windows #1574

Merged
merged 3 commits into from
Mar 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion coverage/xmlreport.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ def xml_file(self, fr: FileReporter, analysis: Analysis, has_arcs: bool) -> None
rel_name = filename[len(source_path)+1:]
break
else:
rel_name = fr.relative_filename()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the for loop is run, the rel_name is generated from filename which is already converted from backslash to slash in line 177

When the else branch is run, rel_name is generated from the FileReporter which needs the conversion

rel_name = fr.relative_filename().replace("\\", "/")
self.source_paths.add(fr.filename[:-len(rel_name)].rstrip(r"\/"))

dirname = os.path.dirname(rel_name) or "."
Expand Down
33 changes: 33 additions & 0 deletions tests/test_xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,39 @@ def test_accented_directory(self) -> None:
"name": "â",
}

def test_no_duplicate_packages(self) -> None:
self.make_file(
"namespace/package/__init__.py",
"from . import sample; from . import test; from .subpackage import test"
)
self.make_file("namespace/package/sample.py", "print('package.sample')")
self.make_file("namespace/package/test.py", "print('package.test')")
self.make_file("namespace/package/subpackage/test.py", "print('package.subpackage.test')")

# no source path passed to coverage!
# problem occurs when they are dynamically generated during xml report
cov = coverage.Coverage()

cov.start()
import_local_file("foo", "namespace/package/__init__.py") # pragma: nested
cov.stop() # pragma: nested

cov.xml_report()

dom = ElementTree.parse("coverage.xml")

# only two packages should be present
packages = dom.findall(".//package")
assert len(packages) == 2

# one of them is namespace.package
named_package = dom.findall(".//package[@name='namespace.package']")
assert len(named_package) == 1

# the other one namespace.package.subpackage
named_sub_package = dom.findall(".//package[@name='namespace.package.subpackage']")
assert len(named_sub_package) == 1


def unbackslash(v: Any) -> Any:
"""Find strings in `v`, and replace backslashes with slashes throughout."""
Expand Down