Repository: z4r/python-coveralls Branch: master Commit: e5f5eb81e62b Files: 18 Total size: 23.7 KB Directory structure: gitextract_yc_1z_9e/ ├── .coveragerc ├── .coveralls.yml ├── .gitignore ├── .travis.yml ├── LICENSE ├── MANIFEST.in ├── README.rst ├── appveyor.yml ├── coveralls/ │ ├── __init__.py │ ├── api.py │ ├── control.py │ ├── report.py │ ├── repository.py │ └── tests.py ├── pytest.ini ├── setup.cfg ├── setup.py └── test_requirements.txt ================================================ FILE CONTENTS ================================================ ================================================ FILE: .coveragerc ================================================ [run] omit = */tests* [report] exclude_lines = pragma: no cover def __repr__ raise NotImplementedError if __name__ == .__main__.: def parse_args ================================================ FILE: .coveralls.yml ================================================ ================================================ FILE: .gitignore ================================================ *.py[cod] venv* # C extensions *.so # Packages *.egg *.egg-info dist build eggs parts bin var sdist develop-eggs .installed.cfg lib lib64 # Installer logs pip-log.txt # Unit test / coverage reports .coverage .tox nosetests.xml .cache # Translations *.mo # Mr Developer .mr.developer.cfg .project .pydevproject .idea # Sample python-coveralls-example ================================================ FILE: .travis.yml ================================================ language: python python: - "2.7" - "3.5" - "3.6" install: - pip install -U pip - python setup.py develop before_script: - pip install -I -r test_requirements.txt - git clone https://github.com/z4r/python-coveralls-example.git - cd python-coveralls-example - git checkout -qf 3e82fd5159b84bebe9bc6c9fd3959f322e6f7098 - py.test example/tests.py --cov=example - cd - script: - py.test coveralls/tests.py --doctest-modules --pep8 coveralls -v --cov coveralls --cov-report term-missing after_success: - coveralls ================================================ FILE: LICENSE ================================================ Copyright 2013 Andrea De Marco. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expressed or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: MANIFEST.in ================================================ include LICENSE README.* *.txt ================================================ FILE: README.rst ================================================ ==================================== Python interface to coveralls.io API ==================================== .. image:: https://api.travis-ci.org/z4r/python-coveralls.png?branch=master :target: http://travis-ci.org/z4r/python-coveralls .. image:: https://coveralls.io/repos/z4r/python-coveralls/badge.png?branch=master :target: https://coveralls.io/r/z4r/python-coveralls .. image:: https://img.shields.io/pypi/v/python-coveralls.svg :target: https://pypi.python.org/pypi/python-coveralls/ .. image:: https://img.shields.io/pypi/dm/python-coveralls.svg :target: https://pypi.python.org/pypi/python-coveralls/ .. image:: https://img.shields.io/pypi/wheel/python-coveralls.svg :target: https://pypi.python.org/pypi/python-coveralls/ :alt: Wheel Status This package provides a module to interface with the https://coveralls.io API. INSTALLING THE PKG ================== Using pip:: $ pip install python-coveralls ...Or simply add it to your requirements. CONFIGURATION ============= If you're not using Travis, Coveralls for Python uses a ``.coveralls.yml`` file at the root level of your repository to configure options. The only required option is ``repo_token`` (found on your repository's page on Coveralls) to specify which project on Coveralls your project maps to. Another important option is is ``service_name`` which allows you to specify where Coveralls should look to find additional information about your builds. This can be any string, but using travis-ci or travis-pro will allow Coveralls to fetch branch data, comment on pull requests, and more. A ``.coveralls.yml`` file configured for Travis Pro: .. code-block:: yaml repo_token: abcdef1234569abdcef service_name: travis-pro parallel: true # if the CI is running your build in parallel if you don't want the ``repo_token`` under source control, set it in your ``coveralls`` command:: COVERALLS_REPO_TOKEN=abcdef1234569abdcef coveralls TRAVIS.YML ========== Create a ``.coverage`` file and you can use `coverage `_, `pytest-cov `_, or `nosexcover `_. Then you can add in the **after_success** step:: coveralls It should look like something like: .. code-block:: yaml language: python python: - "2.6" - "2.7" install: - pip install -e . --use-mirrors before_script: - pip install -r test_requirements.txt --use-mirrors - git clone https://github.com/z4r/python-coveralls-example.git - cd python-coveralls-example - git checkout -qf 17b8119796516195527dcb4f454a2ebd41d60244 - py.test example/tests.py --cov=example - cd - script: - py.test coveralls/tests.py --doctest-modules --pep8 coveralls -v --cov coveralls --cov-report term-missing after_success: - coveralls COVERALLS OPTIONS ================= You probably don't need to configure anything, but if you customize some option of `coverage` you would add it to `coveralls` too:: $ coveralls -h usage: coveralls [-h] [--coveralls_url COVERALLS_URL] [--base_dir BASE_DIR] [--data_file DATA_FILE] [--config_file CONFIG_FILE] [--coveralls_yaml COVERALLS_YAML] [--ignore-errors] [--merge_file MERGE_FILE] [--nogit] optional arguments: -h, --help show this help message and exit --coveralls_url COVERALLS_URL, -u COVERALLS_URL coveralls.io api url --base_dir BASE_DIR, -b BASE_DIR project root directory --data_file DATA_FILE, -d DATA_FILE coverage file name --config_file CONFIG_FILE, -c CONFIG_FILE coverage config file name --coveralls_yaml COVERALLS_YAML, -y COVERALLS_YAML coveralls yaml file name --ignore-errors, -i ignore errors while reading source files --merge_file MERGE_FILE, -m MERGE_FILE json file containing coverage data to be merged (for merging javascript coverage) --nogit do not gather git repo info .. image:: https://d2weczhvl823v0.cloudfront.net/z4r/python-coveralls/trend.png :alt: Bitdeli badge :target: https://bitdeli.com/free ================================================ FILE: appveyor.yml ================================================ environment: matrix: - PYTHON: C:\Python27\python.exe platform: Any CPU - PYTHON: C:\Python33\python.exe platform: Any CPU - PYTHON: C:\Python34\python.exe platform: Any CPU - PYTHON: C:\Python35\python.exe platform: Any CPU before_build: - "%PYTHON% -m pip install virtualenv" - "%PYTHON% -m virtualenv venv" - venv\Scripts\activate.bat build_script: - pip install -U pip - python setup.py develop before_test: - pip install -r test_requirements.txt - 'git clone https://github.com/z4r/python-coveralls-example.git' - cd python-coveralls-example - git checkout -qf 3e82fd5159b84bebe9bc6c9fd3959f322e6f7098 - py.test example/tests.py --cov=example - cd %APPVEYOR_BUILD_FOLDER% test_script: - py.test coveralls/tests.py --doctest-modules --pep8 coveralls -v --cov coveralls --cov-report term-missing #on_success: # - coveralls ================================================ FILE: coveralls/__init__.py ================================================ __author__ = 'Andrea De Marco <24erre@gmail.com>' __version__ = '2.9.3' __classifiers__ = [ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'License :: OSI Approved :: Apache Software License', 'Operating System :: OS Independent', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Topic :: Internet :: WWW/HTTP', 'Topic :: Software Development :: Libraries', ] __copyright__ = "2013, %s " % __author__ __license__ = """ Copyright %s. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expressed or implied. See the License for the specific language governing permissions and limitations under the License. """ % __copyright__ __docformat__ = 'restructuredtext en' __doc__ = """ :abstract: Python interface to coveralls.io API :version: %s :author: %s :contact: http://z4r.github.com/ :date: 2012-02-08 :copyright: %s """ % (__version__, __author__, __license__) def parse_args(): import os import yaml import argparse parser = argparse.ArgumentParser(prog='coveralls') parser.add_argument('--coveralls_url', '-u', help='coveralls.io api url', default='https://coveralls.io/api/v1/jobs') parser.add_argument('--base_dir', '-b', help='project root directory', default='.') parser.add_argument('--data_file', '-d', help='coverage file name', default=None) parser.add_argument('--config_file', '-c', help='coverage config file name', default=None) parser.add_argument('--coveralls_yaml', '-y', help='coveralls yaml file name', default='.coveralls.yml') parser.add_argument('--ignore-errors', '-i', help='ignore errors while reading source files', action='store_true', default=False) parser.add_argument('--merge_file', '-m', help='json file containing coverage data to be merged (for merging javascript coverage)', default=None) parser.add_argument('--nogit', help='do not gather git repo info', action='store_true', default=False) parser.add_argument('--skip_ssl_verify', help='skip ssl certificate verification when communicating with the coveralls server', action='store_true', default=False) args = parser.parse_args() args.base_dir = os.path.abspath(args.base_dir) args.data_file = os.path.join(args.base_dir, args.data_file) if args.data_file else None args.config_file = os.path.join(args.base_dir, args.config_file) if args.config_file else True args.coveralls_yaml = os.path.join(args.base_dir, args.coveralls_yaml) args.merge_file = os.path.join(args.base_dir, args.merge_file) if args.merge_file else None yml = {} try: with open(args.coveralls_yaml, 'r') as fp: yml = yaml.load(fp, Loader=yaml.SafeLoader) except: pass yml = yml or {} args.repo_token = yml.get('repo_token') or os.environ.get('COVERALLS_REPO_TOKEN') or '' args.service_name = yml.get('service_name') or os.environ.get('COVERALLS_SERVICE_NAME') or 'travis-ci' args.service_job_id = os.environ.get('TRAVIS_JOB_ID', '') args.parallel = yml.get('parallel', os.environ.get('COVERALLS_PARALLEL', False)) return args def wear(args=None): from coveralls.control import coveralls from coveralls.repository import repo from coveralls.api import post import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger('coveralls') args = args or parse_args() coverage = coveralls(data_file=args.data_file, config_file=args.config_file) coverage.load() response = post( url=args.coveralls_url, repo_token=args.repo_token, service_job_id=args.service_job_id, service_name=args.service_name, git=repo(args.base_dir) if not args.nogit else {}, source_files=coverage.coveralls(args.base_dir, ignore_errors=args.ignore_errors, merge_file=args.merge_file), parallel=args.parallel, skip_ssl_verify=args.skip_ssl_verify, ) logger.info(response.status_code) logger.info(response.text) return 1 if 'error' in response.json() else 0 ================================================ FILE: coveralls/api.py ================================================ import json from six import StringIO import requests def post(url, repo_token, service_job_id, service_name, git, source_files, parallel, skip_ssl_verify=False): json_file = build_file(repo_token, service_job_id, service_name, git, source_files, parallel) return requests.post(url, files={'json_file': json_file}, verify=(not skip_ssl_verify)) def build_file(repo_token, service_job_id, service_name, git, source_files, parallel): content = { 'service_job_id': service_job_id, 'service_name': service_name, 'git': git, 'source_files': source_files, } if repo_token: content['repo_token'] = repo_token if parallel: content['parallel'] = True return StringIO(json.dumps(content)) ================================================ FILE: coveralls/control.py ================================================ from coverage.control import Coverage from coveralls.report import CoverallsReporter class coveralls(Coverage): def coveralls(self, base_dir, ignore_errors=False, merge_file=None): reporter = CoverallsReporter(self, self.config) reporter.find_file_reporters(None) return reporter.report(base_dir, ignore_errors=ignore_errors, merge_file=merge_file) ================================================ FILE: coveralls/report.py ================================================ import os import json from coverage.report import Reporter from coverage.misc import NotPython class CoverallsReporter(Reporter): def report(self, base_dir, ignore_errors=False, merge_file=None): ret = [] for fr in self.file_reporters: try: with open(fr.filename) as fp: source = fp.readlines() except IOError: if ignore_errors: continue else: raise try: analysis = self.coverage._analyze(fr) except NotPython: if ignore_errors: continue else: raise coverage_list = [None for _ in source] for lineno, line in enumerate(source): if lineno + 1 in analysis.statements: coverage_list[lineno] = int(lineno + 1 not in analysis.missing) ret.append({ 'name': fr.filename.replace(base_dir, '').lstrip(os.sep).replace(os.sep, '/'), 'source': ''.join(source).rstrip(), 'coverage': coverage_list, }) # if there's a merge file, load that and append it to the results as well if merge_file: with open(merge_file, 'r') as mfp: data = json.loads(mfp.read()) source_files = data.get('source_files') if source_files: ret.extend(source_files) return ret ================================================ FILE: coveralls/repository.py ================================================ import sys import os try: from subprocess32 import check_output except ImportError: from subprocess import check_output FORMAT = '%n'.join(['%H', '%aN', '%ae', '%cN', '%ce', '%s']) def gitrepo(root): tmpdir = os.getcwd() os.chdir(root) gitlog = check_output(['git', '--no-pager', 'log', '-1', '--pretty=format:%s' % FORMAT], universal_newlines=True).split('\n', 5) branch = (os.environ.get('CIRCLE_BRANCH') or os.environ.get('TRAVIS_BRANCH', check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD'], universal_newlines=True).strip())) remotes = [x.split() for x in filter(lambda x: x.endswith('(fetch)'), check_output(['git', 'remote', '-v'], universal_newlines=True).strip().splitlines())] os.chdir(tmpdir) return { "head": { "id": gitlog[0], "author_name": gitlog[1], "author_email": gitlog[2], "committer_name": gitlog[3], "committer_email": gitlog[4], "message": gitlog[5].strip(), }, "branch": branch, "remotes": [{'name': remote[0], 'url': remote[1]} for remote in remotes] } HGLOG = """{node} {author|person} {author|email} {author|person} {author|email} {desc}""" def hgrepo(root): hglog = check_output(['hg', 'log', '-l', '1', '--template=%s' % HGLOG], universal_newlines=True).split('\n', 5) branch = (os.environ.get('CIRCLE_BRANCH') or os.environ.get('TRAVIS_BRANCH', check_output(['hg', 'branch'], universal_newlines=True).strip())) remotes = [x.split(' = ') for x in check_output(['hg', 'paths'], universal_newlines=True).strip().splitlines()] return { 'head': { 'id': hglog[0], 'author_name': hglog[1], 'author_email': hglog[2], 'committer_name': hglog[3], 'committer_email': hglog[4], 'message': hglog[5].strip(), }, 'branch': branch, 'remotes': [{ 'name': remote[0], 'url': remote[1] } for remote in remotes] } def repo(root): if '.git' in os.listdir(root): return gitrepo(root) if '.hg' in os.listdir(root): return hgrepo(root) ================================================ FILE: coveralls/tests.py ================================================ # coding=utf-8 import json from unittest import TestCase from coverage.plugin import FileReporter from coverage.python import PythonFileReporter from coverage.misc import NotPython from coveralls.control import coveralls from coveralls.report import CoverallsReporter from httpretty import HTTPretty, httprettified from coveralls import api, repository, control, wear import os class Arguments(object): coveralls_url = 'https://coveralls.io/api/v1/jobs' repo_token = 'abcdef1234569abdcef' service_job_id = '4699301' service_name = 'travi-ci', base_dir = os.path.abspath('python-coveralls-example') data_file = os.path.join(base_dir, '.coverage') config_file = os.path.join(base_dir, '.coveragerc') ignore_errors = False merge_file = os.path.join(base_dir, 'merge.json') parallel = True nogit = False skip_ssl_verify = False GIT_EXP = { 'head': { 'committer_email': u'24erre@gmail.com', 'author_email': u'24erre@gmail.com', 'author_name': u'Andrea de Marco', 'message': u'Merge pull request #1 from insurancezebra/master', 'committer_name': u'Andrea de Marco', 'id': u'3e82fd5159b84bebe9bc6c9fd3959f322e6f7098' }, 'remotes': [ { 'url': 'https://github.com/z4r/python-coveralls-example.git', 'name': 'origin' } ], 'branch': 'master' } SOURCE_FILES = [ { 'source': "__author__ = 'ademarco'", 'name': 'example/__init__.py', 'coverage': [1] }, { 'source': '# coding=utf-8\nEUR = "€"\n\n\ndef amount(tariff, currency=EUR):\n return \'{0} {1:.2f}\'.format(currency, float(tariff))', 'name': 'example/exencode.py', 'coverage': [None, 1, None, None, 1, 1] }, { 'source': "def exsum(a, b):\n # A comment of a exsum\n return a + b\n\n\ndef exdiff(a, b):\n return a - b\n\n\nif __name__ == '__main__':\n print(exsum(3,4))\n print(exdiff(2,2))", 'name': 'example/exmath.py', 'coverage': [1, None, 1, None, None, 1, 0, None, None, None, None, None] } ] MERGE_SOURCE_FILES = [ { 'source': "var foo = 'bar';", 'name': "example/exjs.js", 'coverage': [1] } ] class CoverallsTestCase(TestCase): @httprettified def test_wear_ok(self): HTTPretty.register_uri( HTTPretty.POST, 'https://coveralls.io/api/v1/jobs', body='{"message":"Job #5.1","url":"https://coveralls.io/jobs/5722"}' ) sysexit = wear(Arguments) self.assertEqual(sysexit, 0) @httprettified def test_wear_ok(self): HTTPretty.register_uri( HTTPretty.POST, 'https://coveralls.io/api/v1/jobs', body='{"message":"Build processing error.","error":true,"url":""}', status=500, ) sysexit = wear(Arguments) self.assertEqual(sysexit, 1) def test_gitrepo_head(self): git = repository.gitrepo(Arguments.base_dir) self.assertEqual(git['head'], GIT_EXP['head']) def test_gitrepo_remotes(self): git = repository.gitrepo(Arguments.base_dir) self.assertEqual(git['remotes'], GIT_EXP['remotes']) def test_gitrepo_branch(self): git = repository.gitrepo(Arguments.base_dir) self.assertTrue(git['branch'] in (GIT_EXP['branch'], 'HEAD')) def test_coveralls(self): coverage = control.coveralls(data_file=Arguments.data_file, config_file=Arguments.config_file) coverage.load() self.assertEqual(coverage.coveralls(Arguments.base_dir), SOURCE_FILES) def test_coveralls_with_merge(self): coverage = control.coveralls(data_file=Arguments.data_file, config_file=Arguments.config_file) coverage.load() self.assertEqual(coverage.coveralls(Arguments.base_dir, merge_file=Arguments.merge_file), SOURCE_FILES + MERGE_SOURCE_FILES) @httprettified def test_api(self): HTTPretty.register_uri( HTTPretty.POST, 'https://coveralls.io/api/v1/jobs', body='{"message":"Job #5.1 - 100.0% Covered","url":"https://coveralls.io/jobs/5722"}' ) response = api.post( url=Arguments.coveralls_url, repo_token=Arguments.repo_token, service_job_id=Arguments.service_job_id, service_name=Arguments.service_name, git=GIT_EXP, source_files=SOURCE_FILES, parallel=Arguments.parallel ) self.assertEqual(response.json(), {u'url': u'https://coveralls.io/jobs/5722', u'message': u'Job #5.1 - 100.0% Covered'}) def test_build_file_eur(self): json_file = api.build_file( repo_token=Arguments.repo_token, service_job_id=Arguments.service_job_id, service_name=Arguments.service_name, git=GIT_EXP, source_files=SOURCE_FILES, parallel=Arguments.parallel ) self.assertEqual( json.loads(json_file.read())['source_files'][1]['source'], u'# coding=utf-8\nEUR = "€"\n\n\ndef amount(tariff, currency=EUR):\n return \'{0} {1:.2f}\'.format(currency, float(tariff))' ) class NotAFileTestCase(TestCase): def setUp(self): coverage = coveralls(data_file=Arguments.data_file, config_file=Arguments.config_file) coverage.load() self.reporter = CoverallsReporter(coverage, coverage.config) self.reporter.find_file_reporters(None) self.reporter.file_reporters.append(FileReporter('NotAFile.py')) def test_report_raises(self): self.assertRaises(IOError, self.reporter.report, Arguments.base_dir) def test_report_continue(self): self.assertEqual(self.reporter.report(Arguments.base_dir, ignore_errors=True), SOURCE_FILES) class NotAPythonTestCase(TestCase): def setUp(self): coverage = coveralls(data_file=Arguments.data_file, config_file=Arguments.config_file) coverage.load() self.reporter = CoverallsReporter(coverage, coverage.config) self.reporter.find_file_reporters(None) self.reporter.file_reporters.append(PythonFileReporter('LICENSE', coverage=coverage)) def test_report_raises(self): self.assertRaises(NotPython, self.reporter.report, Arguments.base_dir) def test_report_continue(self): self.assertEqual(self.reporter.report(Arguments.base_dir, ignore_errors=True), SOURCE_FILES) ================================================ FILE: pytest.ini ================================================ [pytest] pep8ignore = E501 ================================================ FILE: setup.cfg ================================================ [wheel] universal = 1 ================================================ FILE: setup.py ================================================ from setuptools import setup, find_packages import sys import os wd = os.path.dirname(os.path.abspath(__file__)) os.chdir(wd) sys.path.insert(1, wd) name = 'python-coveralls' pkg = __import__('coveralls') author, email = pkg.__author__.rsplit(' ', 1) email = email.strip('<>') version = pkg.__version__ classifiers = pkg.__classifiers__ readme = open(os.path.join(wd, 'README.rst'), 'r').readlines() description = readme[1] long_description = ''.join(readme) reqs = [ 'PyYAML', 'requests', 'coverage', 'six', ] if sys.version_info < (2, 7): reqs.append('argparse') reqs.append('subprocess32') setup( name=name, version=version, author=author, author_email=email, url='http://github.com/z4r/python-coveralls', maintainer=author, maintainer_email=email, description=description, long_description=long_description, classifiers=classifiers, install_requires=reqs, packages=find_packages(), license='Apache License 2.0', keywords='coveralls.io', entry_points={ 'console_scripts': [ 'coveralls = coveralls:wear', ], }, ) ================================================ FILE: test_requirements.txt ================================================ pytest pytest-pep8 pytest-cov httpretty