Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-jaraco.packaging for 
openSUSE:Factory checked in at 2026-04-14 17:48:30
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-jaraco.packaging (Old)
 and      /work/SRC/openSUSE:Factory/.python-jaraco.packaging.new.21863 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-jaraco.packaging"

Tue Apr 14 17:48:30 2026 rev:14 rq:1346319 version:10.4.0

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-jaraco.packaging/python-jaraco.packaging.changes
  2025-04-11 16:45:36.196258135 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-jaraco.packaging.new.21863/python-jaraco.packaging.changes
       2026-04-14 17:48:46.532670631 +0200
@@ -1,0 +2,10 @@
+Mon Apr 13 02:39:46 UTC 2026 - Steve Kowalik <[email protected]>
+
+- Update to 10.4.0:
+  * Added releases option to sidebar-links directive, generating a link to
+    the GitHub releases page from the Source URL in project metadata.
+  * Complete annotations and add py.typed marker.
+  * Enabled strict type checking.
+  * Inline the definition of StrPath.
+
+-------------------------------------------------------------------

Old:
----
  jaraco_packaging-10.2.3.tar.gz

New:
----
  jaraco_packaging-10.4.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-jaraco.packaging.spec ++++++
--- /var/tmp/diff_new_pack.KWfSdz/_old  2026-04-14 17:48:47.220699070 +0200
+++ /var/tmp/diff_new_pack.KWfSdz/_new  2026-04-14 17:48:47.220699070 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-jaraco.packaging
 #
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # 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 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-jaraco.packaging
-Version:        10.2.3
+Version:        10.4.0
 Release:        0
 Summary:        Supplement packaging Python releases
 License:        MIT
@@ -67,8 +67,11 @@
 
 %check
 export PIP_FIND_LINKS=$(dirname %{SOURCE10})
-# Broken by https://github.com/pytest-dev/pytest/issues/12303
-%pytest -k 'not (packaging.metadata.hunt_down_url or 
packaging.print-metadata.main)'
+export PYTHONPATH=.
+# Requires large amount of external wheels to install
+donttest="metadata.hunt_down_url or print-metadata.main"
+donttest+=" or metadata.get_source_url or sphinx.load_config_from_setup"
+%pytest -k "not ($donttest)"
 
 %files %{python_files}
 %license LICENSE

++++++ jaraco_packaging-10.2.3.tar.gz -> jaraco_packaging-10.4.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jaraco_packaging-10.2.3/.coveragerc 
new/jaraco_packaging-10.4.0/.coveragerc
--- old/jaraco_packaging-10.2.3/.coveragerc     2024-08-20 05:01:28.000000000 
+0200
+++ new/jaraco_packaging-10.4.0/.coveragerc     2026-02-22 17:40:06.000000000 
+0100
@@ -8,6 +8,8 @@
 [report]
 show_missing = True
 exclude_also =
-       # jaraco/skeleton#97
-       @overload
+       # Exclude common false positives per
+       # 
https://coverage.readthedocs.io/en/latest/excluding.html#advanced-exclusion
+       # Ref jaraco/skeleton#97 and jaraco/skeleton#135
+       class .*\bProtocol\):
        if TYPE_CHECKING:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jaraco_packaging-10.2.3/.github/dependabot.yml 
new/jaraco_packaging-10.4.0/.github/dependabot.yml
--- old/jaraco_packaging-10.2.3/.github/dependabot.yml  2024-08-20 
05:01:28.000000000 +0200
+++ new/jaraco_packaging-10.4.0/.github/dependabot.yml  1970-01-01 
01:00:00.000000000 +0100
@@ -1,8 +0,0 @@
-version: 2
-updates:
-  - package-ecosystem: "pip"
-    directory: "/"
-    schedule:
-      interval: "daily"
-    allow:
-      - dependency-type: "all"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jaraco_packaging-10.2.3/.github/workflows/main.yml 
new/jaraco_packaging-10.4.0/.github/workflows/main.yml
--- old/jaraco_packaging-10.2.3/.github/workflows/main.yml      2024-08-20 
05:01:28.000000000 +0200
+++ new/jaraco_packaging-10.4.0/.github/workflows/main.yml      2026-02-22 
17:40:06.000000000 +0100
@@ -10,6 +10,7 @@
     # required if branches-ignore is supplied (jaraco/skeleton#103)
     - '**'
   pull_request:
+  workflow_dispatch:
 
 permissions:
   contents: read
@@ -20,7 +21,6 @@
 
   # Suppress noisy pip warnings
   PIP_DISABLE_PIP_VERSION_CHECK: 'true'
-  PIP_NO_PYTHON_VERSION_WARNING: 'true'
   PIP_NO_WARN_SCRIPT_LOCATION: 'true'
 
   # Ensure tests can sense settings about the environment
@@ -34,27 +34,36 @@
       # https://blog.jaraco.com/efficient-use-of-ci-resources/
       matrix:
         python:
-        - "3.8"
-        - "3.12"
+        - "3.9"
+        - "3.13"
         platform:
         - ubuntu-latest
         - macos-latest
         - windows-latest
         include:
-        - python: "3.9"
-          platform: ubuntu-latest
         - python: "3.10"
           platform: ubuntu-latest
         - python: "3.11"
           platform: ubuntu-latest
+        - python: "3.12"
+          platform: ubuntu-latest
+        - python: "3.14"
+          platform: ubuntu-latest
         - python: pypy3.10
           platform: ubuntu-latest
     runs-on: ${{ matrix.platform }}
-    continue-on-error: ${{ matrix.python == '3.13' }}
+    continue-on-error: ${{ matrix.python == '3.14' }}
     steps:
       - uses: actions/checkout@v4
+      - name: Install build dependencies
+        # Install dependencies for building packages on pre-release Pythons
+        # jaraco/skeleton#161
+        if: matrix.python == '3.14' && matrix.platform == 'ubuntu-latest'
+        run: |
+          sudo apt update
+          sudo apt install -y libxml2-dev libxslt-dev
       - name: Setup Python
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: ${{ matrix.python }}
           allow-prereleases: true
@@ -76,7 +85,7 @@
         with:
           fetch-depth: 0
       - name: Setup Python
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: 3.x
       - name: Install tox
@@ -110,7 +119,7 @@
     steps:
       - uses: actions/checkout@v4
       - name: Setup Python
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: 3.x
       - name: Install tox
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jaraco_packaging-10.2.3/.pre-commit-config.yaml 
new/jaraco_packaging-10.4.0/.pre-commit-config.yaml
--- old/jaraco_packaging-10.2.3/.pre-commit-config.yaml 2024-08-20 
05:01:28.000000000 +0200
+++ new/jaraco_packaging-10.4.0/.pre-commit-config.yaml 2026-02-22 
17:40:06.000000000 +0100
@@ -1,6 +1,7 @@
 repos:
 - repo: https://github.com/astral-sh/ruff-pre-commit
-  rev: v0.1.8
+  rev: v0.12.0
   hooks:
   - id: ruff
+    args: [--fix, --unsafe-fixes]
   - id: ruff-format
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jaraco_packaging-10.2.3/.readthedocs.yaml 
new/jaraco_packaging-10.4.0/.readthedocs.yaml
--- old/jaraco_packaging-10.2.3/.readthedocs.yaml       2024-08-20 
05:01:28.000000000 +0200
+++ new/jaraco_packaging-10.4.0/.readthedocs.yaml       2026-02-22 
17:40:06.000000000 +0100
@@ -5,6 +5,9 @@
     extra_requirements:
       - doc
 
