# Buggy code
def radius_neighbors(self, X=None, radius=None, return_distance=True):
    """Finds the neighbors within a given radius of a point or points.

    Return the indices and distances of each point from the dataset
    lying in a ball with size ``radius`` around the points of the query
    array. Points lying on the boundary are included in the results.

    The result points are *not* necessarily sorted by distance to their
    query point.

    Parameters
    ----------
    X : array-like, (n_samples, n_features), optional
        The query point or points.
        If not provided, neighbors of each indexed point are returned.
        In this case, the query point is not considered its own neighbor.

    radius : float
        Limiting distance of neighbors to return.
        (default is the value passed to the constructor).

    return_distance : boolean, optional. Defaults to True.
        If False, distances will not be returned

    Returns
    -------
    dist : array, shape (n_samples,) of arrays
        Array representing the distances to each point, only present if
        return_distance=True. The distance values are computed according
        to the ``metric`` constructor parameter.

    ind : array, shape (n_samples,) of arrays
        An array of arrays of indices of the approximate nearest points
        from the population matrix that lie within a ball of size
        ``radius`` around the query points.

    Examples
    --------
    In the following example, we construct a NeighborsClassifier
    class from an array representing our data set and ask who's
    the closest point to [1, 1, 1]:

    >>> import numpy as np
    >>> samples = [[0., 0., 0.], [0., .5, 0.], [1., 1., .5]]
    >>> from sklearn.neighbors import NearestNeighbors
    >>> neigh = NearestNeighbors(radius=1.6)
    >>> neigh.fit(samples) # doctest: +ELLIPSIS
    NearestNeighbors(algorithm='auto', leaf_size=30, ...)
    >>> rng = neigh.radius_neighbors([[1., 1., 1.]])
    >>> print(np.asarray(rng[0][0])) # doctest: +ELLIPSIS
    [1.5 0.5]
    >>> print(np.asarray(rng[1][0])) # doctest: +ELLIPSIS
    [1 2]

    The first array returned contains the distances to all points which
    are closer than 1.6, while the second array returned contains their
    indices.  In general, multiple points can be queried at the same time.

    Notes
    -----
    Because the number of neighbors of each point is not necessarily
    equal, the results for multiple query points cannot be fit in a
    standard data array.
    For efficiency, `radius_neighbors` returns arrays of objects, where
    each object is a 1D array of indices or distances.
    """
    check_is_fitted(self, ["_fit_method", "_fit_X"], all_or_any=any)

    if X is not None:
        query_is_train = False
        X = check_array(X, accept_sparse="csr")
    else:
        query_is_train = True
        X = self._fit_X

    if radius is None:
        radius = self.radius

    if self._fit_method == "brute":
        # for efficiency, use squared euclidean distances
        if self.effective_metric_ == "euclidean":
            radius *= radius
            kwds = {"squared": True}
        else:
            kwds = self.effective_metric_params_

        reduce_func = partial(
            self._radius_neighbors_reduce_func,
            radius=radius,
            return_distance=return_distance,
        )

        results = pairwise_distances_chunked(
            X,
            self._fit_X,
            reduce_func=reduce_func,
            metric=self.effective_metric_,
            n_jobs=self.n_jobs,
            **kwds,
        )
        if return_distance:
            dist_chunks, neigh_ind_chunks = zip(*results)
            dist_list = sum(dist_chunks, [])
            neigh_ind_list = sum(neigh_ind_chunks, [])
            # See https://github.com/numpy/numpy/issues/5456
            # if you want to understand why this is initialized this way.
            dist = np.empty(len(dist_list), dtype="object")
            dist[:] = dist_list
            neigh_ind = np.empty(len(neigh_ind_list), dtype="object")
            neigh_ind[:] = neigh_ind_list
            results = dist, neigh_ind
        else:
            neigh_ind_list = sum(results, [])
            results = np.empty(len(neigh_ind_list), dtype="object")
            results[:] = neigh_ind_list

    elif self._fit_method in ["ball_tree", "kd_tree"]:
        if issparse(X):
            raise ValueError(
                "%s does not work with sparse matrices. Densify the data, "
                "or set algorithm='brute'" % self._fit_method
            )

        n_jobs = effective_n_jobs(self.n_jobs)
        if LooseVersion(joblib_version) < LooseVersion("0.12"):
            # Deal with change of API in joblib
            delayed_query = delayed(self._tree.query_radius, check_pickle=False)
            parallel_kwargs = {"backend": "threading"}
        else:
            delayed_query = delayed(self._tree.query_radius)
            parallel_kwargs = {"prefer": "threads"}
        results = Parallel(n_jobs, **parallel_kwargs)(
            delayed_query(X[s], radius, return_distance)
            for s in gen_even_slices(X.shape[0], n_jobs)
        )
        if return_distance:
            neigh_ind, dist = tuple(zip(*results))
            results = np.hstack(dist), np.hstack(neigh_ind)
        else:
            results = np.hstack(results)
    else:
        raise ValueError("internal: _fit_method not recognized")

    if not query_is_train:
        return results
    else:
        # If the query data is the same as the indexed data, we would like
        # to ignore the first nearest neighbor of every sample, i.e
        # the sample itself.
        if return_distance:
            dist, neigh_ind = results
        else:
            neigh_ind = results

        for ind, ind_neighbor in enumerate(neigh_ind):
            mask = ind_neighbor != ind

            neigh_ind[ind] = ind_neighbor[mask]
            if return_distance:
                dist[ind] = dist[ind][mask]

        if return_distance:
            return dist, neigh_ind
        return neigh_ind


