diff --git a/project_summarizer/cobertura_plugin.py b/project_summarizer/cobertura_plugin.py
index ef42830..73e2a89 100644
--- a/project_summarizer/cobertura_plugin.py
+++ b/project_summarizer/cobertura_plugin.py
@@ -20,6 +20,10 @@ class CoberturaPlugin(ProjectSummarizerPlugin):
     __COMMAND_LINE_ARGUMENT = "--cobertura"
     __COMMAND_LINE_OPTION = "cobertura_coverage_file"
 
+    __COVERAGE_PY_SIGNATURE = (
+        "<!-- Generated by coverage.py: https://coverage.readthedocs.io -->"
+    )
+
     def __init__(self):
         super().__init__()
         self.__output_path = os.path.join(self.REPORT_PUBLISH_PATH, "coverage.json")
@@ -49,6 +53,28 @@ class CoberturaPlugin(ProjectSummarizerPlugin):
             CoberturaPlugin.__COMMAND_LINE_OPTION,
         )
 
+    @classmethod
+    def __calculate_coverage_provider(cls, report_file):
+
+        line_count = 0
+        combined_lines = None
+        with open(report_file, "rt", encoding="utf-8") as infile:
+            next_line = infile.readline()
+            while next_line and next_line.strip() != "<sources>" and line_count < 10:
+                combined_lines = (
+                    f"{combined_lines}\n{next_line[:-1]}"
+                    if combined_lines is not None
+                    else next_line[:-1]
+                )
+                next_line = infile.readline()
+                line_count += 1
+
+        return (
+            "Coverage.py"
+            if CoberturaPlugin.__COVERAGE_PY_SIGNATURE in combined_lines
+            else "Unknown"
+        )
+
     def generate_report(self, only_changes, report_file):
         """
         Generate the report and display it.
@@ -57,8 +83,11 @@ class CoberturaPlugin(ProjectSummarizerPlugin):
         cobertura_document = self.load_xml_docment(
             report_file, "coverage", "test coverage", "Cobertura"
         )
+        coverage_provider_name = self.__calculate_coverage_provider(report_file)
 
-        new_stats = self.__compose_summary_from_cobertura_document(cobertura_document)
+        new_stats = self.__compose_summary_from_cobertura_document(
+            cobertura_document, coverage_provider_name
+        )
         self.save_summary_file(self.__output_path, new_stats, "test coverage")
 
         published_coverage_summary_path = (
@@ -70,7 +99,9 @@ class CoberturaPlugin(ProjectSummarizerPlugin):
 
         self.__report_coverage_files(new_stats, loaded_stats, only_changes)
 
-    def __compose_summary_from_cobertura_document(self, cobertura_document):
+    def __compose_summary_from_cobertura_document(
+        self, cobertura_document, coverage_provider_name
+    ):
         """
         Compose a CoverageTotals instance from the Cobetura based document.
         """
@@ -78,7 +109,7 @@ class CoberturaPlugin(ProjectSummarizerPlugin):
         project_name = cobertura_document.find("./sources/source").text
         project_name = os.path.basename(project_name)
         coverage_totals = CoverageTotals(
-            project_name=project_name, report_source="pytest"
+            project_name=project_name, report_source=coverage_provider_name
         )
 
         measured_lines, covered_lines, measured_branches, covered_branches = 0, 0, 0, 0
diff --git a/publish/coverage.json b/publish/coverage.json
index 1b4018d..b5ea835 100644
--- a/publish/coverage.json
+++ b/publish/coverage.json
@@ -1,13 +1,13 @@
 {
     "projectName": "project_summarizer",
-    "reportSource": "pytest",
+    "reportSource": "Coverage.py",
     "branchLevel": {
-        "totalMeasured": 184,
-        "totalCovered": 184
+        "totalMeasured": 186,
+        "totalCovered": 186
     },
     "lineLevel": {
-        "totalMeasured": 563,
-        "totalCovered": 563
+        "totalMeasured": 576,
+        "totalCovered": 576
     }
 }
 
diff --git a/publish_to_release.cmd b/publish_to_release.cmd
index 45cb58a..08b3d88 100644
--- a/publish_to_release.cmd
+++ b/publish_to_release.cmd
@@ -1,1 +1,1 @@
-pipenv run python -m twine upload --config-file .pypirc --repository pypi dist/*
\ No newline at end of file
+pipenv run python -m twine upload --config-file ../.pypirc --repository pypi dist/*
\ No newline at end of file

diff --git a/test/test_coverage_profiles.py b/test/test_coverage_profiles.py
index 7935fc0..2fc30cb 100644
--- a/test/test_coverage_profiles.py
+++ b/test/test_coverage_profiles.py
@@ -18,11 +18,14 @@ def test_pytest_cobertura_profile():
         total_covered=15, total_measured=20
     )
 
-    expected_dictionary = {"projectName": "?", "reportSource": "pytest"}
     g_branch = {"totalCovered": 5, "totalMeasured": 10}
     g_line = {"totalCovered": 15, "totalMeasured": 20}
-    expected_dictionary["branchLevel"] = g_branch
-    expected_dictionary["lineLevel"] = g_line
+    expected_dictionary = {
+        "projectName": "?",
+        "reportSource": "pytest",
+        "branchLevel": g_branch,
+        "lineLevel": g_line,
+    }
 
     # Act
     coverage_profile_as_dictionary = coverage_profile.to_dict()
@@ -59,19 +62,22 @@ def test_junit_jacoco_profile():
         total_covered=1, total_measured=1
     )
 
-    expected_dictionary = {"projectName": "?", "reportSource": "junit"}
     g_instructions = {"totalCovered": 25, "totalMeasured": 30}
     g_line = {"totalCovered": 15, "totalMeasured": 20}
     g_branch = {"totalCovered": 5, "totalMeasured": 10}
     g_complexity = {"totalCovered": 6, "totalMeasured": 11}
     g_method = {"totalCovered": 3, "totalMeasured": 4}
     g_class = {"totalCovered": 1, "totalMeasured": 1}
-    expected_dictionary["instructionLevel"] = g_instructions
-    expected_dictionary["lineLevel"] = g_line
-    expected_dictionary["branchLevel"] = g_branch
-    expected_dictionary["complexityLevel"] = g_complexity
-    expected_dictionary["methodLevel"] = g_method
-    expected_dictionary["classLevel"] = g_class
+    expected_dictionary = {
+        "projectName": "?",
+        "reportSource": "junit",
+        "instructionLevel": g_instructions,
+        "lineLevel": g_line,
+        "branchLevel": g_branch,
+        "complexityLevel": g_complexity,
+        "methodLevel": g_method,
+        "classLevel": g_class,
+    }
 
     # Act
     coverage_profile_as_dictionary = coverage_profile.to_dict()
@@ -94,9 +100,12 @@ def test_made_up_profile():
         total_covered=25, total_measured=30
     )
 
-    expected_dictionary = {"projectName": "?", "reportSource": "asmunit"}
     g_instructions = {"totalCovered": 25, "totalMeasured": 30}
-    expected_dictionary["instructionLevel"] = g_instructions
+    expected_dictionary = {
+        "projectName": "?",
+        "reportSource": "asmunit",
+        "instructionLevel": g_instructions,
+    }
 
     # Act
     coverage_profile_as_dictionary = coverage_profile.to_dict()
diff --git a/test/test_coverage_scenarios.py b/test/test_coverage_scenarios.py
index c0bc39b..4ba720d 100644
--- a/test/test_coverage_scenarios.py
+++ b/test/test_coverage_scenarios.py
@@ -24,7 +24,7 @@ def compose_coverage_summary_file():
 
     return """{
     "projectName": "project_summarizer",
-    "reportSource": "pytest",
+    "reportSource": "Coverage.py",
     "branchLevel": {
         "totalMeasured": 4,
         "totalCovered": 2

Add ability to try and pull coverage provider from coverage file.
test/test_coverage_scenarios.py::test_summarize_simple_cobertura_report test/test_coverage_scenarios.py::test_summarize_simple_cobertura_report_and_publish test/test_coverage_scenarios.py::test_summarize_simple_cobertura_report_and_publish_and_summarize_again test/test_coverage_scenarios.py::test_summarize_simple_cobertura_report_and_publish_and_summarize_again_only_changes test/test_coverage_scenarios.py::test_summarize_simple_cobertura_report_and_publish_and_summarize_with_error_on_publish_read
test/test_coverage_profiles.py::test_pytest_cobertura_profile test/test_coverage_profiles.py::test_junit_jacoco_profile test/test_coverage_profiles.py::test_made_up_profile test/test_coverage_scenarios.py::test_summarize_cobertura_report_with_bad_source test/test_coverage_scenarios.py::test_summarize_cobertura_report_with_source_as_directory test/test_coverage_scenarios.py::test_summarize_bad_xml_test_coverage test/test_coverage_scenarios.py::test_summarize_bad_test_coverage test/test_coverage_scenarios.py::test_summarize_bad_report_directory test/test_coverage_scenarios.py::test_summarize_invalid_published_summary_file test/test_coverage_scenarios.py::test_summarize_simple_cobertura_report_with_error_on_report_write