coverage-conditional-plugin


Namecoverage-conditional-plugin JSON
Version 0.9.0 PyPI version JSON
download
home_pagehttps://github.com/wemake-services/coverage-conditional-plugin
SummaryConditional coverage based on any rules you define!
upload_time2023-06-02 10:25:10
maintainer
docs_urlNone
authorsobolevn
requires_python>=3.7,<4.0
licenseMIT
keywords coverage coverage.py pytest-cov testing
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # coverage-conditional-plugin

[![wemake.services](https://img.shields.io/badge/%20-wemake.services-green.svg?label=%20&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC%2FxhBQAAAAFzUkdCAK7OHOkAAAAbUExURQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP%2F%2F%2F5TvxDIAAAAIdFJOUwAjRA8xXANAL%2Bv0SAAAADNJREFUGNNjYCAIOJjRBdBFWMkVQeGzcHAwksJnAPPZGOGAASzPzAEHEGVsLExQwE7YswCb7AFZSF3bbAAAAABJRU5ErkJggg%3D%3D)](https://wemake.services)
[![Build Status](https://github.com/wemake-services/coverage-conditional-plugin/workflows/test/badge.svg?branch=master&event=push)](https://github.com/wemake-services/coverage-conditional-plugin/actions?query=workflow%3Atest)
[![codecov](https://codecov.io/gh/wemake-services/coverage-conditional-plugin/branch/master/graph/badge.svg)](https://codecov.io/gh/wemake-services/coverage-conditional-plugin)
[![Python Version](https://img.shields.io/pypi/pyversions/coverage-conditional-plugin.svg)](https://pypi.org/project/coverage-conditional-plugin/)
[![wemake-python-styleguide](https://img.shields.io/badge/style-wemake-000000.svg)](https://github.com/wemake-services/wemake-python-styleguide)

Conditional coverage based on any rules you define!

Some projects have different parts that relies on different environments:

- Python version, some code is only executed on specific versions and ignored on others
- OS version, some code might be Windows, Mac, or Linux only
- External packages, some code is only executed when some 3rd party package is installed

Current best practice is to use `# pragma: no cover` for this places in our project.
This project allows to use configurable pragmas
that include code to the coverage if some condition evaluates to true,
and fallback to ignoring this code when condition is false.

Read [the announcing post](https://sobolevn.me/2020/02/conditional-coverage).


## Installation

```bash
pip install coverage-conditional-plugin
```

Then you will need to add to your `setup.cfg` or `.coveragerc` file
some extra configuration:

```ini
[coverage:run]
# Here we specify plugins for coverage to be used:
plugins =
  coverage_conditional_plugin

[coverage:coverage_conditional_plugin]
# Here we specify files to conditionally omit:
omit =
  "sys_platform == 'win32'":
      "my_project/omit*.py"
      "my_project/win.py"
# Here we specify our pragma rules:
rules =
  "sys_version_info >= (3, 8)": py-gte-38
  "is_installed('mypy')": has-mypy

```

Or to your `pyproject.toml`:

```toml
[tool.coverage.run]
# Here we specify plugins for coverage to be used:
plugins = ["coverage_conditional_plugin"]

[tool.coverage.coverage_conditional_plugin.omit]
# Here we specify files to conditionally omit:
"my_project/omit*.py" = "sys_platform == 'win32'"

[tool.coverage.coverage_conditional_plugin.rules]
# Here we specify our pragma rules:
py-gte-38 = "sys_version_info >= (3, 8)"
has-mypy = "is_installed('mypy')"
```


Adapt rules to suit your needs!


## Example

Imagine that we have this code:

```python
try:  # pragma: has-django
    import django
except ImportError:  # pragma: has-no-django
    django = None

def run_if_django_is_installed():
    if django is not None:  # pragma: has-django
        ...
```

And here's the configuration you might use:

```ini
[coverage:coverage_conditional_plugin]
rules =
  "is_installed('django')": has-django
  "not is_installed('django')": has-no-django

```

When running tests with and without `django` installed
you will have `100%` coverage in both cases.

But, different lines will be included.
With `django` installed it will include
both `try:` and `if django is not None:` conditions.

When running without `django` installed,
it will include `except ImportError:` line.


## Writing pragma rules

Format for pragma rules is:

```
"pragma-condition": pragma-name
```

Code inside `"pragma-condition"` is evaluted with `eval`.
Make sure that the input you pass there is trusted!
`"pragma-condition"` must return `bool` value after evaluation.

We support all environment markers specified in [PEP-496](https://www.python.org/dev/peps/pep-0496/).
See [Strings](https://www.python.org/dev/peps/pep-0496/#strings)
and [Version Numbers](https://www.python.org/dev/peps/pep-0496/#version-numbers)
sections for available values. Also, we provide a bunch of additional markers:

- `sys_version_info` is the same as [`sys.version_info`](https://docs.python.org/3/library/sys.html#sys.version_info)
- `os_environ` is the same as [`os.environ`](https://docs.python.org/3/library/os.html#os.environ)
- `is_installed` is our custom function that tries to import the passed string, returns `bool` value
- `package_version` is our custom function that tries to get package version from `pkg_resources` and returns its [parsed version](https://packaging.pypa.io/en/latest/version/#packaging.version.parse)

Use `get_env_info` to get values for the current environment:

```python
from coverage_conditional_plugin import get_env_info

get_env_info()
```


## Writing omits

Omits allow entire files to be conditionally omitted from coverage measurement.

The TOML format for omits is:

```toml
[tool.coverage.coverage_conditional_plugin.omit]
"pragma-condition" = ["project/prefix*.py", "project/filename.py"]
# or
"pragma-condition" = "project/filename.py"
```

**Note**: `ini` format is not supported for `omit` configuration option,
because there's no easy way to parse `ini` complex configuration. 
PRs with the fix are welcome!

File name patterns should follow coverage.py's `[run] omit` syntax.
See [coverage.py](https://coverage.readthedocs.io/en/stable/source.html).


## License

[MIT](https://github.com/wemake.services/coverage-conditional-plugin/blob/master/LICENSE)

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/wemake-services/coverage-conditional-plugin",
    "name": "coverage-conditional-plugin",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.7,<4.0",
    "maintainer_email": "",
    "keywords": "coverage,coverage.py,pytest-cov,testing",
    "author": "sobolevn",
    "author_email": "mail@sobolevn.me",
    "download_url": "https://files.pythonhosted.org/packages/2e/6e/82f411d325a38cc24289060ca5f80d990ee8d026f4de9782006acf061f9b/coverage_conditional_plugin-0.9.0.tar.gz",
    "platform": null,
    "description": "# coverage-conditional-plugin\n\n[![wemake.services](https://img.shields.io/badge/%20-wemake.services-green.svg?label=%20&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC%2FxhBQAAAAFzUkdCAK7OHOkAAAAbUExURQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP%2F%2F%2F5TvxDIAAAAIdFJOUwAjRA8xXANAL%2Bv0SAAAADNJREFUGNNjYCAIOJjRBdBFWMkVQeGzcHAwksJnAPPZGOGAASzPzAEHEGVsLExQwE7YswCb7AFZSF3bbAAAAABJRU5ErkJggg%3D%3D)](https://wemake.services)\n[![Build Status](https://github.com/wemake-services/coverage-conditional-plugin/workflows/test/badge.svg?branch=master&event=push)](https://github.com/wemake-services/coverage-conditional-plugin/actions?query=workflow%3Atest)\n[![codecov](https://codecov.io/gh/wemake-services/coverage-conditional-plugin/branch/master/graph/badge.svg)](https://codecov.io/gh/wemake-services/coverage-conditional-plugin)\n[![Python Version](https://img.shields.io/pypi/pyversions/coverage-conditional-plugin.svg)](https://pypi.org/project/coverage-conditional-plugin/)\n[![wemake-python-styleguide](https://img.shields.io/badge/style-wemake-000000.svg)](https://github.com/wemake-services/wemake-python-styleguide)\n\nConditional coverage based on any rules you define!\n\nSome projects have different parts that relies on different environments:\n\n- Python version, some code is only executed on specific versions and ignored on others\n- OS version, some code might be Windows, Mac, or Linux only\n- External packages, some code is only executed when some 3rd party package is installed\n\nCurrent best practice is to use `# pragma: no cover` for this places in our project.\nThis project allows to use configurable pragmas\nthat include code to the coverage if some condition evaluates to true,\nand fallback to ignoring this code when condition is false.\n\nRead [the announcing post](https://sobolevn.me/2020/02/conditional-coverage).\n\n\n## Installation\n\n```bash\npip install coverage-conditional-plugin\n```\n\nThen you will need to add to your `setup.cfg` or `.coveragerc` file\nsome extra configuration:\n\n```ini\n[coverage:run]\n# Here we specify plugins for coverage to be used:\nplugins =\n  coverage_conditional_plugin\n\n[coverage:coverage_conditional_plugin]\n# Here we specify files to conditionally omit:\nomit =\n  \"sys_platform == 'win32'\":\n      \"my_project/omit*.py\"\n      \"my_project/win.py\"\n# Here we specify our pragma rules:\nrules =\n  \"sys_version_info >= (3, 8)\": py-gte-38\n  \"is_installed('mypy')\": has-mypy\n\n```\n\nOr to your `pyproject.toml`:\n\n```toml\n[tool.coverage.run]\n# Here we specify plugins for coverage to be used:\nplugins = [\"coverage_conditional_plugin\"]\n\n[tool.coverage.coverage_conditional_plugin.omit]\n# Here we specify files to conditionally omit:\n\"my_project/omit*.py\" = \"sys_platform == 'win32'\"\n\n[tool.coverage.coverage_conditional_plugin.rules]\n# Here we specify our pragma rules:\npy-gte-38 = \"sys_version_info >= (3, 8)\"\nhas-mypy = \"is_installed('mypy')\"\n```\n\n\nAdapt rules to suit your needs!\n\n\n## Example\n\nImagine that we have this code:\n\n```python\ntry:  # pragma: has-django\n    import django\nexcept ImportError:  # pragma: has-no-django\n    django = None\n\ndef run_if_django_is_installed():\n    if django is not None:  # pragma: has-django\n        ...\n```\n\nAnd here's the configuration you might use:\n\n```ini\n[coverage:coverage_conditional_plugin]\nrules =\n  \"is_installed('django')\": has-django\n  \"not is_installed('django')\": has-no-django\n\n```\n\nWhen running tests with and without `django` installed\nyou will have `100%` coverage in both cases.\n\nBut, different lines will be included.\nWith `django` installed it will include\nboth `try:` and `if django is not None:` conditions.\n\nWhen running without `django` installed,\nit will include `except ImportError:` line.\n\n\n## Writing pragma rules\n\nFormat for pragma rules is:\n\n```\n\"pragma-condition\": pragma-name\n```\n\nCode inside `\"pragma-condition\"` is evaluted with `eval`.\nMake sure that the input you pass there is trusted!\n`\"pragma-condition\"` must return `bool` value after evaluation.\n\nWe support all environment markers specified in [PEP-496](https://www.python.org/dev/peps/pep-0496/).\nSee [Strings](https://www.python.org/dev/peps/pep-0496/#strings)\nand [Version Numbers](https://www.python.org/dev/peps/pep-0496/#version-numbers)\nsections for available values. Also, we provide a bunch of additional markers:\n\n- `sys_version_info` is the same as [`sys.version_info`](https://docs.python.org/3/library/sys.html#sys.version_info)\n- `os_environ` is the same as [`os.environ`](https://docs.python.org/3/library/os.html#os.environ)\n- `is_installed` is our custom function that tries to import the passed string, returns `bool` value\n- `package_version` is our custom function that tries to get package version from `pkg_resources` and returns its [parsed version](https://packaging.pypa.io/en/latest/version/#packaging.version.parse)\n\nUse `get_env_info` to get values for the current environment:\n\n```python\nfrom coverage_conditional_plugin import get_env_info\n\nget_env_info()\n```\n\n\n## Writing omits\n\nOmits allow entire files to be conditionally omitted from coverage measurement.\n\nThe TOML format for omits is:\n\n```toml\n[tool.coverage.coverage_conditional_plugin.omit]\n\"pragma-condition\" = [\"project/prefix*.py\", \"project/filename.py\"]\n# or\n\"pragma-condition\" = \"project/filename.py\"\n```\n\n**Note**: `ini` format is not supported for `omit` configuration option,\nbecause there's no easy way to parse `ini` complex configuration. \nPRs with the fix are welcome!\n\nFile name patterns should follow coverage.py's `[run] omit` syntax.\nSee [coverage.py](https://coverage.readthedocs.io/en/stable/source.html).\n\n\n## License\n\n[MIT](https://github.com/wemake.services/coverage-conditional-plugin/blob/master/LICENSE)\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Conditional coverage based on any rules you define!",
    "version": "0.9.0",
    "project_urls": {
        "Funding": "https://github.com/sponsors/wemake-services",
        "Homepage": "https://github.com/wemake-services/coverage-conditional-plugin",
        "Repository": "https://github.com/wemake-services/coverage-conditional-plugin"
    },
    "split_keywords": [
        "coverage",
        "coverage.py",
        "pytest-cov",
        "testing"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "0683df10dd1911cb1695274da836e786ade7eaace9ed625b14056eb0bd6117d8",
                "md5": "d20bf7f3753fb238600d8a15d87726da",
                "sha256": "1b37bc469019d2ab5b01f5eee453abe1846b3431e64e209720c2a9ec4afb8130"
            },
            "downloads": -1,
            "filename": "coverage_conditional_plugin-0.9.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "d20bf7f3753fb238600d8a15d87726da",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7,<4.0",
            "size": 7317,
            "upload_time": "2023-06-02T10:25:08",
            "upload_time_iso_8601": "2023-06-02T10:25:08.177890Z",
            "url": "https://files.pythonhosted.org/packages/06/83/df10dd1911cb1695274da836e786ade7eaace9ed625b14056eb0bd6117d8/coverage_conditional_plugin-0.9.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "2e6e82f411d325a38cc24289060ca5f80d990ee8d026f4de9782006acf061f9b",
                "md5": "d59aca9532802aa16a132cde3c50e799",
                "sha256": "6893dab0542695dbd5ea714281dae0dfec8d0e36480ba32d839e9fa7344f8215"
            },
            "downloads": -1,
            "filename": "coverage_conditional_plugin-0.9.0.tar.gz",
            "has_sig": false,
            "md5_digest": "d59aca9532802aa16a132cde3c50e799",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7,<4.0",
            "size": 10579,
            "upload_time": "2023-06-02T10:25:10",
            "upload_time_iso_8601": "2023-06-02T10:25:10.166627Z",
            "url": "https://files.pythonhosted.org/packages/2e/6e/82f411d325a38cc24289060ca5f80d990ee8d026f4de9782006acf061f9b/coverage_conditional_plugin-0.9.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-06-02 10:25:10",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "wemake-services",
    "github_project": "coverage-conditional-plugin",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "coverage-conditional-plugin"
}
        
Elapsed time: 0.07365s