diff --git a/doc/array.rst b/doc/array.rst
index 3677554263eeb6182ada04958baffd1f3bf9a568..a22ab5f6cd226d149a06da96aff0344809e2eb9a 100644
--- a/doc/array.rst
+++ b/doc/array.rst
@@ -101,7 +101,7 @@ functions defined on them such as `cfloat_mul(a, b)` or `cdouble_log(z)`.
 Elementwise kernels automatically include the header if your kernel has
 complex input or output.
 See the `source file
-<https://github.com/inducer/pyopencl/blob/main/pyopencl/cl/pyopencl-complex.h>`_
+<https://github.com/inducer/pyopencl/blob/main/pyopencl/cl/pyopencl-complex.h>`__
 for a precise list of what's available.
 
 If you need double precision support, please::
diff --git a/doc/howto.rst b/doc/howto.rst
index 5c5b04d22b7179847a459fe36a4299920247b0f5..4437073d30b11e0d81d3e3a9c0c8d6a0648716f9 100644
--- a/doc/howto.rst
+++ b/doc/howto.rst
@@ -34,7 +34,7 @@ lines:
 
 Since OpenCL C may have a different opinion for :mod:`numpy` on how the struct
 should be laid out, for example because of `alignment
-<https://en.wikipedia.org/wiki/Data_structure_alignment>`_. So as a first step, we
+<https://en.wikipedia.org/wiki/Data_structure_alignment>`__. So as a first step, we
 match our dtype against CL's version:
 
 .. doctest::
diff --git a/doc/index.rst b/doc/index.rst
index 7771105a6e5976604e0499e49182bccfd92238c9..873d1f0443c28fe5b4a81e1a2abde07ea677f6a7 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -54,7 +54,7 @@ Tutorials
   `4 <https://www.youtube.com/watch?v=SsuJ0LvZW1Q>`__
   (YouTube, 2011)
 * PyOpenCL course at `DTU GPULab <http://gpulab.compute.dtu.dk/>`__ and
-  `Simula <https://www.simula.no/>`_ (2011):
+  `Simula <https://www.simula.no/>`__ (2011):
   `Lecture 1 <https://tiker.net/pub/simula-pyopencl-lec1.pdf>`__
   `Lecture 2 <https://tiker.net/pub/simula-pyopencl-lec2.pdf>`__
   `Problem set 1 <https://tiker.net/pub/simula-pyopencl-probset1.pdf>`__
diff --git a/doc/runtime_memory.rst b/doc/runtime_memory.rst
index f9c31a8bff21c056a8743b5c76aa4d4aca67de59..c13480ff5b49beb551e0e6dfe63220b9d585f598 100644
--- a/doc/runtime_memory.rst
+++ b/doc/runtime_memory.rst
@@ -58,7 +58,7 @@ Buffer
     .. note::
 
         Python also defines a type of `buffer object
-        <https://docs.python.org/3.4/c-api/buffer.html>`_,
+        <https://docs.python.org/3/c-api/buffer.html>`__,
         and PyOpenCL interacts with those, too, as the host-side
         target of :func:`enqueue_copy`. Make sure to always be
         clear on whether a :class:`Buffer` or a Python buffer
diff --git a/doc/runtime_platform.rst b/doc/runtime_platform.rst
index f720df273c6d381b0cc67601266f353ac2044fee..aeee8c56460cd505ba0665a0760a395de3c4a2ef 100644
--- a/doc/runtime_platform.rst
+++ b/doc/runtime_platform.rst
@@ -127,7 +127,7 @@ Context
         just-give-me-a-context-already behavior, we recommend
         :func:`create_some_context`. See, e.g. this
         `explanation by AMD
-        <https://web.archive.org/web/20101114195033/https://developer.amd.com/support/KnowledgeBase/Lists/KnowledgeBase/DispForm.aspx?ID=71>`_.
+        <https://web.archive.org/web/20101114195033/https://developer.amd.com/support/KnowledgeBase/Lists/KnowledgeBase/DispForm.aspx?ID=71>`__.
 
     .. note::
 
