//  [python]
def _compare_source_spaces(src0, src1, mode="exact", nearest=True, dist_tol=1.5e-3):
    """Compare two source spaces.

    Note: this function is also used by forward/tests/test_make_forward.py
    """
    from numpy.testing import (
        assert_,
        assert_allclose,
        assert_array_equal,
        assert_array_less,
        assert_equal,
    )

    if mode != "exact" and "approx" not in mode:  # 'nointerp' can be appended
        raise RuntimeError(f"unknown mode {mode}")

    for si, (s0, s1) in enumerate(zip(src0, src1)):
        # first check the keys
        a, b = set(s0.keys()), set(s1.keys())
        assert_equal(a, b, str(a ^ b))
        for name in ["nuse", "ntri", "np", "type", "id"]:
            a, b = s0[name], s1[name]
            if name == "id":  # workaround for old NumPy bug
                a, b = int(a), int(b)
            assert_equal(a, b, name)
        for name in ["subject_his_id"]:
            if name in s0 or name in s1:
                assert_equal(s0[name], s1[name], name)
        for name in ["interpolator"]:
            if name in s0 or name in s1:
                assert name in s0, f"{name} in s1 but not s0"
                assert name in s1, f"{name} in s1 but not s0"
                n = np.prod(s0["interpolator"].shape)
                diffs = (s0["interpolator"] - s1["interpolator"]).data
                if len(diffs) > 0 and "nointerp" not in mode:
                    # 0.1%
                    assert_array_less(
                        np.sqrt(np.sum(diffs * diffs) / n),
                        0.001,
                        err_msg=f"{name} > 0.1%",
                    )
        for name in ["nn", "rr", "nuse_tri", "coord_frame", "tris"]:
            if s0[name] is None:
                assert_(s1[name] is None, name)
            else:
                if mode == "exact":
                    assert_array_equal(s0[name], s1[name], name)
                else:  # 'approx' in mode
                    atol = 1e-3 if name == "nn" else 1e-4
                    assert_allclose(
                        s0[name], s1[name], rtol=1e-3, atol=atol, err_msg=name
                    )
        for name in ["seg_name"]:
            if name in s0 or name in s1:
                assert_equal(s0[name], s1[name], name)
        # these fields will exist if patch info was added
        if nearest:
            for name in ["nearest", "nearest_dist", "patch_inds"]:
                if s0[name] is None:
                    assert_(s1[name] is None, name)
                else:
                    atol = 0 if mode == "exact" else 1e-6
                    assert_allclose(s0[name], s1[name], atol=atol, err_msg=name)
            for name in ["pinfo"]:
                if s0[name] is None:
                    assert_(s1[name] is None, name)
                else:
                    assert_(len(s0[name]) == len(s1[name]), name)
                    for p1, p2 in zip(s0[name], s1[name]):
                        assert_(all(p1 == p2), name)
        if mode == "exact":
            for name in ["inuse", "vertno", "use_tris"]:
                assert_array_equal(s0[name], s1[name], err_msg=name)
            for name in ["dist_limit"]:
                assert_(s0[name] == s1[name], name)
            for name in ["dist"]:
                if s0[name] is not None:
                    assert_equal(s1[name].shape, s0[name].shape)
                    assert_(len((s0["dist"] - s1["dist"]).data) == 0)
        else:  # 'approx' in mode:
            # deal with vertno, inuse, and use_tris carefully
            for ii, s in enumerate((s0, s1)):
                assert_array_equal(
                    s["vertno"],
                    np.where(s["inuse"])[0],
                    f'src{ii}[{si}]["vertno"] != '
                    f'np.where(src{ii}[{si}]["inuse"])[0]',
                )
            assert_equal(len(s0["vertno"]), len(s1["vertno"]))
            agreement = np.mean(s0["inuse"] == s1["inuse"])
            assert_(agreement >= 0.99, f"{agreement} < 0.99")
            if agreement < 1.0:
                # make sure mismatched vertno are within 1.5mm
                v0 = np.setdiff1d(s0["vertno"], s1["vertno"])
                v1 = np.setdiff1d(s1["vertno"], s0["vertno"])
                dists = cdist(s0["rr"][v0], s1["rr"][v1])
                assert_allclose(
                    np.min(dists, axis=1),
                    np.zeros(len(v0)),
                    atol=dist_tol,
                    err_msg="mismatched vertno",
                )
            if s0["use_tris"] is not None:  # for "spacing"
                assert_array_equal(s0["use_tris"].shape, s1["use_tris"].shape)
            else:
                assert_(s1["use_tris"] is None)
            assert_(np.mean(s0["use_tris"] == s1["use_tris"]) > 0.99)
    # The above "if s0[name] is not None" can be removed once the sample
    # dataset is updated to have a source space with distance info
    for name in ["working_dir", "command_line"]:
        if mode == "exact":
            assert_equal(src0.info[name], src1.info[name])
        else:  # 'approx' in mode:
            if name in src0.info:
                assert_(name in src1.info, f'"{name}" missing')
            else:
                assert_(name not in src1.info, f'"{name}" should not exist')