Repository: sloria/sphinx-issues

Issue:
support role `:pypi:`
I tried sphinx-issues in the pip https://github.com/pypa/pip/pull/12616, it would be nice to support for the role `:pypi:`.

```
:pypi:`pre-commit` 

would become:

https://pypi.org/project/pre-commit
```

Hints from issue comments:

Solution patch:
diff --git a/README.rst b/README.rst
index 4313bb9..6548075 100644
--- a/README.rst
+++ b/README.rst
@@ -135,6 +135,12 @@ Use the ``:cwe:`` role to link to CWEs on https://cwe.mitre.org.
 
     :cwe:`CWE-787` - The software writes data past the end, or...
 
+Use the ``:pypi:`` role to link to PyPI on https://pypi.org.
+
+.. code-block:: rst
+
+    :pypi:`sphinx-issues` - A Sphinx extension for linking to your project's issue tracker.
+
 Credits
 *******
 
@@ -149,6 +155,12 @@ MIT licensed. See the bundled `LICENSE <https://github.com/sloria/sphinx-issues/
 Changelog
 *********
 
+4.1.0 (unreleased)
+------------------
+
+- Add `:pypi:` role for linking to PyPI projects (`#144 <https://github.com/sloria/sphinx-issues/issues/144>`_).
+  Thanks @shenxianpeng for the suggestion and PR.
+
 4.0.0 (2024-01-19)
 ------------------
 
diff --git a/src/sphinx_issues/__init__.py b/src/sphinx_issues/__init__.py
index c5a8328..748120c 100644
--- a/src/sphinx_issues/__init__.py
+++ b/src/sphinx_issues/__init__.py
@@ -186,6 +186,26 @@ def cwe_role(name, rawtext, text, lineno, inliner, options=None, content=None):
     return [link], []
 
 
+def pypi_role(name, rawtext, text, lineno, inliner, options=None, content=None):
+    """Sphinx role for linking to a PyPI on https://pypi.org/.
+
+    Examples: ::
+
+        :pypi:`sphinx-issues`
+
+    """
+    options = options or {}
+    content = content or []
+    has_explicit_title, title, target = split_explicit_title(text)
+
+    target = utils.unescape(target).strip()
+    title = utils.unescape(title).strip()
+    ref = f"https://pypi.org/project/{target}"
+    text = title if has_explicit_title else target
+    link = nodes.reference(text=text, refuri=ref, **options)
+    return [link], []
+
+
 class IssueRole:
     # Symbols used to separate and issue/pull request/merge request etc
     # i.e
@@ -384,6 +404,7 @@ def setup(app):
     app.add_role("commit", commit_role)
     app.add_role("cve", cve_role)
     app.add_role("cwe", cwe_role)
+    app.add_role("pypi", pypi_role)
     return {
         "version": importlib.metadata.version("sphinx-issues"),
         "parallel_read_safe": True,


Test patch:
diff --git a/tests/test_sphinx_issues.py b/tests/test_sphinx_issues.py
index 84b9f52..b2fa3e8 100644
--- a/tests/test_sphinx_issues.py
+++ b/tests/test_sphinx_issues.py
@@ -14,6 +14,7 @@ from sphinx_issues import (
     cwe_role,
     issue_role,
     pr_role,
+    pypi_role,
     user_role,
 )
 from sphinx_issues import setup as issues_setup
@@ -108,6 +109,13 @@ def inliner(app):
             "CWE-787",
             "https://cwe.mitre.org/data/definitions/787.html",
         ),
+        (
+            pypi_role,
+            "pypi",
+            "sphinx-issues",
+            "sphinx-issues",
+            "https://pypi.org/project/sphinx-issues",
+        ),
         (
             commit_role,
             "commit",