Hello community, here is the log from the commit of package python-pem for openSUSE:Leap:15.2 checked in at 2020-03-26 05:41:20 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Leap:15.2/python-pem (Old) and /work/SRC/openSUSE:Leap:15.2/.python-pem.new.3160 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pem" Thu Mar 26 05:41:20 2020 rev:2 rq:788018 version:20.1.0 Changes: -------- --- /work/SRC/openSUSE:Leap:15.2/python-pem/python-pem.changes 2020-02-11 23:24:59.361256675 +0100 +++ /work/SRC/openSUSE:Leap:15.2/.python-pem.new.3160/python-pem.changes 2020-03-26 05:41:28.927281994 +0100 @@ -1,0 +2,12 @@ +Tue Mar 24 13:24:05 UTC 2020 - pgaj...@suse.com + +- version update to 20.1.0 + - Carriage returns (``\r``) are now stripped before hashing ``pem`` objects to provide consistent hashes across platforms. + `#40 <https://github.com/hynek/pem/issues/40>`_ + - Python 3.4 is not supported anymore. + It has been unsupported by the Python core team for a while now and its PyPI downloads are negligible. + - Added support for ``pem.OpenSSHPrivateKey`` (``OPENSSH PRIVATE KEY``). + OpenSSH added a new ``BEGIN`` label when it switched to a proprietary key encoding. + `#39 <https://github.com/hynek/pem/pull/39>`_ + +------------------------------------------------------------------- Old: ---- python-pem-19.2.0.tar.gz New: ---- python-pem-20.1.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-pem.spec ++++++ --- /var/tmp/diff_new_pack.82wjMv/_old 2020-03-26 05:41:29.595282341 +0100 +++ /var/tmp/diff_new_pack.82wjMv/_new 2020-03-26 05:41:29.595282341 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-pem # -# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2020 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-pem -Version: 19.2.0 +Version: 20.1.0 Release: 0 Summary: PEM file parsing in Python License: MIT ++++++ python-pem-19.2.0.tar.gz -> python-pem-20.1.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pem-19.2.0/.coveragerc new/pem-20.1.0/.coveragerc --- old/pem-19.2.0/.coveragerc 2019-08-06 15:31:36.000000000 +0200 +++ new/pem-20.1.0/.coveragerc 1970-01-01 01:00:00.000000000 +0100 @@ -1,12 +0,0 @@ -[run] -branch = True -source = pem - -[paths] -source = - src/pem - .tox/*/lib/python*/site-packages/pem - .tox/pypy*/site-packages/pem - -[report] -show_missing = True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pem-19.2.0/.pre-commit-config.yaml new/pem-20.1.0/.pre-commit-config.yaml --- old/pem-19.2.0/.pre-commit-config.yaml 2019-08-06 15:31:36.000000000 +0200 +++ new/pem-20.1.0/.pre-commit-config.yaml 2020-01-06 15:18:14.000000000 +0100 @@ -1,6 +1,7 @@ +--- repos: - repo: https://github.com/psf/black - rev: 19.3b0 + rev: 19.10b0 hooks: - id: black language_version: python3.7 @@ -9,7 +10,7 @@ types: [] - repo: https://github.com/asottile/seed-isort-config - rev: v1.9.2 + rev: v1.9.4 hooks: - id: seed-isort-config @@ -17,17 +18,18 @@ rev: v4.3.21 hooks: - id: isort + additional_dependencies: [toml] language_version: python3.7 - repo: https://gitlab.com/pycqa/flake8 - rev: 3.7.8 + rev: 3.7.9 hooks: - id: flake8 language_version: python3.7 - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v2.3.0 + rev: v2.4.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pem-19.2.0/CHANGELOG.rst new/pem-20.1.0/CHANGELOG.rst --- old/pem-19.2.0/CHANGELOG.rst 2019-08-06 15:31:36.000000000 +0200 +++ new/pem-20.1.0/CHANGELOG.rst 2020-01-06 15:18:14.000000000 +0100 @@ -7,6 +7,62 @@ The third digit is only for regressions. +20.1.0 (2020-01-06) +------------------- + + +Backward-incompatible changes: +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*none* + + +Deprecations: +^^^^^^^^^^^^^ + +*none* + + +Changes: +^^^^^^^^ + +- Carriage returns (``\r``) are now stripped before hashing ``pem`` objects to provide consistent hashes across platforms. + `#40 <https://github.com/hynek/pem/issues/40>`_ + + +---- + + +19.3.0 (2019-10-16) +------------------- + + +Backward-incompatible changes: +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Python 3.4 is not supported anymore. + It has been unsupported by the Python core team for a while now and its PyPI downloads are negligible. + + It's very unlikely that ``pem`` will break under 3.4 anytime soon, but we don't test it anymore. + + +Deprecations: +^^^^^^^^^^^^^ + +*none* + + +Changes: +^^^^^^^^ + +- Added support for ``pem.OpenSSHPrivateKey`` (``OPENSSH PRIVATE KEY``). + OpenSSH added a new ``BEGIN`` label when it switched to a proprietary key encoding. + `#39 <https://github.com/hynek/pem/pull/39>`_ + + +---- + + 19.2.0 (2019-08-06) ------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pem-19.2.0/MANIFEST.in new/pem-20.1.0/MANIFEST.in --- old/pem-19.2.0/MANIFEST.in 2019-08-06 15:31:36.000000000 +0200 +++ new/pem-20.1.0/MANIFEST.in 2020-01-06 15:18:14.000000000 +0100 @@ -1,4 +1,4 @@ -include *.rst LICENSE tox.ini dev-requirements.txt docs-requirements.txt .coveragerc pyproject.toml conftest.py *.yml *.yaml mypy.ini +include *.rst *.yml *.yaml *.ini LICENSE pyproject.toml conftest.py recursive-include src *.typed recursive-include docs *.bat recursive-include docs *.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pem-19.2.0/README.rst new/pem-20.1.0/README.rst --- old/pem-19.2.0/README.rst 2019-08-06 15:31:36.000000000 +0200 +++ new/pem-20.1.0/README.rst 2020-01-06 15:18:14.000000000 +0100 @@ -32,7 +32,7 @@ ``pem`` is an MIT_-licensed Python module for parsing and splitting of `PEM files`_, i.e. Base64 encoded DER keys and certificates. -It runs on Python 2.7, 3.4+, and PyPy, has no dependencies, and does not attempt to interpret the certificate data in any way. +It runs on Python 2.7, 3.5+, and PyPy, has no dependencies, and does not attempt to interpret the certificate data in any way. It’s born from the need to load keys, certificates, trust chains, and DH parameters from various certificate deployments: some servers (like Apache_) expect them to be a separate file, others (like nginx_) expect them concatenated to the server certificate and finally some (like HAProxy_) expect key, certificate, and chain to be in one file. With ``pem``, your Python application can cope with all of those scenarios: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pem-19.2.0/azure-pipelines.yml new/pem-20.1.0/azure-pipelines.yml --- old/pem-19.2.0/azure-pipelines.yml 2019-08-06 15:31:36.000000000 +0200 +++ new/pem-20.1.0/azure-pipelines.yml 2020-01-06 15:18:14.000000000 +0100 @@ -30,9 +30,6 @@ py27: python.version: '2.7' tox.env: py27 - py34: - python.version: '3.4' - tox.env: py34 py35-twisted: python.version: '3.5' tox.env: py35-twisted @@ -51,6 +48,12 @@ py37-twisted: python.version: '3.7' tox.env: py37-twisted + py38: + python.version: '3.8' + tox.env: py38 + py38-twisted: + python.version: '3.8' + tox.env: py38-twisted pypy-twisted: python.version: pypy2 @@ -80,15 +83,15 @@ inputs: versionSpec: '$(python.version)' architecture: 'x64' - condition: not(in(variables['python.version'], '3.8')) + # condition: not(in(variables['python.version'], '3.8')) displayName: Use cached Python $(python.version) for tests. - - script: | - sudo add-apt-repository ppa:deadsnakes - sudo apt-get update - sudo apt-get install -y --no-install-recommends python$(python.version)-dev python$(python.version)-distutils - condition: in(variables['python.version'], '3.8') - displayName: Install Python $(python.version) from the deadsnakes PPA for tests. + # - script: | + # sudo add-apt-repository ppa:deadsnakes + # sudo apt-get update + # sudo apt-get install -y --no-install-recommends python$(python.version)-dev python$(python.version)-distutils + # condition: in(variables['python.version'], '3.8') + # displayName: Install Python $(python.version) from the deadsnakes PPA for tests. - script: $(pyTools.pythonLocation)/bin/tox -e $(tox.env) env: @@ -117,7 +120,7 @@ $PY get-pip.py --user fi - $PY -m pip install --user coverage codecov + $PY -m pip install --user 'coverage[toml]' codecov coverage combine codecov diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pem-19.2.0/docs/api.rst new/pem-20.1.0/docs/api.rst --- old/pem-19.2.0/docs/api.rst 2019-08-06 15:31:36.000000000 +0200 +++ new/pem-20.1.0/docs/api.rst 2020-01-06 15:18:14.000000000 +0100 @@ -33,6 +33,7 @@ .. autoclass:: RSAPrivateKey(PrivateKey) .. autoclass:: RSAPublicKey(PublicKey) .. autoclass:: ECPrivateKey(PrivateKey) +.. autoclass:: OpenSSHPrivateKey(PrivateKey) .. autoclass:: DHParameters(AbstractPEMObject) .. autoclass:: CertificateRequest(AbstractPEMObject) .. autoclass:: CertificateRevocationList(AbstractPEMObject) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pem-19.2.0/pyproject.toml new/pem-20.1.0/pyproject.toml --- old/pem-19.2.0/pyproject.toml 2019-08-06 15:31:36.000000000 +0200 +++ new/pem-20.1.0/pyproject.toml 2020-01-06 15:18:14.000000000 +0100 @@ -3,5 +3,29 @@ build-backend = "setuptools.build_meta" +[tool.coverage.run] +parallel = true +branch = true +source = ["pem"] + +[tool.coverage.paths] +source = ["src", ".tox/*/site-packages"] + +[tool.coverage.report] +show_missing = true + + [tool.black] line-length = 79 + + +[tool.isort] +atomic=true +include_trailing_comma=true +lines_after_imports=2 +lines_between_types=1 +multi_line_output=3 +not_skip="__init__.py" + +known_first_party="pem" +known_third_party=["OpenSSL", "certifi", "cryptography", "pem", "pretend", "pytest", "setuptools", "twisted"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pem-19.2.0/setup.cfg new/pem-20.1.0/setup.cfg --- old/pem-19.2.0/setup.cfg 2019-08-06 15:31:36.000000000 +0200 +++ new/pem-20.1.0/setup.cfg 1970-01-01 01:00:00.000000000 +0100 @@ -1,27 +0,0 @@ -[tool:pytest] -minversion = 3.0 -strict = true -addopts = -ra -testpaths = tests - - -[bdist_wheel] -# Since we're a pure Python package, we can mark our wheels as universal. -universal = 1 - - -[metadata] -# ensure LICENSE is included in wheels -license_file = LICENSE - - -[isort] -atomic=true -include_trailing_comma=true -lines_after_imports=2 -lines_between_types=1 -multi_line_output=3 -not_skip=__init__.py - -known_first_party=pem -known_third_party=OpenSSL,certifi,cryptography,pretend,pytest,setuptools,twisted diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pem-19.2.0/setup.py new/pem-20.1.0/setup.py --- old/pem-19.2.0/setup.py 2019-08-06 15:31:36.000000000 +0200 +++ new/pem-20.1.0/setup.py 2020-01-06 15:18:14.000000000 +0100 @@ -26,16 +26,16 @@ "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", "Topic :: Software Development :: Libraries :: Python Modules", ] INSTALL_REQUIRES = [] EXTRAS_REQUIRE = { "docs": ["sphinx"], - "tests": ["coverage", "pytest", "certifi", "pretend", "pyopenssl"], + "tests": ["coverage[toml]", "pytest", "certifi", "pretend", "pyopenssl"], } EXTRAS_REQUIRE["dev"] = ( EXTRAS_REQUIRE["tests"] @@ -94,7 +94,7 @@ + "Release Information\n" + "===================\n\n" + re.search( - r"(\d+.\d.\d \(.*?\)\n.*?)\n\n\n----\n\n\n", + r"(\d+.\d.\d \(.*?\)\r?\n.*?)\r?\n\r?\n\r?\n----\r?\n\r?\n\r?\n", read("CHANGELOG.rst"), re.S, ).group(1) @@ -126,4 +126,5 @@ classifiers=CLASSIFIERS, install_requires=INSTALL_REQUIRES, extras_require=EXTRAS_REQUIRE, + options={"bdist_wheel": {"universal": "1"}}, ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pem-19.2.0/src/pem/__init__.py new/pem-20.1.0/src/pem/__init__.py --- old/pem-19.2.0/src/pem/__init__.py 2019-08-06 15:31:36.000000000 +0200 +++ new/pem-20.1.0/src/pem/__init__.py 2020-01-06 15:18:14.000000000 +0100 @@ -8,6 +8,7 @@ DHParameters, ECPrivateKey, Key, + OpenSSHPrivateKey, PrivateKey, PublicKey, RSAPrivateKey, @@ -23,7 +24,7 @@ twisted = None # type: ignore -__version__ = "19.2.0" +__version__ = "20.1.0" __author__ = "Hynek Schlawack" __license__ = "MIT" __description__ = "Easy PEM file parsing in Python." @@ -40,6 +41,7 @@ "DHParameters", "ECPrivateKey", "Key", + "OpenSSHPrivateKey", "PrivateKey", "PublicKey", "RSAPrivateKey", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pem-19.2.0/src/pem/_core.py new/pem-20.1.0/src/pem/_core.py --- old/pem-19.2.0/src/pem/_core.py 2019-08-06 15:31:36.000000000 +0200 +++ new/pem-20.1.0/src/pem/_core.py 2020-01-06 15:18:14.000000000 +0100 @@ -53,9 +53,15 @@ A SHA-1 digest of the whole object for easy differentiation. .. versionadded:: 18.1.0 - """ + .. versionchanged:: 20.1.0 + + Carriage returns are removed before hashing to give the same hashes + on Windows and UNIX-like operating systems. + """ if self._sha1_hexdigest is None: - self._sha1_hexdigest = hashlib.sha1(self._pem_bytes).hexdigest() + self._sha1_hexdigest = hashlib.sha1( + self._pem_bytes.replace(b"\r", b"") + ).hexdigest() return self._sha1_hexdigest @@ -170,11 +176,20 @@ """ +class OpenSSHPrivateKey(PrivateKey): + """ + OpenSSH private key format + + .. versionadded:: 19.3.0 + """ + + _PEM_TO_CLASS = { b"CERTIFICATE": Certificate, b"PRIVATE KEY": PrivateKey, b"PUBLIC KEY": PublicKey, b"ENCRYPTED PRIVATE KEY": PrivateKey, + b"OPENSSH PRIVATE KEY": OpenSSHPrivateKey, b"RSA PRIVATE KEY": RSAPrivateKey, b"RSA PUBLIC KEY": RSAPublicKey, b"EC PRIVATE KEY": ECPrivateKey, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pem-19.2.0/tests/data.py new/pem-20.1.0/tests/data.py --- old/pem-19.2.0/tests/data.py 2019-08-06 15:31:36.000000000 +0200 +++ new/pem-20.1.0/tests/data.py 2020-01-06 15:18:14.000000000 +0100 @@ -232,3 +232,16 @@ oUQDQgAEyEVc22cgFbf0Ey4W7tNawHEW4o+4xNVznhP4et9g53Puw1KSVD/GOfl1 95dwvaIyx2XZG8tn9DRsVyjy8fjgFA== -----END EC PRIVATE KEY-----""" + +# generated with: +# ssh-keygen -t ecdsa +KEY_PEM_OPENSSH = b"""\ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS +1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQTw5dr6HzmoqoF1tJkUiCrFvbPbe18u +iJ2gmS+0mmdwledpUh8g9VWeCGUpa50MYWH83Y+cT0TY9jjRUhkNCchzAAAAuB5SwggeUs +IIAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPDl2vofOaiqgXW0 +mRSIKsW9s9t7Xy6InaCZL7SaZ3CV52lSHyD1VZ4IZSlrnQxhYfzdj5xPRNj2ONFSGQ0JyH +MAAAAhAMP/HkDnx5kbDXrh2EMYhj5FFAB2jbwXRVvJqeM6jD09AAAAHmJ1ZGR5QEJ1ZGR5 +cy1NYWNCb29rLVByby5sb2NhbAE= +-----END OPENSSH PRIVATE KEY-----""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pem-19.2.0/tests/test_core.py new/pem-20.1.0/tests/test_core.py --- old/pem-19.2.0/tests/test_core.py 2019-08-06 15:31:36.000000000 +0200 +++ new/pem-20.1.0/tests/test_core.py 2020-01-06 15:18:14.000000000 +0100 @@ -5,6 +5,7 @@ from itertools import combinations import certifi +import pytest from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization @@ -21,6 +22,7 @@ CRL_PEMS, DH_PEM, KEY_PEM_EC_PRIVATE, + KEY_PEM_OPENSSH, KEY_PEM_PKCS5_ENCRYPTED, KEY_PEM_PKCS5_UNENCRYPTED, KEY_PEM_PKCS8_ENCRYPTED, @@ -65,11 +67,14 @@ cert_req ) - def test_sha1_hexdigest(self): + @pytest.mark.parametrize("pem_bytes", (b"test", b"test\r")) + def test_sha1_hexdigest(self, pem_bytes): """ obj.sha1_digest contains the correct digest and caches it properly. + + CRs are ignored. """ - cert = pem.Certificate(b"test") + cert = pem.Certificate(pem_bytes) assert ( "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3" @@ -373,7 +378,7 @@ as an RSAPrivateKey. """ rv = pem.parse(KEY_PEM_PKCS5_UNENCRYPTED) - key, = rv + (key,) = rv assert isinstance(key, pem.RSAPrivateKey) assert KEY_PEM_PKCS5_UNENCRYPTED == key.as_bytes() @@ -390,7 +395,7 @@ """ rv = pem.parse(KEY_PEM_PKCS5_ENCRYPTED) - key, = rv + (key,) = rv assert isinstance(key, pem.RSAPrivateKey) assert KEY_PEM_PKCS5_ENCRYPTED == key.as_bytes() @@ -406,7 +411,7 @@ as an Key. """ rv = pem.parse(KEY_PEM_PKCS8_UNENCRYPTED) - key, = rv + (key,) = rv assert isinstance(key, pem.Key) assert KEY_PEM_PKCS8_UNENCRYPTED == key.as_bytes() @@ -422,7 +427,7 @@ as an Key. """ rv = pem.parse(KEY_PEM_PKCS8_ENCRYPTED) - key, = rv + (key,) = rv assert isinstance(key, pem.Key) assert KEY_PEM_PKCS8_ENCRYPTED == key.as_bytes() @@ -446,7 +451,7 @@ """ Parses a PEM string without a new line at the end """ - cert, = pem.parse(CERT_NO_NEW_LINE) + (cert,) = pem.parse(CERT_NO_NEW_LINE) assert isinstance(cert, pem.Certificate) assert CERT_NO_NEW_LINE == cert.as_bytes() @@ -466,7 +471,7 @@ Parses a PEM string with with DH parameters into a DHParameters. """ rv = pem.parse(DH_PEM) - dh, = rv + (dh,) = rv assert isinstance(dh, pem.DHParameters) assert DH_PEM == dh.as_bytes() @@ -507,7 +512,7 @@ \n and \r\n are treated equal. """ lf_pem = KEY_PEM_PKCS5_UNENCRYPTED.replace(b"\n", b"\r\n") - rv, = pem.parse(lf_pem) + (rv,) = pem.parse(lf_pem) assert rv.as_bytes() == lf_pem @@ -535,3 +540,11 @@ key = pem.parse(KEY_PEM_EC_PRIVATE)[0] assert isinstance(key, pem.ECPrivateKey) + + def test_openshh_private_key(self): + """ + Detects and loads private keys in the new OpenSSH private key format. + """ + (key,) = pem.parse(KEY_PEM_OPENSSH) + + assert isinstance(key, pem.OpenSSHPrivateKey) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pem-19.2.0/tox.ini new/pem-20.1.0/tox.ini --- old/pem-19.2.0/tox.ini 2019-08-06 15:31:36.000000000 +0200 +++ new/pem-20.1.0/tox.ini 2020-01-06 15:18:14.000000000 +0100 @@ -1,5 +1,13 @@ +[pytest] +strict = true +addopts = -ra +testpaths = tests +filterwarnings = + once::Warning + + [tox] -envlist = lint,mypy,py34,{py27,py35,py36,py37,pypy,pypy3}{-twisted,},manifest,docs,pypi-description,coverage-report +envlist = lint,mypy,{py27,py35,py36,py37,py38,pypy,pypy3}{-twisted,},manifest,docs,pypi-description,coverage-report isolated_build = true @@ -18,7 +26,7 @@ deps = twisted: twisted[tls] commands = {py27,py37}{-twisted,}: coverage run --parallel -m pytest {posargs} - {py34,py35,py36,pypy,pypy3}{-twisted,}: python -m pytest {posargs} + {py35,py36,pypy,pypy3}{-twisted,}: python -m pytest {posargs} [testenv:mypy] @@ -61,7 +69,7 @@ [testenv:coverage-report] description = Report coverage over all test runs. basepython = python3.7 -deps = coverage +deps = coverage[toml] skip_install = true commands = coverage combine