# Traceback (TypeError)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-36-9fc0a20fa010> in <module>
----> 1 pickle.loads(cloudpickle.dumps(knn._tree.query))

~/pypy3-v6.0.0-linux64/lib-python/3/pickle.py in _loads(s, fix_imports, encoding, errors)
1585     file = io.BytesIO(s)
1586     return _Unpickler(file, fix_imports=fix_imports,
-> 1587                       encoding=encoding, errors=errors).load()
1588
1589 # Use the faster _pickle if possible

~/pypy3-v6.0.0-linux64/lib-python/3/pickle.py in load(self)
1061                     raise EOFError
1062                 assert isinstance(key, bytes_types)
-> 1063                 dispatch[key[0]](self)
1064         except _Stop as stopinst:
1065             return stopinst.value

~/pypy3-v6.0.0-linux64/lib-python/3/pickle.py in load_newobj(self)
1345         args = self.stack.pop()
1346         cls = self.stack.pop()
-> 1347         obj = cls.__new__(cls, *args)
1348         self.append(obj)
1349     dispatch[NEWOBJ[0]] = load_newobj

TypeError: object.__new__(getset_descriptor) is not safe, use getset_descriptor.__new__()

# Fixed code
def radius_neighbors(self, X=None, radius=None, return_distance=True):
    """Finds the neighbors within a given radius of a point or points.

    Return the indices and distances of each point from the dataset
    lying in a ball with size ``radius`` around the points of the query
    array. Points lying on the boundary are included in the results.

    The result points are *not* necessarily sorted by distance to their
    query point.

    Parameters
    ----------
    X : array-like, (n_samples, n_features), optional
        The query point or points.
        If not provided, neighbors of each indexed point are returned.
        In this case, the query point is not considered its own neighbor.

    radius : float
        Limiting distance of neighbors to return.
        (default is the value passed to the constructor).

    return_distance : boolean, optional. Defaults to True.
        If False, distances will not be returned

    Returns
    -------
    dist : array, shape (n_samples,) of arrays
        Array representing the distances to each point, only present if
        return_distance=True. The distance values are computed according
        to the ``metric`` constructor parameter.

    ind : array, shape (n_samples,) of arrays
        An array of arrays of indices of the approximate nearest points
        from the population matrix that lie within a ball of size
        ``radius`` around the query points.

    Examples
    --------
    In the following example, we construct a NeighborsClassifier
    class from an array representing our data set and ask who's
    the closest point to [1, 1, 1]:

    >>> import numpy as np
    >>> samples = [[0., 0., 0.], [0., .5, 0.], [1., 1., .5]]
    >>> from sklearn.neighbors import NearestNeighbors
    >>> neigh = NearestNeighbors(radius=1.6)
    >>> neigh.fit(samples) # doctest: +ELLIPSIS
    NearestNeighbors(algorithm='auto', leaf_size=30, ...)
    >>> rng = neigh.radius_neighbors([[1., 1., 1.]])
    >>> print(np.asarray(rng[0][0])) # doctest: +ELLIPSIS
    [1.5 0.5]
    >>> print(np.asarray(rng[1][0])) # doctest: +ELLIPSIS
    [1 2]

    The first array returned contains the distances to all points which
    are closer than 1.6, while the second array returned contains their
    indices.  In general, multiple points can be queried at the same time.

    Notes
    -----
    Because the number of neighbors of each point is not necessarily
    equal, the results for multiple query points cannot be fit in a
    standard data array.
    For efficiency, `radius_neighbors` returns arrays of objects, where
    each object is a 1D array of indices or distances.
    """
    check_is_fitted(self, ["_fit_method", "_fit_X"], all_or_any=any)

    if X is not None:
        query_is_train = False
        X = check_array(X, accept_sparse="csr")
    else:
        query_is_train = True
        X = self._fit_X

    if radius is None:
        radius = self.radius

    if self._fit_method == "brute":
        # for efficiency, use squared euclidean distances
        if self.effective_metric_ == "euclidean":
            radius *= radius
            kwds = {"squared": True}
        else:
            kwds = self.effective_metric_params_

        reduce_func = partial(
            self._radius_neighbors_reduce_func,
            radius=radius,
            return_distance=return_distance,
        )

        results = pairwise_distances_chunked(
            X,
            self._fit_X,
            reduce_func=reduce_func,
            metric=self.effective_metric_,
            n_jobs=self.n_jobs,
            **kwds,
        )
        if return_distance:
            dist_chunks, neigh_ind_chunks = zip(*results)
            dist_list = sum(dist_chunks, [])
            neigh_ind_list = sum(neigh_ind_chunks, [])
            # See https://github.com/numpy/numpy/issues/5456
            # if you want to understand why this is initialized this way.
            dist = np.empty(len(dist_list), dtype="object")
            dist[:] = dist_list
            neigh_ind = np.empty(len(neigh_ind_list), dtype="object")
            neigh_ind[:] = neigh_ind_list
            results = dist, neigh_ind
        else:
            neigh_ind_list = sum(results, [])
            results = np.empty(len(neigh_ind_list), dtype="object")
            results[:] = neigh_ind_list

    elif self._fit_method in ["ball_tree", "kd_tree"]:
        if issparse(X):
            raise ValueError(
                "%s does not work with sparse matrices. Densify the data, "
                "or set algorithm='brute'" % self._fit_method
            )

        n_jobs = effective_n_jobs(self.n_jobs)
        if LooseVersion(joblib_version) < LooseVersion("0.12"):
            # Deal with change of API in joblib
            delayed_query = delayed(
                _tree_query_radius_parallel_helper, check_pickle=False
            )
            parallel_kwargs = {"backend": "threading"}
        else:
            delayed_query = delayed(_tree_query_radius_parallel_helper)
            parallel_kwargs = {"prefer": "threads"}
        results = Parallel(n_jobs, **parallel_kwargs)(
            delayed_query(self._tree, X[s], radius, return_distance)
            for s in gen_even_slices(X.shape[0], n_jobs)
        )
        if return_distance:
            neigh_ind, dist = tuple(zip(*results))
            results = np.hstack(dist), np.hstack(neigh_ind)
        else:
            results = np.hstack(results)
    else:
        raise ValueError("internal: _fit_method not recognized")

    if not query_is_train:
        return results
    else:
        # If the query data is the same as the indexed data, we would like
        # to ignore the first nearest neighbor of every sample, i.e
        # the sample itself.
        if return_distance:
            dist, neigh_ind = results
        else:
            neigh_ind = results

        for ind, ind_neighbor in enumerate(neigh_ind):
            mask = ind_neighbor != ind

            neigh_ind[ind] = ind_neighbor[mask]
            if return_distance:
                dist[ind] = dist[ind][mask]

        if return_distance:
            return dist, neigh_ind
        return neigh_ind