Merge pull request #4190 from nicoddemus/merge-master-into-features
Merge master into features
This commit is contained in:
commit
b432f1207c
|
@ -93,12 +93,6 @@ after_success:
|
||||||
coverage xml --ignore-errors
|
coverage xml --ignore-errors
|
||||||
coverage report -m --ignore-errors
|
coverage report -m --ignore-errors
|
||||||
bash <(curl -s https://codecov.io/bash) -Z -X gcov -X coveragepy -X search -X xcode -X gcovout -X fix -f coverage.xml -F "${TOXENV//-/,},linux"
|
bash <(curl -s https://codecov.io/bash) -Z -X gcov -X coveragepy -X search -X xcode -X gcovout -X fix -f coverage.xml -F "${TOXENV//-/,},linux"
|
||||||
|
|
||||||
# Coveralls does not support merged reports.
|
|
||||||
if [[ "$TOXENV" = py37 ]]; then
|
|
||||||
pip install coveralls
|
|
||||||
coveralls
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
|
|
|
@ -45,7 +45,7 @@ Deprecations
|
||||||
Users should just ``import pytest`` and access those objects using the ``pytest`` module.
|
Users should just ``import pytest`` and access those objects using the ``pytest`` module.
|
||||||
|
|
||||||
* ``request.cached_setup``, this was the precursor of the setup/teardown mechanism available to fixtures. You can
|
* ``request.cached_setup``, this was the precursor of the setup/teardown mechanism available to fixtures. You can
|
||||||
consult `funcarg comparision section in the docs <https://docs.pytest.org/en/latest/funcarg_compare.html>`_.
|
consult `funcarg comparison section in the docs <https://docs.pytest.org/en/latest/funcarg_compare.html>`_.
|
||||||
|
|
||||||
* Using objects named ``"Class"`` as a way to customize the type of nodes that are collected in ``Collector``
|
* Using objects named ``"Class"`` as a way to customize the type of nodes that are collected in ``Collector``
|
||||||
subclasses has been deprecated. Users instead should use ``pytest_collect_make_item`` to customize node types during
|
subclasses has been deprecated. Users instead should use ``pytest_collect_make_item`` to customize node types during
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fix unescaped XML raw objects in JUnit report for skipped tests
|
|
@ -0,0 +1 @@
|
||||||
|
Pin ``setuptools>=40.0`` to support ``py_modules`` in ``setup.cfg``
|
|
@ -0,0 +1 @@
|
||||||
|
Restore the tmpdir behaviour of symlinking the current test run.
|
|
@ -56,7 +56,7 @@ This should be updated to make use of standard fixture mechanisms:
|
||||||
session.close()
|
session.close()
|
||||||
|
|
||||||
|
|
||||||
You can consult `funcarg comparision section in the docs <https://docs.pytest.org/en/latest/funcarg_compare.html>`_ for
|
You can consult `funcarg comparison section in the docs <https://docs.pytest.org/en/latest/funcarg_compare.html>`_ for
|
||||||
more information.
|
more information.
|
||||||
|
|
||||||
This has been documented as deprecated for years, but only now we are actually emitting deprecation warnings.
|
This has been documented as deprecated for years, but only now we are actually emitting deprecation warnings.
|
||||||
|
@ -68,7 +68,7 @@ Using ``Class`` in custom Collectors
|
||||||
.. deprecated:: 3.9
|
.. deprecated:: 3.9
|
||||||
|
|
||||||
Using objects named ``"Class"`` as a way to customize the type of nodes that are collected in ``Collector``
|
Using objects named ``"Class"`` as a way to customize the type of nodes that are collected in ``Collector``
|
||||||
subclasses has been deprecated. Users instead should use ``pytest_collect_make_item`` to customize node types during
|
subclasses has been deprecated. Users instead should use ``pytest_pycollect_makeitem`` to customize node types during
|
||||||
collection.
|
collection.
|
||||||
|
|
||||||
This issue should affect only advanced plugins who create new collection types, so if you see this warning
|
This issue should affect only advanced plugins who create new collection types, so if you see this warning
|
||||||
|
|
|
@ -75,60 +75,6 @@ Both ``-W`` command-line option and ``filterwarnings`` ini option are based on P
|
||||||
`-W option`_ and `warnings.simplefilter`_, so please refer to those sections in the Python
|
`-W option`_ and `warnings.simplefilter`_, so please refer to those sections in the Python
|
||||||
documentation for other examples and advanced usage.
|
documentation for other examples and advanced usage.
|
||||||
|
|
||||||
Disabling warning summary
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
Although not recommended, you can use the ``--disable-warnings`` command-line option to suppress the
|
|
||||||
warning summary entirely from the test run output.
|
|
||||||
|
|
||||||
Disabling warning capture entirely
|
|
||||||
----------------------------------
|
|
||||||
|
|
||||||
This plugin is enabled by default but can be disabled entirely in your ``pytest.ini`` file with:
|
|
||||||
|
|
||||||
.. code-block:: ini
|
|
||||||
|
|
||||||
[pytest]
|
|
||||||
addopts = -p no:warnings
|
|
||||||
|
|
||||||
Or passing ``-p no:warnings`` in the command-line. This might be useful if your test suites handles warnings
|
|
||||||
using an external system.
|
|
||||||
|
|
||||||
|
|
||||||
.. _`deprecation-warnings`:
|
|
||||||
|
|
||||||
DeprecationWarning and PendingDeprecationWarning
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
.. versionadded:: 3.8
|
|
||||||
.. versionchanged:: 3.9
|
|
||||||
|
|
||||||
By default pytest will display ``DeprecationWarning`` and ``PendingDeprecationWarning``.
|
|
||||||
|
|
||||||
Sometimes it is useful to hide some specific deprecation warnings that happen in code that you have no control over
|
|
||||||
(such as third-party libraries), in which case you might use the standard warning filters options (ini or marks).
|
|
||||||
For example:
|
|
||||||
|
|
||||||
.. code-block:: ini
|
|
||||||
|
|
||||||
[pytest]
|
|
||||||
filterwarnings =
|
|
||||||
ignore:.*U.*mode is deprecated:DeprecationWarning
|
|
||||||
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
If warnings are configured at the interpreter level, using
|
|
||||||
the `PYTHONWARNINGS <https://docs.python.org/3/using/cmdline.html#envvar-PYTHONWARNINGS>`_ environment variable or the
|
|
||||||
``-W`` command-line option, pytest will not configure any filters by default.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
This feature makes pytest more compliant with `PEP-0506 <https://www.python.org/dev/peps/pep-0565/#recommended-filter-settings-for-test-runners>`_ which suggests that those warnings should
|
|
||||||
be shown by default by test runners, but pytest doesn't follow ``PEP-0506`` completely because resetting all
|
|
||||||
warning filters like suggested in the PEP will break existing test suites that configure warning filters themselves
|
|
||||||
by calling ``warnings.simplefilter`` (see issue `#2430 <https://github.com/pytest-dev/pytest/issues/2430>`_
|
|
||||||
for an example of that).
|
|
||||||
|
|
||||||
|
|
||||||
.. _`filterwarnings`:
|
.. _`filterwarnings`:
|
||||||
|
|
||||||
``@pytest.mark.filterwarnings``
|
``@pytest.mark.filterwarnings``
|
||||||
|
@ -167,24 +113,6 @@ decorator or to all tests in a module by setting the ``pytestmark`` variable:
|
||||||
pytestmark = pytest.mark.filterwarnings("error")
|
pytestmark = pytest.mark.filterwarnings("error")
|
||||||
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
Except for these features, pytest does not change the python warning filter; it only captures
|
|
||||||
and displays the warnings which are issued with respect to the currently configured filter,
|
|
||||||
including changes to the filter made by test functions or by the system under test.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
``DeprecationWarning`` and ``PendingDeprecationWarning`` are hidden by the standard library
|
|
||||||
by default so you have to explicitly configure them to be displayed in your ``pytest.ini``:
|
|
||||||
|
|
||||||
.. code-block:: ini
|
|
||||||
|
|
||||||
[pytest]
|
|
||||||
filterwarnings =
|
|
||||||
once::DeprecationWarning
|
|
||||||
once::PendingDeprecationWarning
|
|
||||||
|
|
||||||
|
|
||||||
*Credits go to Florian Schulze for the reference implementation in the* `pytest-warnings`_
|
*Credits go to Florian Schulze for the reference implementation in the* `pytest-warnings`_
|
||||||
*plugin.*
|
*plugin.*
|
||||||
|
@ -193,6 +121,102 @@ decorator or to all tests in a module by setting the ``pytestmark`` variable:
|
||||||
.. _warnings.simplefilter: https://docs.python.org/3/library/warnings.html#warnings.simplefilter
|
.. _warnings.simplefilter: https://docs.python.org/3/library/warnings.html#warnings.simplefilter
|
||||||
.. _`pytest-warnings`: https://github.com/fschulze/pytest-warnings
|
.. _`pytest-warnings`: https://github.com/fschulze/pytest-warnings
|
||||||
|
|
||||||
|
Disabling warnings summary
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
Although not recommended, you can use the ``--disable-warnings`` command-line option to suppress the
|
||||||
|
warning summary entirely from the test run output.
|
||||||
|
|
||||||
|
Disabling warning capture entirely
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
This plugin is enabled by default but can be disabled entirely in your ``pytest.ini`` file with:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
[pytest]
|
||||||
|
addopts = -p no:warnings
|
||||||
|
|
||||||
|
Or passing ``-p no:warnings`` in the command-line. This might be useful if your test suites handles warnings
|
||||||
|
using an external system.
|
||||||
|
|
||||||
|
|
||||||
|
.. _`deprecation-warnings`:
|
||||||
|
|
||||||
|
DeprecationWarning and PendingDeprecationWarning
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
.. versionadded:: 3.8
|
||||||
|
.. versionchanged:: 3.9
|
||||||
|
|
||||||
|
By default pytest will display ``DeprecationWarning`` and ``PendingDeprecationWarning`` warnings from
|
||||||
|
user code and third-party libraries, as recommended by `PEP-0506 <https://www.python.org/dev/peps/pep-0565>`_.
|
||||||
|
This helps users keep their code modern and avoid breakages when deprecated warnings are effectively removed.
|
||||||
|
|
||||||
|
Sometimes it is useful to hide some specific deprecation warnings that happen in code that you have no control over
|
||||||
|
(such as third-party libraries), in which case you might use the warning filters options (ini or marks) to ignore
|
||||||
|
those warnings.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
.. code-block:: ini
|
||||||
|
|
||||||
|
[pytest]
|
||||||
|
filterwarnings =
|
||||||
|
ignore:.*U.*mode is deprecated:DeprecationWarning
|
||||||
|
|
||||||
|
|
||||||
|
This will ignore all warnings of type ``DeprecationWarning`` where the start of the message matches
|
||||||
|
the regular expression ``".*U.*mode is deprecated"``.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
If warnings are configured at the interpreter level, using
|
||||||
|
the `PYTHONWARNINGS <https://docs.python.org/3/using/cmdline.html#envvar-PYTHONWARNINGS>`_ environment variable or the
|
||||||
|
``-W`` command-line option, pytest will not configure any filters by default.
|
||||||
|
|
||||||
|
Also pytest doesn't follow ``PEP-0506`` suggestion of resetting all warning filters because
|
||||||
|
it might break test suites that configure warning filters themselves
|
||||||
|
by calling ``warnings.simplefilter`` (see issue `#2430 <https://github.com/pytest-dev/pytest/issues/2430>`_
|
||||||
|
for an example of that).
|
||||||
|
|
||||||
|
|
||||||
|
.. _`ensuring a function triggers a deprecation warning`:
|
||||||
|
|
||||||
|
.. _ensuring_function_triggers:
|
||||||
|
|
||||||
|
Ensuring code triggers a deprecation warning
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
You can also call a global helper for checking
|
||||||
|
that a certain function call triggers a ``DeprecationWarning`` or
|
||||||
|
``PendingDeprecationWarning``::
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
def test_global():
|
||||||
|
pytest.deprecated_call(myfunction, 17)
|
||||||
|
|
||||||
|
By default, ``DeprecationWarning`` and ``PendingDeprecationWarning`` will not be
|
||||||
|
caught when using ``pytest.warns`` or ``recwarn`` because default Python warnings filters hide
|
||||||
|
them. If you wish to record them in your own code, use the
|
||||||
|
command ``warnings.simplefilter('always')``::
|
||||||
|
|
||||||
|
import warnings
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
def test_deprecation(recwarn):
|
||||||
|
warnings.simplefilter('always')
|
||||||
|
warnings.warn("deprecated", DeprecationWarning)
|
||||||
|
assert len(recwarn) == 1
|
||||||
|
assert recwarn.pop(DeprecationWarning)
|
||||||
|
|
||||||
|
You can also use it as a contextmanager::
|
||||||
|
|
||||||
|
def test_global():
|
||||||
|
with pytest.deprecated_call():
|
||||||
|
myobject.deprecated_method()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. _`asserting warnings`:
|
.. _`asserting warnings`:
|
||||||
|
|
||||||
|
@ -299,43 +323,6 @@ warnings, or index into it to get a particular recorded warning.
|
||||||
|
|
||||||
Full API: :class:`WarningsRecorder`.
|
Full API: :class:`WarningsRecorder`.
|
||||||
|
|
||||||
.. _`ensuring a function triggers a deprecation warning`:
|
|
||||||
|
|
||||||
.. _ensuring_function_triggers:
|
|
||||||
|
|
||||||
Ensuring a function triggers a deprecation warning
|
|
||||||
-------------------------------------------------------
|
|
||||||
|
|
||||||
You can also call a global helper for checking
|
|
||||||
that a certain function call triggers a ``DeprecationWarning`` or
|
|
||||||
``PendingDeprecationWarning``::
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
def test_global():
|
|
||||||
pytest.deprecated_call(myfunction, 17)
|
|
||||||
|
|
||||||
By default, ``DeprecationWarning`` and ``PendingDeprecationWarning`` will not be
|
|
||||||
caught when using ``pytest.warns`` or ``recwarn`` because default Python warnings filters hide
|
|
||||||
them. If you wish to record them in your own code, use the
|
|
||||||
command ``warnings.simplefilter('always')``::
|
|
||||||
|
|
||||||
import warnings
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
def test_deprecation(recwarn):
|
|
||||||
warnings.simplefilter('always')
|
|
||||||
warnings.warn("deprecated", DeprecationWarning)
|
|
||||||
assert len(recwarn) == 1
|
|
||||||
assert recwarn.pop(DeprecationWarning)
|
|
||||||
|
|
||||||
You can also use it as a contextmanager::
|
|
||||||
|
|
||||||
def test_global():
|
|
||||||
with pytest.deprecated_call():
|
|
||||||
myobject.deprecated_method()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. _internal-warnings:
|
.. _internal-warnings:
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = [
|
requires = [
|
||||||
# sync with setup.py until we discard non-pep-517/518
|
# sync with setup.py until we discard non-pep-517/518
|
||||||
"setuptools>=30.3",
|
"setuptools>=40.0",
|
||||||
"setuptools-scm",
|
"setuptools-scm",
|
||||||
"wheel",
|
"wheel",
|
||||||
]
|
]
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -26,7 +26,7 @@ if "_PYTEST_SETUP_SKIP_PLUGGY_DEP" not in os.environ:
|
||||||
def main():
|
def main():
|
||||||
setup(
|
setup(
|
||||||
use_scm_version={"write_to": "src/_pytest/_version.py"},
|
use_scm_version={"write_to": "src/_pytest/_version.py"},
|
||||||
setup_requires=["setuptools-scm", "setuptools>=30.3"],
|
setup_requires=["setuptools-scm", "setuptools>=40.0"],
|
||||||
package_dir={"": "src"},
|
package_dir={"": "src"},
|
||||||
install_requires=INSTALL_REQUIRES,
|
install_requires=INSTALL_REQUIRES,
|
||||||
)
|
)
|
||||||
|
|
|
@ -221,12 +221,14 @@ class _NodeReporter(object):
|
||||||
else:
|
else:
|
||||||
filename, lineno, skipreason = report.longrepr
|
filename, lineno, skipreason = report.longrepr
|
||||||
if skipreason.startswith("Skipped: "):
|
if skipreason.startswith("Skipped: "):
|
||||||
skipreason = bin_xml_escape(skipreason[9:])
|
skipreason = skipreason[9:]
|
||||||
|
details = "%s:%s: %s" % (filename, lineno, skipreason)
|
||||||
|
|
||||||
self.append(
|
self.append(
|
||||||
Junit.skipped(
|
Junit.skipped(
|
||||||
"%s:%s: %s" % (filename, lineno, skipreason),
|
bin_xml_escape(details),
|
||||||
type="pytest.skip",
|
type="pytest.skip",
|
||||||
message=skipreason,
|
message=bin_xml_escape(skipreason),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.write_captured_output(report)
|
self.write_captured_output(report)
|
||||||
|
|
|
@ -279,7 +279,7 @@ class LogCaptureFixture(object):
|
||||||
Unlike 'records', which contains the format string and parameters for interpolation, log messages in this list
|
Unlike 'records', which contains the format string and parameters for interpolation, log messages in this list
|
||||||
are all interpolated.
|
are all interpolated.
|
||||||
Unlike 'text', which contains the output from the handler, log messages in this list are unadorned with
|
Unlike 'text', which contains the output from the handler, log messages in this list are unadorned with
|
||||||
levels, timestamps, etc, making exact comparisions more reliable.
|
levels, timestamps, etc, making exact comparisons more reliable.
|
||||||
|
|
||||||
Note that traceback or stack info (from :func:`logging.exception` or the `exc_info` or `stack_info` arguments
|
Note that traceback or stack info (from :func:`logging.exception` or the `exc_info` or `stack_info` arguments
|
||||||
to the logging functions) is not included, as this is added by the formatter in the handler.
|
to the logging functions) is not included, as this is added by the formatter in the handler.
|
||||||
|
|
|
@ -100,6 +100,26 @@ else:
|
||||||
_max = max
|
_max = max
|
||||||
|
|
||||||
|
|
||||||
|
def _force_symlink(root, target, link_to):
|
||||||
|
"""helper to create the current symlink
|
||||||
|
|
||||||
|
its full of race conditions that are reasonably ok to ignore
|
||||||
|
for the contex of best effort linking to the latest testrun
|
||||||
|
|
||||||
|
the presumption being thatin case of much parallelism
|
||||||
|
the inaccuracy is going to be acceptable
|
||||||
|
"""
|
||||||
|
current_symlink = root.joinpath(target)
|
||||||
|
try:
|
||||||
|
current_symlink.unlink()
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
current_symlink.symlink_to(link_to)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def make_numbered_dir(root, prefix):
|
def make_numbered_dir(root, prefix):
|
||||||
"""create a directory with a increased number as suffix for the given prefix"""
|
"""create a directory with a increased number as suffix for the given prefix"""
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
|
@ -112,6 +132,7 @@ def make_numbered_dir(root, prefix):
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
_force_symlink(root, prefix + "current", new_path)
|
||||||
return new_path
|
return new_path
|
||||||
else:
|
else:
|
||||||
raise EnvironmentError(
|
raise EnvironmentError(
|
||||||
|
|
|
@ -1222,3 +1222,19 @@ def test_set_suite_name(testdir, suite_name):
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
node.assert_attr(name=expected)
|
node.assert_attr(name=expected)
|
||||||
|
|
||||||
|
|
||||||
|
def test_escaped_skipreason_issue3533(testdir):
|
||||||
|
testdir.makepyfile(
|
||||||
|
"""
|
||||||
|
import pytest
|
||||||
|
@pytest.mark.skip(reason='1 <> 2')
|
||||||
|
def test_skip():
|
||||||
|
pass
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
_, dom = runandparse(testdir)
|
||||||
|
node = dom.find_first_by_tag("testcase")
|
||||||
|
snode = node.find_first_by_tag("skipped")
|
||||||
|
assert "1 <> 2" in snode.text
|
||||||
|
snode.assert_attr(message="1 <> 2")
|
||||||
|
|
|
@ -196,6 +196,12 @@ class TestNumberedDir(object):
|
||||||
assert d.name.startswith(self.PREFIX)
|
assert d.name.startswith(self.PREFIX)
|
||||||
assert d.name.endswith(str(i))
|
assert d.name.endswith(str(i))
|
||||||
|
|
||||||
|
symlink = tmp_path.joinpath(self.PREFIX + "current")
|
||||||
|
if symlink.exists():
|
||||||
|
# unix
|
||||||
|
assert symlink.is_symlink()
|
||||||
|
assert symlink.resolve() == d.resolve()
|
||||||
|
|
||||||
def test_cleanup_lock_create(self, tmp_path):
|
def test_cleanup_lock_create(self, tmp_path):
|
||||||
d = tmp_path.joinpath("test")
|
d = tmp_path.joinpath("test")
|
||||||
d.mkdir()
|
d.mkdir()
|
||||||
|
@ -244,7 +250,7 @@ class TestNumberedDir(object):
|
||||||
|
|
||||||
def test_cleanup_keep(self, tmp_path):
|
def test_cleanup_keep(self, tmp_path):
|
||||||
self._do_cleanup(tmp_path)
|
self._do_cleanup(tmp_path)
|
||||||
a, b = tmp_path.iterdir()
|
a, b = (x for x in tmp_path.iterdir() if not x.is_symlink())
|
||||||
print(a, b)
|
print(a, b)
|
||||||
|
|
||||||
def test_cleanup_locked(self, tmp_path):
|
def test_cleanup_locked(self, tmp_path):
|
||||||
|
|
2
tox.ini
2
tox.ini
|
@ -21,7 +21,7 @@ commands =
|
||||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest --lsof
|
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest --lsof
|
||||||
coverage: coverage combine
|
coverage: coverage combine
|
||||||
coverage: coverage report
|
coverage: coverage report
|
||||||
passenv = USER USERNAME COVERAGE_*
|
passenv = USER USERNAME COVERAGE_* TRAVIS
|
||||||
setenv =
|
setenv =
|
||||||
# configuration if a user runs tox with a "coverage" factor, for example "tox -e py36-coverage"
|
# configuration if a user runs tox with a "coverage" factor, for example "tox -e py36-coverage"
|
||||||
coverage: _PYTEST_TOX_COVERAGE_RUN=coverage run -m
|
coverage: _PYTEST_TOX_COVERAGE_RUN=coverage run -m
|
||||||
|
|
Loading…
Reference in New Issue