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

Add --base-dir option #287

Merged
merged 8 commits into from May 24, 2021
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
5 changes: 4 additions & 1 deletion coveralls/api.py
Expand Up @@ -223,7 +223,9 @@ def wear(self, dry_run=False):
json_string = self.create_report()
if dry_run:
return {}
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},
Expand Down Expand Up @@ -368,7 +370,8 @@ def get_coverage(self):
workman.load()
workman.get_data()

return CoverallReporter(workman, workman.config).coverage
base_dir = self.config.get('base_dir') or ''
return CoverallReporter(workman, workman.config, base_dir).coverage

@staticmethod
def debug_bad_encoding(data):
Expand Down
15 changes: 12 additions & 3 deletions coveralls/cli.py
Expand Up @@ -19,7 +19,9 @@
Global options:
--service=<name> Provide an alternative service name to submit.
--rcfile=<file> Specify configuration file. [default: .coveragerc]
--basedir=<dir> Base directory that is removed from reported paths.
--output=<file> Write report to file. Doesn't send anything.
--submit=<file> Upload a previously generated file.
--merge=<file> Merge report from file when submitting.
--finish Finish parallel jobs.
-h --help Display this help.
Expand Down Expand Up @@ -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('--basedir') or '')

if options['--merge']:
coverallz.merge(options['--merge'])
Expand All @@ -75,6 +78,11 @@ def main(argv=None):
coverallz.save_report(options['--output'])
return

if options['--submit']:
with open(options['--submit']) as report_file:
coverallz.submit_report(report_file.read())
return

if options['--finish']:
log.info('Finishing parallel jobs...')
coverallz.parallel_finish()
Expand All @@ -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'))
log.info(result.get('url'))
except KeyboardInterrupt: # pragma: no cover
log.info('Aborted')
except CoverallsException as e:
Expand Down
11 changes: 10 additions & 1 deletion coveralls/reporter.py
Expand Up @@ -12,8 +12,13 @@
class CoverallReporter:
"""Custom coverage.py reporter for coveralls.io."""

def __init__(self, cov, conf):
def __init__(self, cov, conf, base_dir=''):
self.coverage = []
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 += '/'
self.report(cov, conf)

def report5(self, cov):
Expand Down Expand Up @@ -183,9 +188,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):
TheKevJames marked this conversation as resolved.
Show resolved Hide resolved
posix_filename = posix_filename[len(self.base_dir):]

source = analysis.file_reporter.source()

token_lines = analysis.file_reporter.source_token_lines()
Expand Down
1 change: 1 addition & 0 deletions 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}
107 changes: 107 additions & 0 deletions tests/api/reporter_test.py
Expand Up @@ -62,6 +62,113 @@ 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)
Expand Down
27 changes: 25 additions & 2 deletions tests/cli_test.py
Expand Up @@ -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'))

Expand Down Expand Up @@ -104,15 +108,17 @@ 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='')


@mock.patch.dict(os.environ, {}, clear=True)
@mock.patch('coveralls.cli.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='')


@mock.patch.object(coveralls.cli.log, 'exception')
Expand Down Expand Up @@ -142,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=['--basedir=foo'])
mock_coveralls.assert_called_with(True, config_file='.coveragerc',
service_name=None,
base_dir='foo')