+sphinx:
+  configuration: docs/conf.py
+
 # required boilerplate readthedocs/readthedocs.org#10401
 build:
   os: ubuntu-lts-latest
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jaraco_packaging-10.2.3/LICENSE 
new/jaraco_packaging-10.4.0/LICENSE
--- old/jaraco_packaging-10.2.3/LICENSE 2024-08-20 05:01:28.000000000 +0200
+++ new/jaraco_packaging-10.4.0/LICENSE 2026-02-22 17:40:27.000000000 +0100
@@ -1,17 +1,18 @@
-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 the Software without restriction, including without limitation the
-rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-sell copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
+MIT License
 
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
+Copyright (c) 2026 <copyright holders>
 
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-IN THE SOFTWARE.
+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 the Software 
without restriction, including
+without limitation the rights to use, copy, modify, merge, publish, 
distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is 
furnished to do so, subject to the
+following conditions:
+
+The above copyright notice and this permission notice shall be included in all 
copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
IMPLIED, INCLUDING BUT NOT
+LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE 
AND NONINFRINGEMENT. IN NO
+EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 
OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jaraco_packaging-10.2.3/NEWS.rst 
new/jaraco_packaging-10.4.0/NEWS.rst
--- old/jaraco_packaging-10.2.3/NEWS.rst        2024-08-20 05:01:28.000000000 
+0200
+++ new/jaraco_packaging-10.4.0/NEWS.rst        2026-02-22 17:40:06.000000000 
+0100
@@ -1,3 +1,28 @@
+v10.4.0
+=======
+
+Features
+--------
+
+- Added ``releases`` option to ``sidebar-links`` directive, generating a link 
to the GitHub releases page from the ``Source`` URL in project metadata. (#23)
+
+
+v10.3.0
+=======
+
+Features
+--------
+
+- Complete annotations and add ``py.typed`` marker -- by :user:`Avasam` (#20)
+- Enabled strict type checking. (#20)
+
+
+Bugfixes
+--------
+
+- Inline the definition of StrPath. (#22)
+
+
 v10.2.3
 =======
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jaraco_packaging-10.2.3/PKG-INFO 
new/jaraco_packaging-10.4.0/PKG-INFO
--- old/jaraco_packaging-10.2.3/PKG-INFO        2024-08-20 05:01:49.005039700 
+0200
+++ new/jaraco_packaging-10.4.0/PKG-INFO        2026-02-22 17:40:28.007702400 
+0100
@@ -1,16 +1,16 @@
-Metadata-Version: 2.1
+Metadata-Version: 2.4
 Name: jaraco.packaging
-Version: 10.2.3
+Version: 10.4.0
 Summary: tools to supplement packaging Python releases
 Author-email: "Jason R. Coombs" <[email protected]>
+License-Expression: MIT
 Project-URL: Source, https://github.com/jaraco/jaraco.packaging
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: MIT License
 Classifier: Programming Language :: Python :: 3
 Classifier: Programming Language :: Python :: 3 :: Only
 Classifier: Framework :: Sphinx :: Extension
-Requires-Python: >=3.8
+Requires-Python: >=3.9
 Description-Content-Type: text/x-rst
 License-File: LICENSE
 Requires-Dist: build[virtualenv]
@@ -19,11 +19,6 @@
 Requires-Dist: domdf-python-tools
 Provides-Extra: test
 Requires-Dist: pytest!=8.1.*,>=6; extra == "test"
-Requires-Dist: pytest-checkdocs>=2.4; extra == "test"
-Requires-Dist: pytest-cov; extra == "test"
-Requires-Dist: pytest-mypy; extra == "test"
-Requires-Dist: pytest-enabler>=2.2; extra == "test"
-Requires-Dist: pytest-ruff>=0.2.1; sys_platform != "cygwin" and extra == "test"
 Requires-Dist: types-docutils; extra == "test"
 Provides-Extra: doc
 Requires-Dist: sphinx>=3.5; extra == "doc"
@@ -31,6 +26,18 @@
 Requires-Dist: rst.linker>=1.9; extra == "doc"
 Requires-Dist: furo; extra == "doc"
 Requires-Dist: sphinx-lint; extra == "doc"
+Provides-Extra: check
+Requires-Dist: pytest-checkdocs>=2.4; extra == "check"
+Requires-Dist: pytest-ruff>=0.2.1; sys_platform != "cygwin" and extra == 
"check"
+Provides-Extra: cover
+Requires-Dist: pytest-cov; extra == "cover"
+Provides-Extra: enabler
+Requires-Dist: pytest-enabler>=3.4; extra == "enabler"
+Provides-Extra: type
+Requires-Dist: pytest-mypy>=1.0.1; extra == "type"
+Requires-Dist: mypy<1.19; platform_python_implementation == "PyPy" and extra 
== "type"
+Requires-Dist: importlib_metadata; extra == "type"
+Dynamic: license-file
 
 .. image:: https://img.shields.io/pypi/v/jaraco.packaging.svg
    :target: https://pypi.org/project/jaraco.packaging
@@ -41,14 +48,14 @@
    :target: 
https://github.com/jaraco/jaraco.packaging/actions?query=workflow%3A%22tests%22
    :alt: tests
 
-.. image:: 
https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json
+.. image:: 
https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
     :target: https://github.com/astral-sh/ruff
     :alt: Ruff
 
 .. image:: 
https://readthedocs.org/projects/jaracopackaging/badge/?version=latest
    :target: https://jaracopackaging.readthedocs.io/en/latest/?badge=latest
 
-.. image:: https://img.shields.io/badge/skeleton-2024-informational
+.. image:: https://img.shields.io/badge/skeleton-2025-informational
    :target: https://blog.jaraco.com/skeleton
 
 Tools for packaging.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jaraco_packaging-10.2.3/README.rst 
new/jaraco_packaging-10.4.0/README.rst
--- old/jaraco_packaging-10.2.3/README.rst      2024-08-20 05:01:28.000000000 
+0200
+++ new/jaraco_packaging-10.4.0/README.rst      2026-02-22 17:40:06.000000000 
+0100
@@ -7,14 +7,14 @@
    :target: 
https://github.com/jaraco/jaraco.packaging/actions?query=workflow%3A%22tests%22
    :alt: tests
 
-.. image:: 
https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json
+.. image:: 
https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
     :target: https://github.com/astral-sh/ruff
     :alt: Ruff
 
 .. image:: 
https://readthedocs.org/projects/jaracopackaging/badge/?version=latest
    :target: https://jaracopackaging.readthedocs.io/en/latest/?badge=latest
 
-.. image:: https://img.shields.io/badge/skeleton-2024-informational
+.. image:: https://img.shields.io/badge/skeleton-2025-informational
    :target: https://blog.jaraco.com/skeleton
 
 Tools for packaging.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jaraco_packaging-10.2.3/conftest.py 
new/jaraco_packaging-10.4.0/conftest.py
--- old/jaraco_packaging-10.2.3/conftest.py     2024-08-20 05:01:28.000000000 
+0200
+++ new/jaraco_packaging-10.4.0/conftest.py     2026-02-22 17:40:06.000000000 
+0100
@@ -1,10 +1,11 @@
 import subprocess
+from pathlib import Path
 
 import pytest
 
 
 @pytest.fixture
-def static_wheel(tmp_path, monkeypatch):
+def static_wheel(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
     subprocess.check_call(
         ['pip', 'download', '--no-deps', '--dest', str(tmp_path), 
'sampleproject'],
         stderr=subprocess.DEVNULL,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jaraco_packaging-10.2.3/docs/conf.py 
new/jaraco_packaging-10.4.0/docs/conf.py
--- old/jaraco_packaging-10.2.3/docs/conf.py    2024-08-20 05:01:28.000000000 
+0200
+++ new/jaraco_packaging-10.4.0/docs/conf.py    2026-02-22 17:40:06.000000000 
+0100
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 extensions = [
     'sphinx.ext.autodoc',
     'jaraco.packaging.sphinx',
@@ -30,6 +32,7 @@
 
 # Be strict about any broken references
 nitpicky = True
+nitpick_ignore: list[tuple[str, str]] = []
 
 # Include Python intersphinx mapping to prevent failures
 # jaraco/skeleton#51
@@ -41,3 +44,14 @@
 
 # Preserve authored syntax for defaults
 autodoc_preserve_defaults = True
+
+# Add support for linking usernames, PyPI projects, Wikipedia pages
+github_url = 'https://github.com/'
+extlinks = {
+    'user': (f'{github_url}%s', '@%s'),
+    'pypi': ('https://pypi.org/project/%s', '%s'),
+    'wiki': ('https://wikipedia.org/wiki/%s', '%s'),
+}
+extensions += ['sphinx.ext.extlinks']
+
+# local
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/jaraco_packaging-10.2.3/jaraco/packaging/make-tree.py 
new/jaraco_packaging-10.4.0/jaraco/packaging/make-tree.py
--- old/jaraco_packaging-10.2.3/jaraco/packaging/make-tree.py   2024-08-20 
05:01:28.000000000 +0200
+++ new/jaraco_packaging-10.4.0/jaraco/packaging/make-tree.py   2026-02-22 
17:40:06.000000000 +0100
@@ -3,35 +3,47 @@
 a tree rooted at the indicated package.
 """
 
+from __future__ import annotations
+
 import itertools
 import json
 import sys
+from collections.abc import Iterable, Mapping
+from typing import TYPE_CHECKING, Any, TypeVar
+
+if TYPE_CHECKING:
+    from typing_extensions import Self
+
+_T = TypeVar("_T")
 
 
-def by_package_key(item):
+def by_package_key(
+    item: Mapping[str, Mapping[str, _T]],
+) -> _T:
     return by_key(item['package'])
 
 
-def by_key(item):
+def by_key(item: Mapping[str, _T]) -> _T:
     return item['key']
 
 
-def main():
+def main() -> None:
     (root,) = sys.argv[1:]
     pkgs = Packages.from_defn(json.load(sys.stdin))
     json.dump(pkgs.make_tree(root), sys.stdout)
 
 
-class Packages(dict):
+class Packages(dict[str, dict[str, Any]]):
     @classmethod
-    def from_defn(cls, items):
+    def from_defn(cls, items: Iterable[dict[str, Any]]) -> Self:
         return cls(
             (key, next(items))
             for key, items in itertools.groupby(items, by_package_key)
         )
 
-    def make_tree(self, target):
-        vars(self).setdefault('visited', set())
+    def make_tree(self, target: str) -> dict[str, Any]:
+        if not hasattr(self, 'visited'):
+            self.visited: set[str] = set()
         root = self[target].copy()
         if target in self.visited:
             # short-circuit circular dependencies
@@ -43,4 +55,5 @@
         return root
 
 
-__name__ == '__main__' and main()
+if __name__ == '__main__':
+    main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jaraco_packaging-10.2.3/jaraco/packaging/metadata.py 
new/jaraco_packaging-10.4.0/jaraco/packaging/metadata.py
--- old/jaraco_packaging-10.2.3/jaraco/packaging/metadata.py    2024-08-20 
05:01:28.000000000 +0200
+++ new/jaraco_packaging-10.4.0/jaraco/packaging/metadata.py    2026-02-22 
17:40:06.000000000 +0100
@@ -1,40 +1,63 @@
+from __future__ import annotations
+
 import os
 import re
+from collections.abc import Iterable
+from typing import TYPE_CHECKING
 
 from build import util
 
+if TYPE_CHECKING:
+    from _typeshed import StrPath
+    from importlib_metadata import PackageMetadata
+    from pyproject_hooks import SubprocessRunner
+
 
 def load(
-    source_dir: util.StrPath,
+    source_dir: StrPath,
     isolated: bool = os.environ.get('BUILD_ENVIRONMENT', 'isolated') == 
'isolated',
-    **kwargs,
-):
+    **kwargs: SubprocessRunner,
+) -> PackageMetadata:
     """
     Allow overriding the isolation behavior at the enviroment level.
     """
     return util.project_wheel_metadata(source_dir, isolated, **kwargs)
 
 
-def hunt_down_url(meta):
+def hunt_down_url(meta: PackageMetadata) -> str | None:
     """
     Given project metadata, figure out what the package URL is.
 
     >>> hunt_down_url(load('.'))
     'https://github.com/jaraco/jaraco.packaging'
     """
-    return meta.get('Home-page') or get_best(meta.get_all('Project-URL'))
+    return meta.get('Home-page') or get_best(meta.get_all('Project-URL', ()))
 
 
-def get_best(project_urls):
+def get_best(project_urls: Iterable[str]) -> str | None:
     lookup = dict(url.split(', ') for url in project_urls)
     return lookup.get('Source') or lookup.get('Homepage')
 
 
+def get_source_url(meta: PackageMetadata) -> str | None:
+    """
+    Given project metadata, return the Source URL from Project-URL entries.
+
+    >>> get_source_url(load('.'))
+    'https://github.com/jaraco/jaraco.packaging'
+    >>> import email.message
+    >>> get_source_url(email.message.Message()) is None
+    True
+    """
+    lookup = dict(url.split(', ', 1) for url in meta.get_all('Project-URL', 
()))
+    return lookup.get('Source')
+
+
 combo_re = r'["]?(?P<name>\w[\w\s.]*?)["]?\s+<(?P<email>\w+@[\w.]+)>'
 """The pattern for matching name and email from *-email fields."""
 
 
-def extract_author(meta):
+def extract_author(meta: PackageMetadata) -> str:
     """
     Given project metadata, figure out who the author is.
 
@@ -63,7 +86,7 @@
     )
 
 
-def extract_email(meta):
+def extract_email(meta: PackageMetadata) -> str:
     """
     Given project metadata, figure out the author's email.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/jaraco_packaging-10.2.3/jaraco/packaging/print-metadata.py 
new/jaraco_packaging-10.4.0/jaraco/packaging/print-metadata.py
--- old/jaraco_packaging-10.2.3/jaraco/packaging/print-metadata.py      
2024-08-20 05:01:28.000000000 +0200
+++ new/jaraco_packaging-10.4.0/jaraco/packaging/print-metadata.py      
2026-02-22 17:40:06.000000000 +0100
@@ -1,15 +1,22 @@
+from typing import TYPE_CHECKING, cast
+
 from . import metadata
 
+if TYPE_CHECKING:
+    from importlib_metadata._adapters import Message
+
 
-def main():
+def main() -> None:
     """
     >>> main()
     Metadata-Version: ...
     """
-    md = metadata.load('.')
+    # cast: Default PathDistribution.metadata is a Message
+    md = cast("Message", metadata.load('.'))
     # cannot print(md) due to python/cpython#119650
     for key, value in md.items():
         print(key, value, sep=': ')
 
 
-__name__ == '__main__' and main()
+if __name__ == '__main__':
+    main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jaraco_packaging-10.2.3/jaraco/packaging/sphinx.py 
new/jaraco_packaging-10.4.0/jaraco/packaging/sphinx.py
--- old/jaraco_packaging-10.2.3/jaraco/packaging/sphinx.py      2024-08-20 
05:01:28.000000000 +0200
+++ new/jaraco_packaging-10.4.0/jaraco/packaging/sphinx.py      2026-02-22 
17:40:06.000000000 +0100
@@ -6,23 +6,43 @@
 True
 """
 
+from __future__ import annotations
+
 import os
 import warnings
-from importlib import metadata
-from typing import ClassVar
+from collections.abc import MutableMapping
+from typing import TYPE_CHECKING, ClassVar
 
+import docutils.nodes
 import docutils.statemachine
 import domdf_python_tools.stringlist
+import sphinx.addnodes
+import sphinx.application
+import sphinx.config
 import sphinx.util.docutils
 from docutils.parsers.rst import directives
-
 from jaraco.context import suppress
 
 from . import metadata as jp_metadata
 
+if TYPE_CHECKING:
+    import importlib_metadata as metadata
+else:
+    from importlib import metadata
+
 
-def setup(app):
+def setup(app: sphinx.application.Sphinx) -> dict[str, str | bool]:
+    """
+    >>> class MockApp:
+    ...     def add_config_value(self, *a): pass
+    ...     def connect(self, *a): pass
+    ...     def add_directive(self, *a): pass
+    >>> result = setup(MockApp())
+    >>> result['parallel_read_safe']
+    True
+    """
     app.add_config_value('package_url', '', '')
+    app.add_config_value('source_url', '', '')
     app.connect('config-inited', load_config_from_setup)
     app.connect('config-inited', configure_substitutions)
     app.connect('html-page-context', add_package_url)
@@ -41,12 +61,31 @@
     option_spec = {
         "pypi": directives.flag,
         "home": directives.flag,
+        "releases": directives.flag,
         "caption": directives.unchanged_required,
     }
 
-    def run(self):
+    def run(self) -> list[sphinx.addnodes.only]:
         """
         Create the installation node.
+
+        >>> from unittest.mock import MagicMock
+        >>> directive = object.__new__(SidebarLinksDirective)
+        >>> directive.state = MagicMock()
+        >>> env = directive.state.document.settings.env
+        >>> env.docname = env.config.master_doc = 'index'
+        >>> env.config.source_url = 'https://github.com/foo/bar'
+        >>> directive.options = {'releases': None}
+        >>> directive.content = []
+        >>> directive.content_offset = 0
+        >>> len(directive.run())  # one 'only' node wrapping the toctree
+        1
+        >>> env.config.source_url = ''
+        >>> from docutils.parsers.rst import DirectiveError
+        >>> directive.run()
+        Traceback (most recent call last):
+            ...
+        docutils.parsers.rst.DirectiveError
         """
 
         if self.env.docname != self.env.config.master_doc:
@@ -67,6 +106,13 @@
                 body.append(
                     f"PyPI 
<https://pypi.org/project/{self.env.config.project}>"
                 )
+            if "releases" in self.options:
+                source_url = self.env.config.source_url
+                if not source_url:
+                    raise self.error(
+                        "releases link requires a Source URL in project 
metadata"
+                    )
+                body.append(f"Releases <{source_url}/releases>")
 
             body.extend(self.content)
 
@@ -84,7 +130,7 @@
 
 
 @suppress(KeyError)
-def _load_metadata_from_wheel():
+def _load_metadata_from_wheel() -> metadata.PackageMetadata:
     """
     If indicated by an environment variable, expect the metadata
     to be present in a wheel and load it from there, avoiding
@@ -103,12 +149,24 @@
         DeprecationWarning,
     )
     (dist,) = metadata.distributions(path=[wheel])
+    assert dist.metadata is not None
     return dist.metadata
 
 
-def load_config_from_setup(app, config):
+def load_config_from_setup(
+    app: sphinx.application.Sphinx, config: sphinx.config.Config
+) -> None:
     """
     Replace values in app.config from package metadata
+
+    >>> class MockConfig:
+    ...     pass
+    >>> class MockApp:
+    ...     confdir = 'docs'
+    >>> config = MockConfig()
+    >>> load_config_from_setup(MockApp(), config)
+    >>> config.source_url
+    'https://github.com/jaraco/jaraco.packaging'
     """
     # for now, assume project root is one level up
     root = os.path.join(app.confdir, '..')
@@ -116,13 +174,20 @@
     config.project = meta['Name']
     config.version = config.release = meta['Version']
     config.package_url = jp_metadata.hunt_down_url(meta)
+    config.source_url = jp_metadata.get_source_url(meta)
     config.author = config.copyright = jp_metadata.extract_author(meta)
 
 
-def configure_substitutions(app, config):
+def configure_substitutions(app: object, config: sphinx.config.Config) -> None:
     epilogs = config.rst_epilog, f'.. |project| replace:: {config.project}'
     config.rst_epilog = '\n'.join(filter(None, epilogs))
 
 
-def add_package_url(app, pagename, templatename, context, doctree):
+def add_package_url(
+    app: sphinx.application.Sphinx,
+    pagename: object,
+    templatename: object,
+    context: MutableMapping[str, str],
+    doctree: object,
+) -> None:
     context['package_url'] = app.config.package_url
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/jaraco_packaging-10.2.3/jaraco.packaging.egg-info/PKG-INFO 
new/jaraco_packaging-10.4.0/jaraco.packaging.egg-info/PKG-INFO
--- old/jaraco_packaging-10.2.3/jaraco.packaging.egg-info/PKG-INFO      
2024-08-20 05:01:48.000000000 +0200
+++ new/jaraco_packaging-10.4.0/jaraco.packaging.egg-info/PKG-INFO      
2026-02-22 17:40:27.000000000 +0100
@@ -1,16 +1,16 @@
-Metadata-Version: 2.1
+Metadata-Version: 2.4
 Name: jaraco.packaging
-Version: 10.2.3
+Version: 10.4.0
 Summary: tools to supplement packaging Python releases
 Author-email: "Jason R. Coombs" <[email protected]>
+License-Expression: MIT
 Project-URL: Source, https://github.com/jaraco/jaraco.packaging
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: MIT License
 Classifier: Programming Language :: Python :: 3
 Classifier: Programming Language :: Python :: 3 :: Only
 Classifier: Framework :: Sphinx :: Extension
-Requires-Python: >=3.8
+Requires-Python: >=3.9
 Description-Content-Type: text/x-rst
 License-File: LICENSE
 Requires-Dist: build[virtualenv]
@@ -19,11 +19,6 @@
 Requires-Dist: domdf-python-tools
 Provides-Extra: test
 Requires-Dist: pytest!=8.1.*,>=6; extra == "test"
-Requires-Dist: pytest-checkdocs>=2.4; extra == "test"
-Requires-Dist: pytest-cov; extra == "test"
-Requires-Dist: pytest-mypy; extra == "test"
-Requires-Dist: pytest-enabler>=2.2; extra == "test"
-Requires-Dist: pytest-ruff>=0.2.1; sys_platform != "cygwin" and extra == "test"
 Requires-Dist: types-docutils; extra == "test"
 Provides-Extra: doc
 Requires-Dist: sphinx>=3.5; extra == "doc"
@@ -31,6 +26,18 @@
 Requires-Dist: rst.linker>=1.9; extra == "doc"
 Requires-Dist: furo; extra == "doc"
 Requires-Dist: sphinx-lint; extra == "doc"
+Provides-Extra: check
+Requires-Dist: pytest-checkdocs>=2.4; extra == "check"
+Requires-Dist: pytest-ruff>=0.2.1; sys_platform != "cygwin" and extra == 
"check"
+Provides-Extra: cover
+Requires-Dist: pytest-cov; extra == "cover"
+Provides-Extra: enabler
+Requires-Dist: pytest-enabler>=3.4; extra == "enabler"
+Provides-Extra: type
+Requires-Dist: pytest-mypy>=1.0.1; extra == "type"
+Requires-Dist: mypy<1.19; platform_python_implementation == "PyPy" and extra 
== "type"
+Requires-Dist: importlib_metadata; extra == "type"
+Dynamic: license-file
 
 .. image:: https://img.shields.io/pypi/v/jaraco.packaging.svg
    :target: https://pypi.org/project/jaraco.packaging
@@ -41,14 +48,14 @@
    :target: 
https://github.com/jaraco/jaraco.packaging/actions?query=workflow%3A%22tests%22
    :alt: tests
 
-.. image:: 
https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json
+.. image:: 
https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
     :target: https://github.com/astral-sh/ruff
     :alt: Ruff
 
 .. image:: 
https://readthedocs.org/projects/jaracopackaging/badge/?version=latest
    :target: https://jaracopackaging.readthedocs.io/en/latest/?badge=latest
 
-.. image:: https://img.shields.io/badge/skeleton-2024-informational
+.. image:: https://img.shields.io/badge/skeleton-2025-informational
    :target: https://blog.jaraco.com/skeleton
 
 Tools for packaging.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/jaraco_packaging-10.2.3/jaraco.packaging.egg-info/SOURCES.txt 
new/jaraco_packaging-10.4.0/jaraco.packaging.egg-info/SOURCES.txt
--- old/jaraco_packaging-10.2.3/jaraco.packaging.egg-info/SOURCES.txt   
2024-08-20 05:01:48.000000000 +0200
+++ new/jaraco_packaging-10.4.0/jaraco.packaging.egg-info/SOURCES.txt   
2026-02-22 17:40:27.000000000 +0100
@@ -12,7 +12,6 @@
 ruff.toml
 towncrier.toml
 tox.ini
-.github/dependabot.yml
 .github/workflows/main.yml
 docs/conf.py
 docs/history.rst
@@ -26,4 +25,5 @@
 jaraco/packaging/make-tree.py
 jaraco/packaging/metadata.py
 jaraco/packaging/print-metadata.py
+jaraco/packaging/py.typed
 jaraco/packaging/sphinx.py
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/jaraco_packaging-10.2.3/jaraco.packaging.egg-info/requires.txt 
new/jaraco_packaging-10.4.0/jaraco.packaging.egg-info/requires.txt
--- old/jaraco_packaging-10.2.3/jaraco.packaging.egg-info/requires.txt  
2024-08-20 05:01:48.000000000 +0200
+++ new/jaraco_packaging-10.4.0/jaraco.packaging.egg-info/requires.txt  
2026-02-22 17:40:27.000000000 +0100
@@ -3,6 +3,15 @@
 sphinx
 domdf-python-tools
 
+[check]
+pytest-checkdocs>=2.4
+
+[check:sys_platform != "cygwin"]
+pytest-ruff>=0.2.1
+
+[cover]
+pytest-cov
+
 [doc]
 sphinx>=3.5
 jaraco.packaging>=9.3
@@ -10,13 +19,16 @@
 furo
 sphinx-lint
 
+[enabler]
+pytest-enabler>=3.4
+
 [test]
 pytest!=8.1.*,>=6
-pytest-checkdocs>=2.4
-pytest-cov
-pytest-mypy
-pytest-enabler>=2.2
 types-docutils
 
-[test:sys_platform != "cygwin"]
-pytest-ruff>=0.2.1
+[type]
+pytest-mypy>=1.0.1
+importlib_metadata
+
+[type:platform_python_implementation == "PyPy"]
+mypy<1.19
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jaraco_packaging-10.2.3/mypy.ini 
new/jaraco_packaging-10.4.0/mypy.ini
--- old/jaraco_packaging-10.2.3/mypy.ini        2024-08-20 05:01:28.000000000 
+0200
+++ new/jaraco_packaging-10.4.0/mypy.ini        2026-02-22 17:40:06.000000000 
+0100
@@ -1,5 +1,15 @@
 [mypy]
-ignore_missing_imports = True
-# required to support namespace packages
-# https://github.com/python/mypy/issues/14057
+# Is the project well-typed?
+strict = True
+
+# Early opt-in even when strict = False
+warn_unused_ignores = True
+warn_redundant_casts = True
+enable_error_code = ignore-without-code
+
+# Support namespace packages per https://github.com/python/mypy/issues/14057
 explicit_package_bases = True
+
+disable_error_code =
+       # Disable due to many false positives
+       overload-overlap,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jaraco_packaging-10.2.3/pyproject.toml 
new/jaraco_packaging-10.4.0/pyproject.toml
--- old/jaraco_packaging-10.2.3/pyproject.toml  2024-08-20 05:01:28.000000000 
+0200
+++ new/jaraco_packaging-10.4.0/pyproject.toml  2026-02-22 17:40:06.000000000 
+0100
@@ -1,5 +1,10 @@
 [build-system]
-requires = ["setuptools>=61.2", "setuptools_scm[toml]>=3.4.1"]
+requires = [
+       "setuptools>=77",
+       "setuptools_scm[toml]>=3.4.1",
+       # jaraco/skeleton#174
+       "coherent.licensed",
+]
 build-backend = "setuptools.build_meta"
 
 [project]
@@ -12,12 +17,12 @@
 classifiers = [
        "Development Status :: 5 - Production/Stable",
        "Intended Audience :: Developers",
-       "License :: OSI Approved :: MIT License",
        "Programming Language :: Python :: 3",
        "Programming Language :: Python :: 3 :: Only",
        "Framework :: Sphinx :: Extension",
 ]
-requires-python = ">=3.8"
+requires-python = ">=3.9"
+license = "MIT"
 dependencies = [
        # virtualenv extra due to pypa/build#266
        "build[virtualenv]",
@@ -34,15 +39,11 @@
 test = [
        # upstream
        "pytest >= 6, != 8.1.*",
-       "pytest-checkdocs >= 2.4",
-       "pytest-cov",
-       "pytest-mypy",
-       "pytest-enabler >= 2.2",
-       "pytest-ruff >= 0.2.1; sys_platform != 'cygwin'",
 
        # local
        "types-docutils",
 ]
+
 doc = [
        # upstream
        "sphinx >= 3.5",
@@ -54,4 +55,30 @@
        # local
 ]
 
+check = [
+       "pytest-checkdocs >= 2.4",
+       "pytest-ruff >= 0.2.1; sys_platform != 'cygwin'",
+]
+
+cover = [
+       "pytest-cov",
+]
+
+enabler = [
+       "pytest-enabler >= 3.4",
+]
+
+type = [
+       # upstream
+       "pytest-mypy >= 1.0.1",
+
+       ## workaround for python/mypy#20454
+       "mypy < 1.19; python_implementation == 'PyPy'",
+
+       # local
+       # PackageMetadata Protocol doesn't have `get` method until Python 3.12
+       # But this is a type-checking only issue.
+       "importlib_metadata",
+]
+
 [tool.setuptools_scm]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jaraco_packaging-10.2.3/ruff.toml 
new/jaraco_packaging-10.4.0/ruff.toml
--- old/jaraco_packaging-10.2.3/ruff.toml       2024-08-20 05:01:28.000000000 
+0200
+++ new/jaraco_packaging-10.4.0/ruff.toml       2026-02-22 17:40:06.000000000 
+0100
@@ -1,10 +1,31 @@
 [lint]
 extend-select = [
-       "C901",
-       "PERF401",
-       "W",
+       # upstream
+
+       "C901", # complex-structure
+       "I", # isort
+       "PERF401", # manual-list-comprehension
+
+       # Ensure modern type annotation syntax and best practices
+       # Not including those covered by type-checkers or exclusive to Python 
3.11+
+       "FA", # flake8-future-annotations
+       "F404", # late-future-import
+       "PYI", # flake8-pyi
+       "UP006", # non-pep585-annotation
+       "UP007", # non-pep604-annotation
+       "UP010", # unnecessary-future-import
+       "UP035", # deprecated-import
+       "UP037", # quoted-annotation
+       "UP043", # unnecessary-default-type-args
+
+       # local
 ]
 ignore = [
+       # upstream
+
+       # Typeshed rejects complex or non-literal defaults for maintenance and 
testing reasons,
+       # irrelevant to this project.
+       "PYI011", # typed-argument-default-in-stub
        # https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules
        "W191",
        "E111",
@@ -18,8 +39,8 @@
        "Q003",
        "COM812",
        "COM819",
-       "ISC001",
-       "ISC002",
+
+       # local
 ]
 
 [format]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jaraco_packaging-10.2.3/towncrier.toml 
new/jaraco_packaging-10.4.0/towncrier.toml
--- old/jaraco_packaging-10.2.3/towncrier.toml  2024-08-20 05:01:28.000000000 
+0200
+++ new/jaraco_packaging-10.4.0/towncrier.toml  2026-02-22 17:40:06.000000000 
+0100
@@ -1,2 +1,3 @@
 [tool.towncrier]
 title_format = "{version}"
+directory = "newsfragments"  # jaraco/skeleton#184
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jaraco_packaging-10.2.3/tox.ini 
new/jaraco_packaging-10.4.0/tox.ini
--- old/jaraco_packaging-10.2.3/tox.ini 2024-08-20 05:01:28.000000000 +0200
+++ new/jaraco_packaging-10.4.0/tox.ini 2026-02-22 17:40:06.000000000 +0100
@@ -8,6 +8,10 @@
 usedevelop = True
 extras =
        test
+       check
+       cover
+       enabler
+       type
 
 [testenv:diffcov]
 description = run tests and check that diff from main is covered
@@ -27,9 +31,7 @@
 changedir = docs
 commands =
        python -m sphinx -W --keep-going . {toxinidir}/build/html
-       python -m sphinxlint \
-               # workaround for sphinx-contrib/sphinx-lint#83
-               --jobs 1
+       python -m sphinxlint
 
 [testenv:finalize]
 description = assemble changelog and tag a release

Reply via email to