diff --git a/doc/runtime_program.rst b/doc/runtime_program.rst
index 4e90bd1285ba8fe2520089e35fe4c635c67fe4dc..91a68966acf45d0b5e1ca01090b9224636726c82 100644
--- a/doc/runtime_program.rst
+++ b/doc/runtime_program.rst
@@ -39,7 +39,7 @@ Program
 
     *binaries* must contain one binary for each entry in *devices*.
     If *src* is a :class:`bytes` object starting with a valid `SPIR-V
-    <https://www.khronos.org/spir>`_ magic number, it will be handed
+    <https://www.khronos.org/spir>`__ magic number, it will be handed
     off to the OpenCL implementation as such, rather than as OpenCL C source
     code. (SPIR-V support requires OpenCL 2.1.)
 
@@ -273,7 +273,7 @@ Kernel
 
             A solution involving implicit locks was discussed and decided against on the
             mailing list in `October 2012
-            <https://lists.tiker.net/pipermail/pyopencl/2012-October/001311.html>`_.
+            <https://lists.tiker.net/pipermail/pyopencl/2012-October/001311.html>`__.
 
         .. versionchanged:: 0.92
 
diff --git a/pyopencl/__init__.py b/pyopencl/__init__.py
index ce436be82b59d52232e893b279df3584352fdcfe..a95cb1b6a2ae95d4c29f39b26e370a5a63586146 100644
--- a/pyopencl/__init__.py
+++ b/pyopencl/__init__.py
@@ -1767,7 +1767,7 @@ def enqueue_copy(queue, dest, src, **kwargs):
         Two types of 'buffer' occur in the arguments to this function,
         :class:`Buffer` and 'host-side buffers'. The latter are
         defined by Python and commonly called `buffer objects
-        <https://docs.python.org/3.4/c-api/buffer.html>`_. :mod:`numpy`
+        <https://docs.python.org/3/c-api/buffer.html>`__. :mod:`numpy`
         arrays are a very common example.
         Make sure to always be clear on whether a :class:`Buffer` or a
         Python buffer object is needed.
diff --git a/pyopencl/algorithm.py b/pyopencl/algorithm.py
index 2dadf0ae59167ccf888a5872e77153ce0e98f3b1..a76b0ff71df12361d43f4750fbdd6b0c34f95995 100644
--- a/pyopencl/algorithm.py
+++ b/pyopencl/algorithm.py
@@ -426,7 +426,7 @@ RADIX_SORT_OUTPUT_STMT_TPL = Template(r"""//CL//
 # {{{ driver
 
 class RadixSort:
-    """Provides a general `radix sort <https://en.wikipedia.org/wiki/Radix_sort>`_
+    """Provides a general `radix sort <https://en.wikipedia.org/wiki/Radix_sort>`__
     on the compute device.
 
     .. seealso:: :class:`pyopencl.bitonic_sort.BitonicSort`
diff --git a/pyopencl/characterize/__init__.py b/pyopencl/characterize/__init__.py
index 091175c4974ae57b5bcbb7858843bb04a7adf0f8..3f12970abd549276b96ecba9d91c2369cbe70313 100644
--- a/pyopencl/characterize/__init__.py
+++ b/pyopencl/characterize/__init__.py
@@ -376,7 +376,7 @@ def _check_for_pocl_arg_count_bug(
 
 def has_struct_arg_count_bug(dev, ctx=None):
     """Checks whether the device is expected to have the
-    `argument counting bug <https://github.com/pocl/pocl/issues/197>`_.
+    `argument counting bug <https://github.com/pocl/pocl/issues/197>`__.
     """
 
     if dev.platform.name == "Apple" and dev.type & cl.device_type.CPU:
diff --git a/pyopencl/clrandom.py b/pyopencl/clrandom.py
index 5654b2b5ef3694817d4ee860126d28b48198f6ae..d9ca92ac1eef66fa1c067a7f4bd776ee4252056f 100644
--- a/pyopencl/clrandom.py
+++ b/pyopencl/clrandom.py
@@ -33,9 +33,9 @@ they are available in any piece of code compiled through PyOpenCL by::
     #include <pyopencl-random123/threefry.cl>
 
 See the `Philox source
-<https://github.com/inducer/pyopencl/blob/main/pyopencl/cl/pyopencl-random123/philox.cl>`_
+<https://github.com/inducer/pyopencl/blob/main/pyopencl/cl/pyopencl-random123/philox.cl>`__
 and the `Threefry source
-<https://github.com/inducer/pyopencl/blob/main/pyopencl/cl/pyopencl-random123/threefry.cl>`_
+<https://github.com/inducer/pyopencl/blob/main/pyopencl/cl/pyopencl-random123/threefry.cl>`__
 for some documentation if you're planning on using Random123 directly.
 
 .. note::