Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-service_identity for openSUSE:Factory checked in at 2024-01-21 23:07:21 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-service_identity (Old) and /work/SRC/openSUSE:Factory/.python-service_identity.new.16006 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-service_identity" Sun Jan 21 23:07:21 2024 rev:15 rq:1140210 version:24.1.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-service_identity/python-service_identity.changes 2023-09-22 21:47:20.496702425 +0200 +++ /work/SRC/openSUSE:Factory/.python-service_identity.new.16006/python-service_identity.changes 2024-01-21 23:07:26.671511362 +0100 @@ -1,0 +2,9 @@ +Sat Jan 20 20:31:18 UTC 2024 - Dirk Müller <dmuel...@suse.com> + +- update to 24.1.0: + * If a certificate doesn't contain any `subjectAltName`s, we + now raise `service_identity.CertificateError` instead of + `service_identity.VerificationError` to make the problem + easier to debug. + +------------------------------------------------------------------- Old: ---- 23.1.0.tar.gz New: ---- 24.1.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-service_identity.spec ++++++ --- /var/tmp/diff_new_pack.l7lQlL/_old 2024-01-21 23:07:27.443539504 +0100 +++ /var/tmp/diff_new_pack.l7lQlL/_new 2024-01-21 23:07:27.443539504 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-service_identity # -# Copyright (c) 2023 SUSE LLC +# Copyright (c) 2024 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,7 +19,7 @@ %define oname service_identity %{?sle15_python_module_pythons} Name: python-service_identity -Version: 23.1.0 +Version: 24.1.0 Release: 0 Summary: Service identity verification for pyOpenSSL License: MIT ++++++ 23.1.0.tar.gz -> 24.1.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/.git_archival.txt new/service-identity-24.1.0/.git_archival.txt --- old/service-identity-23.1.0/.git_archival.txt 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/.git_archival.txt 2024-01-14 08:05:19.000000000 +0100 @@ -1,4 +1,4 @@ -node: be2f98443fe0ce1d8dcc7f373ea53561bd929837 -node-date: 2023-06-14T09:54:35+02:00 -describe-name: 23.1.0 -ref-names: tag: 23.1.0 +node: e5ba15ec13b1750cae35004dede2e6e4af74308f +node-date: 2024-01-14T08:05:19+01:00 +describe-name: 24.1.0 +ref-names: tag: 24.1.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/.github/CONTRIBUTING.md new/service-identity-24.1.0/.github/CONTRIBUTING.md --- old/service-identity-23.1.0/.github/CONTRIBUTING.md 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/.github/CONTRIBUTING.md 2024-01-14 08:05:19.000000000 +0100 @@ -65,7 +65,7 @@ > Yes, you can work on `main` in your fork and submit pull requests. > But this will *inevitably* lead to you not being able to synchronize your > fork with upstream and having to start over. -Change into the newly created directory and after activating a virtual environment, install an editable version of *service-identity* along with its tests and docs requirements: +Change into the newly created directory and after activating a virtual environment, install an editable version of *service-identity* along with its tests requirements: ```console $ cd service-identity @@ -79,13 +79,21 @@ $ python -Im pytest ``` -should work and pass, as should: +When working on the documentation, use: ```console -$ cd docs -$ make html +$ tox run -e docs-watch ``` +... to watch your files and automatically rebuild when a file changes. +And use: + +```console +$ tox run -e docs +``` + +... to build it once and run our doctests. + The built documentation can then be found in `docs/_build/html/`. --- @@ -102,23 +110,31 @@ $ pre-commit run --all-files ``` -and our CI has integration with [pre-commit.ci](https://pre-commit.ci). But it's way more comfortable to run it locally and catch avoidable errors before pushing them to GitHub. ## Code - Obey [PEP 8](https://www.python.org/dev/peps/pep-0008/) and [PEP 257](https://www.python.org/dev/peps/pep-0257/). - We use the `"""`-on-separate-lines style for docstrings: + We use the `"""`-on-separate-lines style for docstrings with [Napoleon](https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html)-style API documentation: ```python - def func(x: str) -> str: + def func(x: str, y: int) -> str: """ Do something. - :param str x: A very important parameter. + Args: + x: A very important parameter. + + y: + Another important parameter but one that doesn't fit a line so + it already starts on the next one. - :rtype: str + Raises: + Exception: When Something goes wrong. + + Returns: + A very important return value. """ ``` - If you add or change public APIs, tag the docstring using `.. versionadded:: 16.0.0 WHAT` or `.. versionchanged:: 16.2.0 WHAT`. @@ -140,9 +156,6 @@ - To run the test suite, all you need is a recent [*tox*]. It will ensure the test suite runs with all dependencies against all Python versions just as it will in our [CI]. - If you lack some Python versions, you can can always limit the environments like `tox -e py38,py39`, or make it a non-failure using `tox --skip-missing-interpreters`. - - In that case you should look into [*asdf*](https://asdf-vm.com) or [*pyenv*](https://github.com/pyenv/pyenv), which make it very easy to install many different Python versions in parallel. - Write [good test docstrings](https://jml.io/pages/test-docstrings.html). - If you've changed or added public APIs, please update our type stubs (files ending in `.pyi`). @@ -166,7 +179,7 @@ ## Header of New Top Section - ### Header of New Section + ### Header of New Section First line of new section. ``` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/.github/workflows/ci.yml new/service-identity-24.1.0/.github/workflows/ci.yml --- old/service-identity-23.1.0/.github/workflows/ci.yml 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/.github/workflows/ci.yml 2024-01-14 08:05:19.000000000 +0100 @@ -3,28 +3,26 @@ on: push: - branches: ["main"] + branches: [main] pull_request: - branches: ["main"] - -permissions: - contents: read + workflow_dispatch: env: FORCE_COLOR: "1" # Make tools pretty. PIP_DISABLE_PIP_VERSION_CHECK: "1" PIP_NO_PYTHON_VERSION_WARNING: "1" +permissions: {} jobs: lint: name: Run linters - runs-on: "ubuntu-latest" + runs-on: ubuntu-latest steps: - - uses: "actions/checkout@v3" - - uses: "actions/setup-python@v4" + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: - python-version-file: .python-version-default + python-version: "3.11" # XXX: change once interrogate works on 3.12 cache: pip - name: Install & run tox @@ -47,8 +45,8 @@ - "pypy-3.9" steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} allow-prereleases: true @@ -71,29 +69,30 @@ run: python -Im tox run -e mypy-api - name: Upload coverage data - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: coverage-data + name: coverage-data-${{ matrix.python-version }} path: .coverage.* if-no-files-found: ignore coverage: - name: Combine & check coverage. + name: Combine & check coverage needs: tests runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version-file: .python-version-default cache: pip - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: - name: coverage-data + pattern: coverage-data-* + merge-multiple: true - - name: Combine coverage & fail if it's <100%. + - name: Combine coverage & fail if it's <100% run: | python -Im pip install coverage[toml] @@ -101,13 +100,13 @@ python -Im coverage html --skip-covered --skip-empty # Report and write to summary. - python -Im coverage report | sed 's/^/ /' >> $GITHUB_STEP_SUMMARY + python -Im coverage report --format=markdown >> $GITHUB_STEP_SUMMARY # Report again and fail if under 100%. python -Im coverage report --fail-under=100 - name: Upload HTML report if check failed. - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: html-report path: htmlcov @@ -118,8 +117,8 @@ runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version-file: .python-version-default cache: pip @@ -138,8 +137,8 @@ runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version-file: .python-version-default cache: pip @@ -153,11 +152,11 @@ name: Build docs & run doctests runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: # Keep in sync with tox.ini/docs & .readthedocs.yaml - python-version: "3.11" + python-version: "3.12" cache: pip - name: Install & run tox diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/.github/workflows/codeql-analysis.yml new/service-identity-24.1.0/.github/workflows/codeql-analysis.yml --- old/service-identity-23.1.0/.github/workflows/codeql-analysis.yml 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/.github/workflows/codeql-analysis.yml 2024-01-14 08:05:19.000000000 +0100 @@ -28,15 +28,15 @@ steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/.github/workflows/pypi-package.yml new/service-identity-24.1.0/.github/workflows/pypi-package.yml --- old/service-identity-23.1.0/.github/workflows/pypi-package.yml 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/.github/workflows/pypi-package.yml 2024-01-14 08:05:19.000000000 +0100 @@ -6,7 +6,6 @@ branches: [main] tags: ["*"] pull_request: - branches: [main] release: types: - published @@ -23,11 +22,11 @@ runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: hynek/build-and-inspect-python-package@v1 + - uses: hynek/build-and-inspect-python-package@v2 # Upload to Test PyPI on every commit on main. release-test-pypi: @@ -39,7 +38,7 @@ steps: - name: Download packages built by build-and-inspect-python-package - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: Packages path: dist @@ -59,7 +58,7 @@ steps: - name: Download packages built by build-and-inspect-python-package - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: Packages path: dist diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/.pre-commit-config.yaml new/service-identity-24.1.0/.pre-commit-config.yaml --- old/service-identity-23.1.0/.pre-commit-config.yaml 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/.pre-commit-config.yaml 2024-01-14 08:05:19.000000000 +0100 @@ -1,28 +1,31 @@ --- -default_language_version: - # keep in-sync with .python-version-default - python: python3.11 - repos: - repo: https://github.com/psf/black - rev: 23.3.0 + rev: 23.12.1 hooks: - id: black - - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.272 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.1.13 hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix] - repo: https://github.com/codespell-project/codespell - rev: v2.2.4 + rev: v2.2.6 hooks: - id: codespell args: [-L, fo] + - repo: https://github.com/econchick/interrogate + rev: 1.5.0 + hooks: + - id: interrogate + language_version: python3.11 + args: [tests, -v] + - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.5.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/.python-version-default new/service-identity-24.1.0/.python-version-default --- old/service-identity-23.1.0/.python-version-default 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/.python-version-default 2024-01-14 08:05:19.000000000 +0100 @@ -1 +1 @@ -3.11 +3.12 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/.readthedocs.yaml new/service-identity-24.1.0/.readthedocs.yaml --- old/service-identity-23.1.0/.readthedocs.yaml 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/.readthedocs.yaml 2024-01-14 08:05:19.000000000 +0100 @@ -5,7 +5,7 @@ os: ubuntu-22.04 tools: # Keep in-sync with tox.ini/docs and ci.yml/docs - python: "3.11" + python: "3.12" python: install: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/CHANGELOG.md new/service-identity-24.1.0/CHANGELOG.md --- old/service-identity-23.1.0/CHANGELOG.md 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/CHANGELOG.md 2024-01-14 08:05:19.000000000 +0100 @@ -12,6 +12,15 @@ <!-- changelog follows --> + +## [24.1.0](https://github.com/pyca/service-identity/compare/23.1.0...24.1.0) - 2024-01-14 + +### Changed + +- If a certificate doesn't contain any `subjectAltName`s, we now raise `service_identity.CertificateError` instead of `service_identity.VerificationError` to make the problem easier to debug. + [#67](https://github.com/pyca/service-identity/pull/67) + + ## [23.1.0](https://github.com/pyca/service-identity/compare/21.1.0...23.1.0) - 2023-06-14 ### Removed @@ -21,7 +30,7 @@ It has been deprecated since 2017 and isn't supported by any major browser. - The oldest supported pyOpenSSL version (when using the `pyopenssl` backend) is now 17.0.0. When using such an old pyOpenSSL version, you have to pin *cryptography* yourself to ensure compatibility between them. - Please check out [`contraints/oldest-pyopenssl.txt`](https://github.com/pyca/service-identity/blob/main/tests/constraints/oldest-pyopenssl.txt) to verify what we are testing against. + Please check out [`constraints/oldest-pyopenssl.txt`](https://github.com/pyca/service-identity/blob/main/tests/constraints/oldest-pyopenssl.txt) to verify what we are testing against. ### Deprecated diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/LICENSE new/service-identity-24.1.0/LICENSE --- old/service-identity-23.1.0/LICENSE 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/LICENSE 2024-01-14 08:05:19.000000000 +0100 @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014 Hynek Schlawack and the service-identity contibutors +Copyright (c) 2014 Hynek Schlawack and the service-identity contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/README.md new/service-identity-24.1.0/README.md --- old/service-identity-23.1.0/README.md 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/README.md 2024-01-14 08:05:19.000000000 +0100 @@ -1,23 +1,11 @@ # Service Identity Verification -<a href="https://service-identity.readthedocs.io/"> - <img src="https://img.shields.io/badge/Docs-Read%20The%20Docs-black" alt="Documentation" /> -</a> -<a href="https://github.com/pyca/service-identity/blob/main/LICENSE"> - <img src="https://img.shields.io/badge/license-MIT-C06524" alt="License: MIT" /> -</a> -<a href="https://pypi.org/project/service-identity/"> - <img src="https://img.shields.io/pypi/v/service-identity" alt="PyPI release" /> -</a> -<a href="https://pepy.tech/project/service-identity"> - <img src="https://static.pepy.tech/badge/service-identity/month" alt="Downloads per month" /> -</a> -<a href="https://bestpractices.coreinfrastructure.org/projects/7462"> - <img src="https://bestpractices.coreinfrastructure.org/projects/7462/badge" /> -</a> -<a href="https://www.irccloud.com/invite?channel=%23pyca&hostname=irc.libera.chat&port=6697&ssl=1"> - <img src="https://www.irccloud.com/invite-svg?channel=%23pyca&hostname=irc.libera.chat&port=6697&ssl=1" alt="PyCA on IRC" /> -</a> +<a href="https://service-identity.readthedocs.io/"><img src="https://img.shields.io/badge/Docs-Read%20The%20Docs-black" alt="Documentation" /></a> +<a href="https://github.com/pyca/service-identity/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-C06524" alt="License: MIT" /></a> +<a href="https://pypi.org/project/service-identity/"><img src="https://img.shields.io/pypi/v/service-identity" alt="PyPI release" /></a> +<a href="https://pepy.tech/project/service-identity"><img src="https://static.pepy.tech/badge/service-identity/month" alt="Downloads per month" /></a> +<a href="https://bestpractices.coreinfrastructure.org/projects/7462"><img src="https://bestpractices.coreinfrastructure.org/projects/7462/badge" /></a> +<a href="https://www.irccloud.com/invite?channel=%23pyca&hostname=irc.libera.chat&port=6697&ssl=1"><img src="https://www.irccloud.com/invite-svg?channel=%23pyca&hostname=irc.libera.chat&port=6697&ssl=1" alt="PyCA on IRC" /></a> <!-- spiel-begin --> @@ -31,6 +19,8 @@ In the simplest case, this means *host name verification*. However, *service-identity* implements [RFC 6125](https://datatracker.ietf.org/doc/html/rfc6125.html) fully. +Also check out [*pem*](https://github.com/hynek/pem) that makes loading certificates from all kinds of PEM-encoded files a breeze! + ## Project Information @@ -41,7 +31,7 @@ *service-identity* is written and maintained by [Hynek Schlawack](https://hynek.me/). -The development is kindly supported by my employer [Variomedia AG](https://www.variomedia.de/), *service-identity*'s [Tidelift subscribers][Tidelift], and all my amazing [GitHub Sponsors](https://github.com/sponsors/hynek). +The development is kindly supported by my employer [Variomedia AG](https://www.variomedia.de/), *service-identity*'s [Tidelift subscribers](https://tidelift.com/lifter/search/pypi/service-identity), and all my amazing [GitHub Sponsors](https://github.com/sponsors/hynek). ### *service-identity* for Enterprise @@ -50,6 +40,4 @@ The maintainers of *service-identity* and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open-source packages you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use. -[Learn more.][Tidelift] - -[Tidelift]: https://tidelift.com/subscription/pkg/pypi-service-identity?utm_source=pypi-service-identity&utm_medium=readme +[Learn more.](https://tidelift.com/lifter/search/pypi/service-identity) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/docs/_static/custom.css new/service-identity-24.1.0/docs/_static/custom.css --- old/service-identity-23.1.0/docs/_static/custom.css 1970-01-01 01:00:00.000000000 +0100 +++ new/service-identity-24.1.0/docs/_static/custom.css 2024-01-14 08:05:19.000000000 +0100 @@ -0,0 +1,10 @@ +@import url('https://rsms.me/inter/inter.css'); +@import url('https://assets.hynek.me/css/bm.css'); + + +:root { + font-feature-settings: 'liga' 1, 'calt' 1; /* fix for Chrome */ +} +@supports (font-variation-settings: normal) { + :root { font-family: InterVariable, sans-serif; } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/docs/conf.py new/service-identity-24.1.0/docs/conf.py --- old/service-identity-23.1.0/docs/conf.py 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/docs/conf.py 2024-01-14 08:05:19.000000000 +0100 @@ -18,6 +18,7 @@ "sphinx.ext.doctest", "sphinx.ext.autodoc", "sphinx.ext.intersphinx", + "sphinx.ext.napoleon", "myst_parser", "notfound.extension", ] @@ -63,6 +64,10 @@ # The short X.Y version. version = release.rsplit(".", 1)[0] +# Avoid confusing in-dev versions. +if "dev" in release: + release = version = "UNRELEASED" + # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # language = None @@ -104,85 +109,17 @@ # -- Options for HTML output ---------------------------------------------- -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. - html_theme = "furo" - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -# html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# "<project> v<release> documentation". -# html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -# html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -# html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -# html_static_path = ['_static'] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -# html_extra_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -# html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -# html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# html_additional_pages = {} - -# If false, no module index is generated. -# html_domain_indices = True - -# If false, no index is generated. -# html_use_index = True - -# If true, the index is split into individual pages for each letter. -# html_split_index = False - -# If true, links to the reST sources are added to the pages. -# html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a <link> tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None +html_theme_options = { + "top_of_page_button": None, + "light_css_variables": { + "font-stack": "Inter, sans-serif", + "font-stack--monospace": "BerkeleyMono, MonoLisa, ui-monospace, " + "SFMono-Regular, Menlo, Consolas, Liberation Mono, monospace", + }, +} +html_static_path = ["_static"] +html_css_files = ["custom.css"] # Output file base name for HTML help builder. htmlhelp_basename = "service-identitydoc" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/docs/index.md new/service-identity-24.1.0/docs/index.md --- old/service-identity-23.1.0/docs/index.md 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/docs/index.md 2024-01-14 08:05:19.000000000 +0100 @@ -17,22 +17,28 @@ api ``` -## Project Information - -```{include} ../README.md -:start-after: "## Project Information" -``` - - ## Indices and tables - {ref}`genindex` - {ref}`search` -% Prevent warning; the changelog is linked in the header. + +## *service-identity* for Enterprise + +```{include} ../README.md +:start-after: "*service-identity* for Enterprise" +``` + ```{toctree} :hidden: +:caption: Meta +license changelog +PyPI <https://pypi.org/project/service-identity/> +GitHub <https://github.com/pyca/service-identity/> +Contributing <https://github.com/pyca/service-identity/blob/main/.github/CONTRIBUTING.md> +Security Policy <https://github.com/pyca/service-identity/blob/main/.github/SECURITY.md> +Funding <https://hynek.me/say-thanks/> ``` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/docs/license.md new/service-identity-24.1.0/docs/license.md --- old/service-identity-23.1.0/docs/license.md 1970-01-01 01:00:00.000000000 +0100 +++ new/service-identity-24.1.0/docs/license.md 2024-01-14 08:05:19.000000000 +0100 @@ -0,0 +1,9 @@ +# License and Credits + +*service-identity* is released under the [MIT](https://github.com/pyca/service-identity/blob/main/LICENSE) license. + +```{include} ../README.md +:parser: myst_parser.sphinx_ +:start-after: "## Credits" +:end-before: "### *service-identity* for Enterprise" +``` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/pyproject.toml new/service-identity-24.1.0/pyproject.toml --- old/service-identity-23.1.0/pyproject.toml 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/pyproject.toml 2024-01-14 08:05:19.000000000 +0100 @@ -38,14 +38,16 @@ tests = ["coverage[toml]>=5.0.2", "pytest"] docs = ["sphinx", "furo", "myst-parser", "sphinx-notfound-page", "pyOpenSSL"] mypy = ["mypy", "types-pyOpenSSL", "idna"] -dev = ["service-identity[tests,mypy,docs,idna]", "pyOpenSSL"] +dev = ["service-identity[tests,mypy,idna]", "pyOpenSSL"] [project.urls] Documentation = "https://service-identity.readthedocs.io/" -"Bug Tracker" = "https://github.com/pyca/service-identity/issues" -"Source Code" = "https://github.com/pyca/service-identity" +Changelog = "https://service-identity.readthedocs.io/en/stable/changelog.html" +GitHub = "https://github.com/pyca/service-identity" Funding = "https://github.com/sponsors/hynek" Tidelift = "https://tidelift.com/subscription/pkg/pypi-service-identity?utm_source=pypi-service-identity&utm_medium=pypi" +Mastodon = "https://mastodon.social/@hynek" +Twitter = "https://twitter.com/hynek" [tool.hatch.version] @@ -78,7 +80,7 @@ text = """ ---- -[â Complete Changelog](https://service-identity.readthedocs.io/en/stable/changelog.html) +[Complete Changelog â](https://service-identity.readthedocs.io/en/stable/changelog.html) """ @@ -123,6 +125,13 @@ ] +[tool.interrogate] +omit-covered-files = true +verbose = 2 +fail-under = 100 +whitelist-regex = ["test_.*"] + + [tool.black] line-length = 79 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/src/service_identity/__init__.py new/service-identity-24.1.0/src/service_identity/__init__.py --- old/service-identity-23.1.0/src/service_identity/__init__.py 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/src/service_identity/__init__.py 2024-01-14 08:05:19.000000000 +0100 @@ -37,7 +37,7 @@ "__url__": "", "__email__": "", } - if name not in dunder_to_metadata.keys(): + if name not in dunder_to_metadata: raise AttributeError(f"module {__name__} has no attribute {name}") import warnings @@ -55,7 +55,7 @@ meta = metadata("service-identity") if name in ("__uri__", "__url__"): - return meta["Project-URL"].split(" ", 1)[-1] + return meta["Project-URL"].split(" ", 1)[1] if name == "__email__": return meta["Author-email"].split("<", 1)[1].rstrip(">") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/src/service_identity/cryptography.py new/service-identity-24.1.0/src/service_identity/cryptography.py --- old/service-identity-23.1.0/src/service_identity/cryptography.py 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/src/service_identity/cryptography.py 2024-01-14 08:05:19.000000000 +0100 @@ -40,22 +40,31 @@ def verify_certificate_hostname( certificate: Certificate, hostname: str ) -> None: - """ + r""" Verify whether *certificate* is valid for *hostname*. - .. note:: Nothing is verified about the *authority* of the certificate; - the caller must verify that the certificate chains to an appropriate - trust root themselves. - - :param certificate: A *cryptography* X509 certificate object. - :param hostname: The hostname that *certificate* should be valid for. - - :raises service_identity.VerificationError: If *certificate* is not valid - for *hostname*. - :raises service_identity.CertificateError: If *certificate* contains - invalid / unexpected data. - - :returns: ``None`` + .. note:: + Nothing is verified about the *authority* of the certificate; + the caller must verify that the certificate chains to an appropriate + trust root themselves. + + Args: + certificate: A *cryptography* X509 certificate object. + + hostname: The hostname that *certificate* should be valid for. + + Raises: + service_identity.VerificationError: + If *certificate* is not valid for *hostname*. + + service_identity.CertificateError: + If *certificate* contains invalid / unexpected data. This includes + the case where the certificate contains no `subjectAltName`\ s. + + .. versionchanged:: 24.1.0 + :exc:`~service_identity.CertificateError` is raised if the certificate + contains no ``subjectAltName``\ s instead of + :exc:`~service_identity.VerificationError`. """ verify_service_identity( cert_patterns=extract_patterns(certificate), @@ -67,25 +76,35 @@ def verify_certificate_ip_address( certificate: Certificate, ip_address: str ) -> None: - """ + r""" Verify whether *certificate* is valid for *ip_address*. - .. note:: Nothing is verified about the *authority* of the certificate; - the caller must verify that the certificate chains to an appropriate - trust root themselves. - - :param certificate: A *cryptography* X509 certificate object. - :param ip_address: The IP address that *connection* should be valid - for. Can be an IPv4 or IPv6 address. - - :raises service_identity.VerificationError: If *certificate* is not valid - for *ip_address*. - :raises service_identity.CertificateError: If *certificate* contains - invalid / unexpected data. - - :returns: ``None`` + .. note:: + Nothing is verified about the *authority* of the certificate; + the caller must verify that the certificate chains to an appropriate + trust root themselves. + + Args: + certificate: A *cryptography* X509 certificate object. + + ip_address: + The IP address that *connection* should be valid for. Can be an + IPv4 or IPv6 address. + + Raises: + service_identity.VerificationError: + If *certificate* is not valid for *ip_address*. + + service_identity.CertificateError: + If *certificate* contains invalid / unexpected data. This includes + the case where the certificate contains no ``subjectAltName``\ s. .. versionadded:: 18.1.0 + + .. versionchanged:: 24.1.0 + :exc:`~service_identity.CertificateError` is raised if the certificate + contains no ``subjectAltName``\ s instead of + :exc:`~service_identity.VerificationError`. """ verify_service_identity( cert_patterns=extract_patterns(certificate), @@ -101,9 +120,11 @@ """ Extract all valid ID patterns from a certificate for service verification. - :param cert: The certificate to be dissected. + Args: + cert: The certificate to be dissected. - :return: List of IDs. + Returns: + List of IDs. .. versionchanged:: 23.1.0 ``commonName`` is not used as a fallback anymore. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/src/service_identity/exceptions.py new/service-identity-24.1.0/src/service_identity/exceptions.py --- old/service-identity-23.1.0/src/service_identity/exceptions.py 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/src/service_identity/exceptions.py 2024-01-14 08:05:19.000000000 +0100 @@ -72,6 +72,9 @@ class CertificateError(Exception): - """ + r""" Certificate contains invalid or unexpected data. + + This includes the case where s certificate contains no + ``subjectAltName``\ s. """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/src/service_identity/hazmat.py new/service-identity-24.1.0/src/service_identity/hazmat.py --- old/service-identity-23.1.0/src/service_identity/hazmat.py 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/src/service_identity/hazmat.py 2024-01-14 08:05:19.000000000 +0100 @@ -50,6 +50,11 @@ *obligatory_ids* must be both present and match. *optional_ids* must match if a pattern of the respective type is present. """ + if not cert_patterns: + raise CertificateError( + "Certificate does not contain any `subjectAltName`s." + ) + errors = [] matches = _find_matches(cert_patterns, obligatory_ids) + _find_matches( cert_patterns, optional_ids @@ -83,8 +88,8 @@ """ Search for matching certificate patterns and service_ids. - :param service_ids: List of service IDs like DNS_ID. - :type service_ids: `list` + Args: + service_ids: List of service IDs like DNS_ID. """ matches = [] for sid in service_ids: @@ -102,9 +107,11 @@ """ Check whether *pattern* could be/match an IP address. - :param pattern: A pattern for a host name. + Args: + pattern: A pattern for a host name. - :return: `True` if *pattern* could be an IP address, else `False`. + Returns: + `True` if *pattern* could be an IP address, else `False`. """ if isinstance(pattern, bytes): try: @@ -426,15 +433,13 @@ cnt = cert_pattern.count(b"*") if cnt > 1: raise CertificateError( - "Certificate's DNS-ID {!r} contains too many wildcards.".format( - cert_pattern - ) + f"Certificate's DNS-ID {cert_pattern!r} contains too many wildcards." ) parts = cert_pattern.split(b".") if len(parts) < 3: raise CertificateError( - "Certificate's DNS-ID {!r} has too few host components for " - "wildcard usage.".format(cert_pattern) + f"Certificate's DNS-ID {cert_pattern!r} has too few host components for " + "wildcard usage." ) # We assume there will always be only one wildcard allowed. if b"*" not in parts[0]: @@ -444,9 +449,7 @@ ) if any(not len(p) for p in parts): raise CertificateError( - "Certificate's DNS-ID {!r} contains empty parts.".format( - cert_pattern - ) + f"Certificate's DNS-ID {cert_pattern!r} contains empty parts." ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/src/service_identity/pyopenssl.py new/service-identity-24.1.0/src/service_identity/pyopenssl.py --- old/service-identity-23.1.0/src/service_identity/pyopenssl.py 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/src/service_identity/pyopenssl.py 2024-01-14 08:05:19.000000000 +0100 @@ -37,19 +37,28 @@ def verify_hostname(connection: Connection, hostname: str) -> None: - """ + r""" Verify whether the certificate of *connection* is valid for *hostname*. - :param connection: A pyOpenSSL connection object. - :param hostname: The hostname that *connection* should be connected to. + Args: + connection: A pyOpenSSL connection object. - :raises service_identity.VerificationError: If *connection* does not - provide a certificate that is valid for *hostname*. - :raises service_identity.CertificateError: If the certificate chain of - *connection* contains a certificate that contains invalid/unexpected - data. + hostname: The hostname that *connection* should be connected to. - :returns: ``None`` + Raises: + service_identity.VerificationError: + If *connection* does not provide a certificate that is valid for + *hostname*. + + service_identity.CertificateError: + If certificate provided by *connection* contains invalid / + unexpected data. This includes the case where the certificate + contains no ``subjectAltName``\ s. + + .. versionchanged:: 24.1.0 + :exc:`~service_identity.CertificateError` is raised if the certificate + contains no ``subjectAltName``\ s instead of + :exc:`~service_identity.VerificationError`. """ verify_service_identity( cert_patterns=extract_patterns( @@ -61,22 +70,31 @@ def verify_ip_address(connection: Connection, ip_address: str) -> None: - """ + r""" Verify whether the certificate of *connection* is valid for *ip_address*. - :param connection: A pyOpenSSL connection object. - :param ip_address: The IP address that *connection* should be connected to. - Can be an IPv4 or IPv6 address. - - :raises service_identity.VerificationError: If *connection* does not - provide a certificate that is valid for *ip_address*. - :raises service_identity.CertificateError: If the certificate chain of - *connection* contains a certificate that contains invalid/unexpected - data. + Args: + connection: A pyOpenSSL connection object. - :returns: ``None`` + ip_address: + The IP address that *connection* should be connected to. Can be an + IPv4 or IPv6 address. + + Raises: + service_identity.VerificationError: + If *connection* does not provide a certificate that is valid for + *ip_address*. + + service_identity.CertificateError: + If the certificate chain of *connection* contains a certificate + that contains invalid/unexpected data. .. versionadded:: 18.1.0 + + .. versionchanged:: 24.1.0 + :exc:`~service_identity.CertificateError` is raised if the certificate + contains no ``subjectAltName``\ s instead of + :exc:`~service_identity.VerificationError`. """ verify_service_identity( cert_patterns=extract_patterns( @@ -94,9 +112,11 @@ """ Extract all valid ID patterns from a certificate for service verification. - :param cert: The certificate to be dissected. + Args: + cert: The certificate to be dissected. - :return: List of IDs. + Returns: + List of IDs. .. versionchanged:: 23.1.0 ``commonName`` is not used as a fallback anymore. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/tests/certificates.py new/service-identity-24.1.0/tests/certificates.py --- old/service-identity-23.1.0/tests/certificates.py 1970-01-01 01:00:00.000000000 +0100 +++ new/service-identity-24.1.0/tests/certificates.py 2024-01-14 08:05:19.000000000 +0100 @@ -0,0 +1,142 @@ +from cryptography.hazmat.backends import default_backend +from cryptography.x509 import load_pem_x509_certificate + +from service_identity.cryptography import extract_patterns + + +# Test certificates + +PEM_DNS_ONLY = b"""\ +-----BEGIN CERTIFICATE----- +MIIGbjCCBVagAwIBAgIDCesrMA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ +TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0 +YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg +MSBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTMwNDEwMTk1ODA5 +WhcNMTQwNDExMTkyODAwWjB1MRkwFwYDVQQNExBTN2xiQ3Q3TjJSNHQ5bzhKMQsw +CQYDVQQGEwJVUzEeMBwGA1UEAxMVd3d3LnR3aXN0ZWRtYXRyaXguY29tMSswKQYJ +KoZIhvcNAQkBFhxwb3N0bWFzdGVyQHR3aXN0ZWRtYXRyaXguY29tMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxUH8iDxIEiDcMQb8kr/JTYXDGuE8ISQA +uw/gBqpvHIvCgPBkZpvjQLA23rnUZm1S3VG5MIq6gZVdtl9LFIfokMPGgY9EZng8 +BaI+6Y36cMtubnzW53OZb7yLQQyg+rjuwjvJOY33ZulEthxhdB3km1Leb67iE9v7 +dpyKeJ/8m2IWD37HCtXIEnp9ZqWOZkAPzlzDt6oNxj0s/l3z23+XqZdr+kmlh9U+ +VWBTPppO4AJNwSqbBd0PgIozbYsp6urxSr40YQkIYFOOZQNs7HETJE71Ia7DQcUD +kUF1jZSYZnhVQwGPisqQLGodt9q9p2BhpSf0cUm02uKKzYi5A2h7UQIDAQABo4IC +7TCCAukwCQYDVR0TBAIwADALBgNVHQ8EBAMCA6gwEwYDVR0lBAwwCgYIKwYBBQUH +AwEwHQYDVR0OBBYEFGeuUvDrFHkl7Krl/+rlv1FsnsU6MB8GA1UdIwQYMBaAFOtC +NNCYsKuf9BtrCPfMZC7vDixFMDMGA1UdEQQsMCqCFXd3dy50d2lzdGVkbWF0cml4 +LmNvbYIRdHdpc3RlZG1hdHJpeC5jb20wggFWBgNVHSAEggFNMIIBSTAIBgZngQwB +AgEwggE7BgsrBgEEAYG1NwECAzCCASowLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cu +c3RhcnRzc2wuY29tL3BvbGljeS5wZGYwgfcGCCsGAQUFBwICMIHqMCcWIFN0YXJ0 +Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MAMCAQEagb5UaGlzIGNlcnRpZmlj +YXRlIHdhcyBpc3N1ZWQgYWNjb3JkaW5nIHRvIHRoZSBDbGFzcyAxIFZhbGlkYXRp +b24gcmVxdWlyZW1lbnRzIG9mIHRoZSBTdGFydENvbSBDQSBwb2xpY3ksIHJlbGlh +bmNlIG9ubHkgZm9yIHRoZSBpbnRlbmRlZCBwdXJwb3NlIGluIGNvbXBsaWFuY2Ug +b2YgdGhlIHJlbHlpbmcgcGFydHkgb2JsaWdhdGlvbnMuMDUGA1UdHwQuMCwwKqAo +oCaGJGh0dHA6Ly9jcmwuc3RhcnRzc2wuY29tL2NydDEtY3JsLmNybDCBjgYIKwYB +BQUHAQEEgYEwfzA5BggrBgEFBQcwAYYtaHR0cDovL29jc3Auc3RhcnRzc2wuY29t +L3N1Yi9jbGFzczEvc2VydmVyL2NhMEIGCCsGAQUFBzAChjZodHRwOi8vYWlhLnN0 +YXJ0c3NsLmNvbS9jZXJ0cy9zdWIuY2xhc3MxLnNlcnZlci5jYS5jcnQwIwYDVR0S +BBwwGoYYaHR0cDovL3d3dy5zdGFydHNzbC5jb20vMA0GCSqGSIb3DQEBBQUAA4IB +AQCN85dUStYjHmWdXthpAqJcS3KD2JP6N9egOz7FTcToXLW8Kl5a2SUVaJv8Fzs+ +wtbPJQSm0LyGtfdrR6iKFPf28Vm/VkYXPiOV08GD9B7yl1SjktXOsGMPlOHU8YQZ +DEsHOrRvaZBSA1VtBQjYnoO0pDVu9QwDLAPLFvFice2PN803HuMFIwcuQSIrh4nq +PqwitBZ6nPPHz7aSiAut/+txK3EZll0d+hl0H3Phd+ICeITYhNkLe90k7l1IFpET +fJiBDvG/iDAJISgkrR1heuX/e+yWfx7RvqGlMLIE35d+0MhWy92Jzejbl8fJdr4C +Kulh/pV07MWAUZxscUPtWmPo +-----END CERTIFICATE-----""" + +DNS_IDS = extract_patterns( + load_pem_x509_certificate(PEM_DNS_ONLY, default_backend()) +) + +PEM_CN_ONLY = b"""\ +-----BEGIN CERTIFICATE----- +MIIDlzCCAn+gAwIBAgIUNS9qfJRgoLrr68mAfmhzBior0JAwDQYJKoZIhvcNAQEL +BQAwWzELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEUMBIGA1UEAwwLZXhhbXBsZS5jb20w +HhcNMjMwNjA4MDkwNDAxWhcNNDkwMTI3MDkwNDAxWjBbMQswCQYDVQQGEwJBVTET +MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ +dHkgTHRkMRQwEgYDVQQDDAtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBALltBNRAyeFczK2kdKTkW6E3/+rptXBcaw3SyltY/Ft8DPe3 +lW/GWbbgAU7ceYC0LkYxOEnyQTlXhTyLHSk+PCQLi2ESgwWGnGY5Eusk1DRJ162q +hLUkmz25KdTILnh402fgoziF2RU6PnA7iIwAVntT5uh4S1yPW7TWkdPsE0tc1yBx +3SAHTXDkoahjKSot35Q87Jw92fxUd7WqVmDrgcLMvp8rXNjdg+HG4fQGoMcSQq2Z +nVPIoWSTOGdL6SzSs6Wvllz3n7YWShTqp9CmGctCGubt02fHF+8G/dMTTukntG4q +EjBtVfeDFx8yXUdOgN4egFxZGYATAUsLcyzNhQcCAwEAAaNTMFEwHQYDVR0OBBYE +FDkuqwU8KxIvwAwMqVpNFYlgd6WbMB8GA1UdIwQYMBaAFDkuqwU8KxIvwAwMqVpN +FYlgd6WbMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ9Nb/C0 +2gkxhWm3S2/9onPMhFOxDLsYxBvZtJMeOvRRrJaxN2m0aXkm0Ww8Bq0qEegZE51m +0T57IOS256rQlxEnZNeAWT2tf8FEqQGjbI1c/prj420e6afn18x8CSQgiOG4PJ+S +YfufRjSHAYwiiNi+tiKBQ8jOuayFhih9/GsDJvAMW0HjaYZyG6jlA9p4bL1rSqD3 +gE+upYhkpVN1lFRZAhxRZOVIqJV/ppHp9RAuawsUdSNKm+rnlaExJKoVys+tZL9+ +djWWQVqnttYocQQ0umX4ydCTr1RM+7ziwWTR5kpOESA/gZePZQqeH9k+XrPEQtLn +6QBxk+Ft53ZPVso= +-----END CERTIFICATE----- +""" + + +PEM_OTHER_NAME = b"""\ +-----BEGIN CERTIFICATE----- +MIID/DCCAuSgAwIBAgIJAIS0TSddIw6cMA0GCSqGSIb3DQEBBQUAMGwxFDASBgNV +BAMTC2V4YW1wbGUuY29tMSAwHgYJKoZIhvcNAQkBFhFib2d1c0BleGFtcGxlLmNv +bTEUMBIGA1UEChMLRXhhbXBsZSBJbmMxDzANBgNVBAcTBkJlcmxpbjELMAkGA1UE +BhMCREUwHhcNMTQwMzA2MTYyNTA5WhcNMTUwMzA2MTYyNTA5WjBsMRQwEgYDVQQD +EwtleGFtcGxlLmNvbTEgMB4GCSqGSIb3DQEJARYRYm9ndXNAZXhhbXBsZS5jb20x +FDASBgNVBAoTC0V4YW1wbGUgSW5jMQ8wDQYDVQQHEwZCZXJsaW4xCzAJBgNVBAYT +AkRFMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxGQUcOc8cAdzSJbk +0eCHA1qBY2XwRG8YQzihgQS8Ey+3j69Xf0mtWOlL6v23v8J1ilA7ERs87Y4nbV/9 +GJVhC/jTMZmrC6ogwtVIl1wL8sTiHaQZ/4pbpx57YW3qCdefLQrZqAMUgAe20z0G +YVU97u5EGXHYahG4TnB3xN6Qd3BGKP7K69Lb7ZOES2Esq533AZxZShseYR4JNYAc +2anag2/DpHw6k8ZaxtWHR4SmxlkCoW5IPK0YypeUY91PFY+dxJQEewtisfALKltE +SYnOTWkc0K9YuLuYVogx0K285wX4/Yha2wyo6KSAm0txJayOhcrEP2/34aWCl62m +xOtPbQIDAQABo4GgMIGdMIGaBgNVHREEgZIwgY+CDSouZXhhbXBsZS5uZXSCC2V4 +YW1wbGUuY29thwTAqAABhxAAEwAAAAAAAAAAAAAAAAAXhhNodHRwOi8vZXhhbXBs +ZS5jb20voCYGCCsGAQUFBwgHoBoWGF94bXBwLWNsaWVudC5leGFtcGxlLm5ldKAc +BggrBgEFBQcIBaAQDA5pbS5leGFtcGxlLmNvbTANBgkqhkiG9w0BAQUFAAOCAQEA +ACVQcgEKzXEw0M9mmVFFXL2SyDk/4oaDFZbnNfyUp+H7bnxdVBG2M3DzQQLw5yH5 +k4GNPvHOKshBbaFcZWiG1sdrfQJy/UjIWnaC5410npfBv7kJWafKKxZzMq3gp4rd +jPO2LxuWcYVOnUtA3CBe12tRV7ynGU8KmKOsU9bOWhUKo8DJ4a6XHB+YwXeOTPyU +mG7XBpQebT01I3OijFJ+apKR2ubjwZE8l1+BAlTzHyUmmcTTWTQk8FTFcP3nZuIr +VyudDBMASs4yVGHzQxmMalYYzd7ZDzM1NrgfG1KyKWqZEA0MzUxiYdUbZN79xL52 +EyKUOXPHw78G6zsVmAE1Aw== +-----END CERTIFICATE-----""" + + +PEM_EVERYTHING = b"""\ +-----BEGIN CERTIFICATE----- +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 +3HotzNMgpPpx8C2KKLKKaiIGRY0pg/WC6w== +-----END CERTIFICATE-----""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/tests/conftest.py new/service-identity-24.1.0/tests/conftest.py --- old/service-identity-23.1.0/tests/conftest.py 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/tests/conftest.py 2024-01-14 08:05:19.000000000 +0100 @@ -18,11 +18,7 @@ openssl_version = "n/a" pyopenssl_version = "missing" - return """\ -OpenSSL: {openssl} -pyOpenSSL: {pyOpenSSL} -cryptography: {cryptography}""".format( - openssl=openssl_version, - pyOpenSSL=pyopenssl_version, - cryptography=cryptography.__version__, - ) + return f"""\ +OpenSSL: {openssl_version} +pyOpenSSL: {pyopenssl_version} +cryptography: {cryptography.__version__}""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/tests/test_cryptography.py new/service-identity-24.1.0/tests/test_cryptography.py --- old/service-identity-23.1.0/tests/test_cryptography.py 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/tests/test_cryptography.py 2024-01-14 08:05:19.000000000 +0100 @@ -12,6 +12,7 @@ verify_certificate_ip_address, ) from service_identity.exceptions import ( + CertificateError, DNSMismatch, IPAddressMismatch, VerificationError, @@ -24,7 +25,12 @@ URIPattern, ) -from .util import PEM_CN_ONLY, PEM_DNS_ONLY, PEM_EVERYTHING, PEM_OTHER_NAME +from .certificates import ( + PEM_CN_ONLY, + PEM_DNS_ONLY, + PEM_EVERYTHING, + PEM_OTHER_NAME, +) backend = default_backend() @@ -35,6 +41,29 @@ class TestPublicAPI: + def test_no_cert_patterns_hostname(self): + """ + A certificate without subjectAltNames raises a helpful + CertificateError. + """ + with pytest.raises( + CertificateError, + match="Certificate does not contain any `subjectAltName`s.", + ): + verify_certificate_hostname(X509_CN_ONLY, "example.com") + + @pytest.mark.parametrize("ip", ["203.0.113.0", "2001:db8::"]) + def test_no_cert_patterns_ip_address(self, ip): + """ + A certificate without subjectAltNames raises a helpful + CertificateError. + """ + with pytest.raises( + CertificateError, + match="Certificate does not contain any `subjectAltName`s.", + ): + verify_certificate_ip_address(X509_CN_ONLY, ip) + def test_certificate_verify_hostname_ok(self): """ verify_certificate_hostname succeeds if the hostnames match. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/tests/test_hazmat.py new/service-identity-24.1.0/tests/test_hazmat.py --- old/service-identity-23.1.0/tests/test_hazmat.py 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/tests/test_hazmat.py 2024-01-14 08:05:19.000000000 +0100 @@ -30,8 +30,8 @@ verify_service_identity, ) +from .certificates import DNS_IDS from .test_cryptography import CERT_EVERYTHING -from .util import DNS_IDS try: @@ -45,6 +45,18 @@ Simple integration tests for verify_service_identity. """ + def test_no_cert_patterns(self): + """ + Empty cert patterns raise a helpful CertificateError. + """ + with pytest.raises( + CertificateError, + match="Certificate does not contain any `subjectAltName`s.", + ): + verify_service_identity( + cert_patterns=[], obligatory_ids=[], optional_ids=[] + ) + def test_dns_id_success(self): """ Return pairs of certificate ids and service ids on matches. @@ -693,7 +705,7 @@ assert repr(e) == str(e) assert str(e) != "" - @pytest.mark.parametrize("proto", range(0, pickle.HIGHEST_PROTOCOL + 1)) + @pytest.mark.parametrize("proto", range(pickle.HIGHEST_PROTOCOL + 1)) @pytest.mark.parametrize( "exc", [ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/tests/test_packaging.py new/service-identity-24.1.0/tests/test_packaging.py --- old/service-identity-23.1.0/tests/test_packaging.py 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/tests/test_packaging.py 2024-01-14 08:05:19.000000000 +0100 @@ -1,16 +1,10 @@ -import sys +from importlib import metadata import pytest import service_identity -if sys.version_info < (3, 8): - import importlib_metadata as metadata -else: - from importlib import metadata - - class TestLegacyMetadataHack: def test_version(self): """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/tests/test_pyopenssl.py new/service-identity-24.1.0/tests/test_pyopenssl.py --- old/service-identity-23.1.0/tests/test_pyopenssl.py 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/tests/test_pyopenssl.py 2024-01-14 08:05:19.000000000 +0100 @@ -21,7 +21,12 @@ verify_ip_address, ) -from .util import PEM_CN_ONLY, PEM_DNS_ONLY, PEM_EVERYTHING, PEM_OTHER_NAME +from .certificates import ( + PEM_CN_ONLY, + PEM_DNS_ONLY, + PEM_EVERYTHING, + PEM_OTHER_NAME, +) if pytest.importorskip("OpenSSL"): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/tests/util.py new/service-identity-24.1.0/tests/util.py --- old/service-identity-23.1.0/tests/util.py 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/tests/util.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,142 +0,0 @@ -from cryptography.hazmat.backends import default_backend -from cryptography.x509 import load_pem_x509_certificate - -from service_identity.cryptography import extract_patterns - - -# Test certificates - -PEM_DNS_ONLY = b"""\ ------BEGIN CERTIFICATE----- -MIIGbjCCBVagAwIBAgIDCesrMA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ -TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0 -YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg -MSBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTMwNDEwMTk1ODA5 -WhcNMTQwNDExMTkyODAwWjB1MRkwFwYDVQQNExBTN2xiQ3Q3TjJSNHQ5bzhKMQsw -CQYDVQQGEwJVUzEeMBwGA1UEAxMVd3d3LnR3aXN0ZWRtYXRyaXguY29tMSswKQYJ -KoZIhvcNAQkBFhxwb3N0bWFzdGVyQHR3aXN0ZWRtYXRyaXguY29tMIIBIjANBgkq -hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxUH8iDxIEiDcMQb8kr/JTYXDGuE8ISQA -uw/gBqpvHIvCgPBkZpvjQLA23rnUZm1S3VG5MIq6gZVdtl9LFIfokMPGgY9EZng8 -BaI+6Y36cMtubnzW53OZb7yLQQyg+rjuwjvJOY33ZulEthxhdB3km1Leb67iE9v7 -dpyKeJ/8m2IWD37HCtXIEnp9ZqWOZkAPzlzDt6oNxj0s/l3z23+XqZdr+kmlh9U+ -VWBTPppO4AJNwSqbBd0PgIozbYsp6urxSr40YQkIYFOOZQNs7HETJE71Ia7DQcUD -kUF1jZSYZnhVQwGPisqQLGodt9q9p2BhpSf0cUm02uKKzYi5A2h7UQIDAQABo4IC -7TCCAukwCQYDVR0TBAIwADALBgNVHQ8EBAMCA6gwEwYDVR0lBAwwCgYIKwYBBQUH -AwEwHQYDVR0OBBYEFGeuUvDrFHkl7Krl/+rlv1FsnsU6MB8GA1UdIwQYMBaAFOtC -NNCYsKuf9BtrCPfMZC7vDixFMDMGA1UdEQQsMCqCFXd3dy50d2lzdGVkbWF0cml4 -LmNvbYIRdHdpc3RlZG1hdHJpeC5jb20wggFWBgNVHSAEggFNMIIBSTAIBgZngQwB -AgEwggE7BgsrBgEEAYG1NwECAzCCASowLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cu -c3RhcnRzc2wuY29tL3BvbGljeS5wZGYwgfcGCCsGAQUFBwICMIHqMCcWIFN0YXJ0 -Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MAMCAQEagb5UaGlzIGNlcnRpZmlj -YXRlIHdhcyBpc3N1ZWQgYWNjb3JkaW5nIHRvIHRoZSBDbGFzcyAxIFZhbGlkYXRp -b24gcmVxdWlyZW1lbnRzIG9mIHRoZSBTdGFydENvbSBDQSBwb2xpY3ksIHJlbGlh -bmNlIG9ubHkgZm9yIHRoZSBpbnRlbmRlZCBwdXJwb3NlIGluIGNvbXBsaWFuY2Ug -b2YgdGhlIHJlbHlpbmcgcGFydHkgb2JsaWdhdGlvbnMuMDUGA1UdHwQuMCwwKqAo -oCaGJGh0dHA6Ly9jcmwuc3RhcnRzc2wuY29tL2NydDEtY3JsLmNybDCBjgYIKwYB -BQUHAQEEgYEwfzA5BggrBgEFBQcwAYYtaHR0cDovL29jc3Auc3RhcnRzc2wuY29t -L3N1Yi9jbGFzczEvc2VydmVyL2NhMEIGCCsGAQUFBzAChjZodHRwOi8vYWlhLnN0 -YXJ0c3NsLmNvbS9jZXJ0cy9zdWIuY2xhc3MxLnNlcnZlci5jYS5jcnQwIwYDVR0S -BBwwGoYYaHR0cDovL3d3dy5zdGFydHNzbC5jb20vMA0GCSqGSIb3DQEBBQUAA4IB -AQCN85dUStYjHmWdXthpAqJcS3KD2JP6N9egOz7FTcToXLW8Kl5a2SUVaJv8Fzs+ -wtbPJQSm0LyGtfdrR6iKFPf28Vm/VkYXPiOV08GD9B7yl1SjktXOsGMPlOHU8YQZ -DEsHOrRvaZBSA1VtBQjYnoO0pDVu9QwDLAPLFvFice2PN803HuMFIwcuQSIrh4nq -PqwitBZ6nPPHz7aSiAut/+txK3EZll0d+hl0H3Phd+ICeITYhNkLe90k7l1IFpET -fJiBDvG/iDAJISgkrR1heuX/e+yWfx7RvqGlMLIE35d+0MhWy92Jzejbl8fJdr4C -Kulh/pV07MWAUZxscUPtWmPo ------END CERTIFICATE-----""" - -DNS_IDS = extract_patterns( - load_pem_x509_certificate(PEM_DNS_ONLY, default_backend()) -) - -PEM_CN_ONLY = b"""\ ------BEGIN CERTIFICATE----- -MIIDlzCCAn+gAwIBAgIUNS9qfJRgoLrr68mAfmhzBior0JAwDQYJKoZIhvcNAQEL -BQAwWzELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM -GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEUMBIGA1UEAwwLZXhhbXBsZS5jb20w -HhcNMjMwNjA4MDkwNDAxWhcNNDkwMTI3MDkwNDAxWjBbMQswCQYDVQQGEwJBVTET -MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ -dHkgTHRkMRQwEgYDVQQDDAtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBALltBNRAyeFczK2kdKTkW6E3/+rptXBcaw3SyltY/Ft8DPe3 -lW/GWbbgAU7ceYC0LkYxOEnyQTlXhTyLHSk+PCQLi2ESgwWGnGY5Eusk1DRJ162q -hLUkmz25KdTILnh402fgoziF2RU6PnA7iIwAVntT5uh4S1yPW7TWkdPsE0tc1yBx -3SAHTXDkoahjKSot35Q87Jw92fxUd7WqVmDrgcLMvp8rXNjdg+HG4fQGoMcSQq2Z -nVPIoWSTOGdL6SzSs6Wvllz3n7YWShTqp9CmGctCGubt02fHF+8G/dMTTukntG4q -EjBtVfeDFx8yXUdOgN4egFxZGYATAUsLcyzNhQcCAwEAAaNTMFEwHQYDVR0OBBYE -FDkuqwU8KxIvwAwMqVpNFYlgd6WbMB8GA1UdIwQYMBaAFDkuqwU8KxIvwAwMqVpN -FYlgd6WbMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ9Nb/C0 -2gkxhWm3S2/9onPMhFOxDLsYxBvZtJMeOvRRrJaxN2m0aXkm0Ww8Bq0qEegZE51m -0T57IOS256rQlxEnZNeAWT2tf8FEqQGjbI1c/prj420e6afn18x8CSQgiOG4PJ+S -YfufRjSHAYwiiNi+tiKBQ8jOuayFhih9/GsDJvAMW0HjaYZyG6jlA9p4bL1rSqD3 -gE+upYhkpVN1lFRZAhxRZOVIqJV/ppHp9RAuawsUdSNKm+rnlaExJKoVys+tZL9+ -djWWQVqnttYocQQ0umX4ydCTr1RM+7ziwWTR5kpOESA/gZePZQqeH9k+XrPEQtLn -6QBxk+Ft53ZPVso= ------END CERTIFICATE----- -""" - - -PEM_OTHER_NAME = b"""\ ------BEGIN CERTIFICATE----- -MIID/DCCAuSgAwIBAgIJAIS0TSddIw6cMA0GCSqGSIb3DQEBBQUAMGwxFDASBgNV -BAMTC2V4YW1wbGUuY29tMSAwHgYJKoZIhvcNAQkBFhFib2d1c0BleGFtcGxlLmNv -bTEUMBIGA1UEChMLRXhhbXBsZSBJbmMxDzANBgNVBAcTBkJlcmxpbjELMAkGA1UE -BhMCREUwHhcNMTQwMzA2MTYyNTA5WhcNMTUwMzA2MTYyNTA5WjBsMRQwEgYDVQQD -EwtleGFtcGxlLmNvbTEgMB4GCSqGSIb3DQEJARYRYm9ndXNAZXhhbXBsZS5jb20x -FDASBgNVBAoTC0V4YW1wbGUgSW5jMQ8wDQYDVQQHEwZCZXJsaW4xCzAJBgNVBAYT -AkRFMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxGQUcOc8cAdzSJbk -0eCHA1qBY2XwRG8YQzihgQS8Ey+3j69Xf0mtWOlL6v23v8J1ilA7ERs87Y4nbV/9 -GJVhC/jTMZmrC6ogwtVIl1wL8sTiHaQZ/4pbpx57YW3qCdefLQrZqAMUgAe20z0G -YVU97u5EGXHYahG4TnB3xN6Qd3BGKP7K69Lb7ZOES2Esq533AZxZShseYR4JNYAc -2anag2/DpHw6k8ZaxtWHR4SmxlkCoW5IPK0YypeUY91PFY+dxJQEewtisfALKltE -SYnOTWkc0K9YuLuYVogx0K285wX4/Yha2wyo6KSAm0txJayOhcrEP2/34aWCl62m -xOtPbQIDAQABo4GgMIGdMIGaBgNVHREEgZIwgY+CDSouZXhhbXBsZS5uZXSCC2V4 -YW1wbGUuY29thwTAqAABhxAAEwAAAAAAAAAAAAAAAAAXhhNodHRwOi8vZXhhbXBs -ZS5jb20voCYGCCsGAQUFBwgHoBoWGF94bXBwLWNsaWVudC5leGFtcGxlLm5ldKAc -BggrBgEFBQcIBaAQDA5pbS5leGFtcGxlLmNvbTANBgkqhkiG9w0BAQUFAAOCAQEA -ACVQcgEKzXEw0M9mmVFFXL2SyDk/4oaDFZbnNfyUp+H7bnxdVBG2M3DzQQLw5yH5 -k4GNPvHOKshBbaFcZWiG1sdrfQJy/UjIWnaC5410npfBv7kJWafKKxZzMq3gp4rd -jPO2LxuWcYVOnUtA3CBe12tRV7ynGU8KmKOsU9bOWhUKo8DJ4a6XHB+YwXeOTPyU -mG7XBpQebT01I3OijFJ+apKR2ubjwZE8l1+BAlTzHyUmmcTTWTQk8FTFcP3nZuIr -VyudDBMASs4yVGHzQxmMalYYzd7ZDzM1NrgfG1KyKWqZEA0MzUxiYdUbZN79xL52 -EyKUOXPHw78G6zsVmAE1Aw== ------END CERTIFICATE-----""" - - -PEM_EVERYTHING = b"""\ ------BEGIN CERTIFICATE----- -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 -3HotzNMgpPpx8C2KKLKKaiIGRY0pg/WC6w== ------END CERTIFICATE-----""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/service-identity-23.1.0/tox.ini new/service-identity-24.1.0/tox.ini --- old/service-identity-23.1.0/tox.ini 2023-06-14 09:54:35.000000000 +0200 +++ new/service-identity-24.1.0/tox.ini 2024-01-14 08:05:19.000000000 +0100 @@ -25,7 +25,17 @@ pyopenssl-oldest: PIP_CONSTRAINT = tests/constraints/oldest-pyopenssl.txt commands = coverage run -m pytest {posargs} - py311-pyopenssl-latest-idna: coverage run -m pytest --doctest-modules --doctest-glob='*.rst' {posargs} + py312-pyopenssl-latest-idna: coverage run -m pytest --doctest-modules --doctest-glob='*.rst' {posargs} + + +[testenv:coverage-report] +# keep in-sync with .python-version-default +base_python = py312 +deps = coverage[toml]>=5.0.2 +skip_install = true +commands = + coverage combine + coverage report [testenv:lint] @@ -46,18 +56,25 @@ [testenv:docs] # Keep in-sync with gh-actions and .readthedocs.yaml. -base_python = py311 +base_python = py312 extras = docs commands = sphinx-build -W -b html -d {envtmpdir}/doctrees docs docs/_build/html sphinx-build -W -b doctest -d {envtmpdir}/doctrees docs docs/_build/html - -[testenv:coverage-report] -# keep in-sync with .python-version-default -base_python = py311 -deps = coverage[toml]>=5.0.2 -skip_install = true +[testenv:docs-watch] +package = editable +base_python = {[testenv:docs]base_python} +extras = {[testenv:docs]extras} +deps = watchfiles commands = - coverage combine - coverage report + watchfiles \ + --ignore-paths docs/_build/ \ + 'sphinx-build -W -n --jobs auto -b html -d {envtmpdir}/doctrees docs docs/_build/html' \ + src \ + docs + +[testenv:docs-linkcheck] +base_python = {[testenv:docs]base_python} +extras = {[testenv:docs]extras} +commands = sphinx-build -W -b linkcheck -d {envtmpdir}/doctrees docs docs/_build/html