From 5b1cd928e72cc0cc261eda1636da436c4c5a872a Mon Sep 17 00:00:00 2001 From: swryan Date: Fri, 2 Apr 2021 23:55:07 -0400 Subject: [PATCH 1/6] add --base-dir option (#1) * add option to upload previously generated file * cleanup * fix * add --base_dir arg * result=None? * fix * win fix * posix base_dir * big * fix tests --- coveralls/api.py | 6 +++++- coveralls/cli.py | 15 ++++++++++++--- coveralls/reporter.py | 12 +++++++++++- tests/cli_test.py | 6 ++++-- 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/coveralls/api.py b/coveralls/api.py index 7c707970..d2ed3fa0 100644 --- a/coveralls/api.py +++ b/coveralls/api.py @@ -223,7 +223,10 @@ def wear(self, dry_run=False): json_string = self.create_report() if dry_run: return {} + else: + return self.submit_report(json_string) + def submit_report(self, json_string): endpoint = '{}/api/v1/jobs'.format(self._coveralls_host.rstrip('/')) verify = not bool(os.environ.get('COVERALLS_SKIP_SSL_VERIFY')) response = requests.post(endpoint, files={'json_file': json_string}, @@ -368,7 +371,8 @@ def get_coverage(self): workman.load() workman.get_data() - return CoverallReporter(workman, workman.config).coverage + base_dir = self.config.get('base_dir', None) + return CoverallReporter(workman, workman.config, base_dir).coverage @staticmethod def debug_bad_encoding(data): diff --git a/coveralls/cli.py b/coveralls/cli.py index 3244e2d5..fe834c5a 100644 --- a/coveralls/cli.py +++ b/coveralls/cli.py @@ -19,7 +19,9 @@ Global options: --service= Provide an alternative service name to submit. --rcfile= Specify configuration file. [default: .coveragerc] + --base_dir= Base directory that is removed from reported paths. --output= Write report to file. Doesn't send anything. + --submit= Upload a previously generated file. --merge= Merge report from file when submitting. --finish Finish parallel jobs. -h --help Display this help. @@ -60,7 +62,8 @@ def main(argv=None): try: coverallz = Coveralls(token_required, config_file=options['--rcfile'], - service_name=options['--service']) + service_name=options['--service'], + base_dir=options.get('--base_dir', None)) if options['--merge']: coverallz.merge(options['--merge']) @@ -75,6 +78,11 @@ def main(argv=None): coverallz.save_report(options['--output']) return + if options['--submit']: + with open(options['--submit'], 'r') as report_file: + coverallz.submit_report(report_file.read()) + return + if options['--finish']: log.info('Finishing parallel jobs...') coverallz.parallel_finish() @@ -86,8 +94,9 @@ def main(argv=None): log.info('Coverage submitted!') log.debug(result) - log.info(result['message']) - log.info(result['url']) + if result: + log.info(result.get('message', None)) + log.info(result.get('url', None)) except KeyboardInterrupt: # pragma: no cover log.info('Aborted') except CoverallsException as e: diff --git a/coveralls/reporter.py b/coveralls/reporter.py index f0f810a0..ac658d00 100644 --- a/coveralls/reporter.py +++ b/coveralls/reporter.py @@ -12,8 +12,14 @@ class CoverallReporter: """Custom coverage.py reporter for coveralls.io.""" - def __init__(self, cov, conf): + def __init__(self, cov, conf, base_dir=None): self.coverage = [] + if base_dir: + self.base_dir = base_dir + os.path.sep if base_dir and \ + base_dir[-1] != os.path.sep else base_dir + self.base_dir = self.base_dir.replace(os.path.sep, '/') + else: + self.base_dir = None self.report(cov, conf) def report5(self, cov): @@ -183,9 +189,13 @@ def get_arcs(analysis): def parse_file(self, cu, analysis): """Generate data for single file.""" filename = cu.relative_filename() + # ensure results are properly merged between platforms posix_filename = filename.replace(os.path.sep, '/') + if self.base_dir and posix_filename.startswith(self.base_dir): + posix_filename = posix_filename[len(self.base_dir):] + source = analysis.file_reporter.source() token_lines = analysis.file_reporter.source_token_lines() diff --git a/tests/cli_test.py b/tests/cli_test.py index ebafb040..da08f3f3 100644 --- a/tests/cli_test.py +++ b/tests/cli_test.py @@ -104,7 +104,8 @@ def test_real(mock_wear, mock_log): def test_rcfile(mock_coveralls): coveralls.cli.main(argv=['--rcfile=coveragerc']) mock_coveralls.assert_called_with(True, config_file='coveragerc', - service_name=None) + service_name=None, + base_dir=None) @mock.patch.dict(os.environ, {}, clear=True) @@ -112,7 +113,8 @@ def test_rcfile(mock_coveralls): def test_service_name(mock_coveralls): coveralls.cli.main(argv=['--service=travis-pro']) mock_coveralls.assert_called_with(True, config_file='.coveragerc', - service_name='travis-pro') + service_name='travis-pro', + base_dir=None) @mock.patch.object(coveralls.cli.log, 'exception') From 77b8c4d015e8dc04476d68023305ceb3b7ccfb05 Mon Sep 17 00:00:00 2001 From: swryan Date: Thu, 6 May 2021 16:50:01 -0400 Subject: [PATCH 2/6] tests --- coveralls/api.py | 3 +-- coveralls/cli.py | 2 +- coveralls/reporter.py | 6 +++--- tests/cli_test.py | 21 +++++++++++++++++++++ 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/coveralls/api.py b/coveralls/api.py index d2ed3fa0..f254efb7 100644 --- a/coveralls/api.py +++ b/coveralls/api.py @@ -223,8 +223,7 @@ def wear(self, dry_run=False): json_string = self.create_report() if dry_run: return {} - else: - return self.submit_report(json_string) + return self.submit_report(json_string) def submit_report(self, json_string): endpoint = '{}/api/v1/jobs'.format(self._coveralls_host.rstrip('/')) diff --git a/coveralls/cli.py b/coveralls/cli.py index fe834c5a..dbbb1ed7 100644 --- a/coveralls/cli.py +++ b/coveralls/cli.py @@ -79,7 +79,7 @@ def main(argv=None): return if options['--submit']: - with open(options['--submit'], 'r') as report_file: + with open(options['--submit']) as report_file: coverallz.submit_report(report_file.read()) return diff --git a/coveralls/reporter.py b/coveralls/reporter.py index ac658d00..3c452f77 100644 --- a/coveralls/reporter.py +++ b/coveralls/reporter.py @@ -15,9 +15,9 @@ class CoverallReporter: def __init__(self, cov, conf, base_dir=None): self.coverage = [] if base_dir: - self.base_dir = base_dir + os.path.sep if base_dir and \ - base_dir[-1] != os.path.sep else base_dir - self.base_dir = self.base_dir.replace(os.path.sep, '/') + self.base_dir = base_dir.replace(os.path.sep, '/') + if self.base_dir[-1] != '/': + self.base_dir += '/' else: self.base_dir = None self.report(cov, conf) diff --git a/tests/cli_test.py b/tests/cli_test.py index da08f3f3..b455cf35 100644 --- a/tests/cli_test.py +++ b/tests/cli_test.py @@ -11,6 +11,10 @@ EXC = CoverallsException('bad stuff happened') +BASE_DIR = os.path.dirname(os.path.dirname(__file__)) +EXAMPLE_DIR = os.path.join(BASE_DIR, 'example') + + def req_json(request): return json.loads(request.body.decode('utf-8')) @@ -144,3 +148,20 @@ def test_save_report_to_file_no_token(mock_coveralls): """Check save_report api usage when token is not set.""" coveralls.cli.main(argv=['--output=test.log']) mock_coveralls.assert_called_with('test.log') + + +@mock.patch.object(coveralls.Coveralls, 'submit_report') +@mock.patch.dict(os.environ, {'TRAVIS': 'True'}, clear=True) +def test_submit(mock_submit): + json_file = os.path.join(EXAMPLE_DIR, 'example.json') + json_string = open(json_file).read() + coveralls.cli.main(argv=['--submit=' + json_file]) + mock_submit.assert_called_with(json_string) + + +@mock.patch('coveralls.cli.Coveralls') +def test_base_dir_arg(mock_coveralls): + coveralls.cli.main(argv=['--base_dir=foo']) + mock_coveralls.assert_called_with(True, config_file='.coveragerc', + service_name=None, + base_dir='foo') From a8a6b536b842e309e5627c4ca58c806b8f88dd54 Mon Sep 17 00:00:00 2001 From: swryan Date: Thu, 6 May 2021 21:30:29 -0400 Subject: [PATCH 3/6] new file --- example/example.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 example/example.json diff --git a/example/example.json b/example/example.json new file mode 100644 index 00000000..5c0d4708 --- /dev/null +++ b/example/example.json @@ -0,0 +1 @@ +{"source_files": [{"name": "coveralls-python/example/project.py", "source": "def hello():\n print('world')\n\n\nclass Foo:\n \"\"\" Bar \"\"\"\n\n\ndef baz():\n print('this is not tested')\n\ndef branch(cond1, cond2):\n if cond1:\n print('condition tested both ways')\n if cond2:\n print('condition not tested both ways')\n", "coverage": [1, 1, null, null, 1, null, null, null, 1, 0, null, 1, 1, 1, 1, 1]}, {"name": "coveralls-python/example/runtests.py", "source": "from project import branch\nfrom project import hello\n\nif __name__ == '__main__':\n hello()\n branch(False, True)\n branch(True, True)\n", "coverage": [1, 1, null, 1, 1, 1, 1]}], "service_name": "coveralls-python", "config_file": ".coveragerc", "base_dir": null} \ No newline at end of file From e0811abd7e226a97854837369be2941dc902b1f9 Mon Sep 17 00:00:00 2001 From: swryan Date: Thu, 6 May 2021 22:02:00 -0400 Subject: [PATCH 4/6] more tests for --base_dir --- tests/api/reporter_test.py | 105 +++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/tests/api/reporter_test.py b/tests/api/reporter_test.py index 8c90e514..6e64d207 100644 --- a/tests/api/reporter_test.py +++ b/tests/api/reporter_test.py @@ -62,6 +62,111 @@ def test_reporter(self): 'name': 'runtests.py', 'coverage': [1, 1, None, 1, 1, 1, 1]}) + def test_reporter_no_base_dir_arg(self): + subprocess.call(['coverage', 'run', '--omit=**/.tox/*', + 'example/runtests.py'], cwd=BASE_DIR) + + # without base_dir arg, file name is prefixed with 'example/' + os.chdir(BASE_DIR) + results = Coveralls(repo_token='xxx').get_coverage() + assert len(results) == 2 + + assert_coverage(results[0], { + 'source': ('def hello():\n' + ' print(\'world\')\n\n\n' + 'class Foo:\n' + ' """ Bar """\n\n\n' + 'def baz():\n' + ' print(\'this is not tested\')\n\n' + 'def branch(cond1, cond2):\n' + ' if cond1:\n' + ' print(\'condition tested both ways\')\n' + ' if cond2:\n' + ' print(\'condition not tested both ways\')\n'), + 'name': 'example/project.py', + 'coverage': [1, 1, None, None, 1, None, None, + None, 1, 0, None, 1, 1, 1, 1, 1]}) + + assert_coverage(results[1], { + 'source': ('from project import branch\n' + 'from project import hello\n\n' + "if __name__ == '__main__':\n" + ' hello()\n' + ' branch(False, True)\n' + ' branch(True, True)\n'), + 'name': 'example/runtests.py', + 'coverage': [1, 1, None, 1, 1, 1, 1]}) + + def test_reporter_with_base_dir_arg(self): + subprocess.call(['coverage', 'run', '--omit=**/.tox/*', + 'example/runtests.py'], cwd=BASE_DIR) + + # without base_dir arg, file name is prefixed with 'example/' + os.chdir(BASE_DIR) + results = Coveralls(repo_token='xxx', base_dir='example').get_coverage() + assert len(results) == 2 + + assert_coverage(results[0], { + 'source': ('def hello():\n' + ' print(\'world\')\n\n\n' + 'class Foo:\n' + ' """ Bar """\n\n\n' + 'def baz():\n' + ' print(\'this is not tested\')\n\n' + 'def branch(cond1, cond2):\n' + ' if cond1:\n' + ' print(\'condition tested both ways\')\n' + ' if cond2:\n' + ' print(\'condition not tested both ways\')\n'), + 'name': 'project.py', + 'coverage': [1, 1, None, None, 1, None, None, + None, 1, 0, None, 1, 1, 1, 1, 1]}) + + assert_coverage(results[1], { + 'source': ('from project import branch\n' + 'from project import hello\n\n' + "if __name__ == '__main__':\n" + ' hello()\n' + ' branch(False, True)\n' + ' branch(True, True)\n'), + 'name': 'runtests.py', + 'coverage': [1, 1, None, 1, 1, 1, 1]}) + + def test_reporter_with_base_dir_trailing_sep(self): + subprocess.call(['coverage', 'run', '--omit=**/.tox/*', + 'example/runtests.py'], cwd=BASE_DIR) + + # without base_dir arg, file name is prefixed with 'example/' + os.chdir(BASE_DIR) + results = Coveralls(repo_token='xxx', base_dir='example/').get_coverage() + assert len(results) == 2 + + assert_coverage(results[0], { + 'source': ('def hello():\n' + ' print(\'world\')\n\n\n' + 'class Foo:\n' + ' """ Bar """\n\n\n' + 'def baz():\n' + ' print(\'this is not tested\')\n\n' + 'def branch(cond1, cond2):\n' + ' if cond1:\n' + ' print(\'condition tested both ways\')\n' + ' if cond2:\n' + ' print(\'condition not tested both ways\')\n'), + 'name': 'project.py', + 'coverage': [1, 1, None, None, 1, None, None, + None, 1, 0, None, 1, 1, 1, 1, 1]}) + + assert_coverage(results[1], { + 'source': ('from project import branch\n' + 'from project import hello\n\n' + "if __name__ == '__main__':\n" + ' hello()\n' + ' branch(False, True)\n' + ' branch(True, True)\n'), + 'name': 'runtests.py', + 'coverage': [1, 1, None, 1, 1, 1, 1]}) + def test_reporter_with_branches(self): subprocess.call(['coverage', 'run', '--branch', '--omit=**/.tox/*', 'runtests.py'], cwd=EXAMPLE_DIR) From 4e65569d36f9b4819753338ce8ad416114d03278 Mon Sep 17 00:00:00 2001 From: swryan Date: Thu, 6 May 2021 22:05:10 -0400 Subject: [PATCH 5/6] lint --- tests/api/reporter_test.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/api/reporter_test.py b/tests/api/reporter_test.py index 6e64d207..31f40be3 100644 --- a/tests/api/reporter_test.py +++ b/tests/api/reporter_test.py @@ -103,7 +103,8 @@ def test_reporter_with_base_dir_arg(self): # without base_dir arg, file name is prefixed with 'example/' os.chdir(BASE_DIR) - results = Coveralls(repo_token='xxx', base_dir='example').get_coverage() + results = Coveralls(repo_token='xxx', + base_dir='example').get_coverage() assert len(results) == 2 assert_coverage(results[0], { @@ -138,7 +139,8 @@ def test_reporter_with_base_dir_trailing_sep(self): # without base_dir arg, file name is prefixed with 'example/' os.chdir(BASE_DIR) - results = Coveralls(repo_token='xxx', base_dir='example/').get_coverage() + results = Coveralls(repo_token='xxx', + base_dir='example/').get_coverage() assert len(results) == 2 assert_coverage(results[0], { From e71c7e4b8d712bdafad6e4fd4f11e1160680223a Mon Sep 17 00:00:00 2001 From: swryan Date: Tue, 18 May 2021 14:54:22 -0400 Subject: [PATCH 6/6] change --base_dir to --basedir, default to '' --- coveralls/api.py | 2 +- coveralls/cli.py | 8 ++++---- coveralls/reporter.py | 9 ++++----- tests/cli_test.py | 6 +++--- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/coveralls/api.py b/coveralls/api.py index f254efb7..cb9db7fd 100644 --- a/coveralls/api.py +++ b/coveralls/api.py @@ -370,7 +370,7 @@ def get_coverage(self): workman.load() workman.get_data() - base_dir = self.config.get('base_dir', None) + base_dir = self.config.get('base_dir') or '' return CoverallReporter(workman, workman.config, base_dir).coverage @staticmethod diff --git a/coveralls/cli.py b/coveralls/cli.py index dbbb1ed7..1c90604c 100644 --- a/coveralls/cli.py +++ b/coveralls/cli.py @@ -19,7 +19,7 @@ Global options: --service= Provide an alternative service name to submit. --rcfile= Specify configuration file. [default: .coveragerc] - --base_dir= Base directory that is removed from reported paths. + --basedir= Base directory that is removed from reported paths. --output= Write report to file. Doesn't send anything. --submit= Upload a previously generated file. --merge= Merge report from file when submitting. @@ -63,7 +63,7 @@ def main(argv=None): coverallz = Coveralls(token_required, config_file=options['--rcfile'], service_name=options['--service'], - base_dir=options.get('--base_dir', None)) + base_dir=options.get('--basedir') or '') if options['--merge']: coverallz.merge(options['--merge']) @@ -95,8 +95,8 @@ def main(argv=None): log.info('Coverage submitted!') log.debug(result) if result: - log.info(result.get('message', None)) - log.info(result.get('url', None)) + log.info(result.get('message')) + log.info(result.get('url')) except KeyboardInterrupt: # pragma: no cover log.info('Aborted') except CoverallsException as e: diff --git a/coveralls/reporter.py b/coveralls/reporter.py index 3c452f77..529a5c76 100644 --- a/coveralls/reporter.py +++ b/coveralls/reporter.py @@ -12,14 +12,13 @@ class CoverallReporter: """Custom coverage.py reporter for coveralls.io.""" - def __init__(self, cov, conf, base_dir=None): + def __init__(self, cov, conf, base_dir=''): self.coverage = [] - if base_dir: - self.base_dir = base_dir.replace(os.path.sep, '/') + self.base_dir = base_dir + if self.base_dir: + self.base_dir = self.base_dir.replace(os.path.sep, '/') if self.base_dir[-1] != '/': self.base_dir += '/' - else: - self.base_dir = None self.report(cov, conf) def report5(self, cov): diff --git a/tests/cli_test.py b/tests/cli_test.py index b455cf35..8e85cbce 100644 --- a/tests/cli_test.py +++ b/tests/cli_test.py @@ -109,7 +109,7 @@ def test_rcfile(mock_coveralls): coveralls.cli.main(argv=['--rcfile=coveragerc']) mock_coveralls.assert_called_with(True, config_file='coveragerc', service_name=None, - base_dir=None) + base_dir='') @mock.patch.dict(os.environ, {}, clear=True) @@ -118,7 +118,7 @@ def test_service_name(mock_coveralls): coveralls.cli.main(argv=['--service=travis-pro']) mock_coveralls.assert_called_with(True, config_file='.coveragerc', service_name='travis-pro', - base_dir=None) + base_dir='') @mock.patch.object(coveralls.cli.log, 'exception') @@ -161,7 +161,7 @@ def test_submit(mock_submit): @mock.patch('coveralls.cli.Coveralls') def test_base_dir_arg(mock_coveralls): - coveralls.cli.main(argv=['--base_dir=foo']) + coveralls.cli.main(argv=['--basedir=foo']) mock_coveralls.assert_called_with(True, config_file='.coveragerc', service_name=None, base_dir='foo')