Replace isort, flake8, pycln and pyupgrade by ruff. [Ruff](https://github.com/charliermarsh/ruff) is getting popular lately, and I really like the idea of having a single tool for Python lining instead of N which currently exist. Also written in Rust which is a good use case for this.

 It's supposed to have equivalent functionality, to the ones we are using. The fact that major projects are adopting it is a good sign (see list in their readme).  There are also a few extra options in their readme that look interesting and that we could enable (without having to install yet another plugin)

We won't gain much speed-wise: previously isort, flake8 (which itself is an abstraction over pycodestyle and pyflakes), pycln and pyupgrade  on all files was around 1s, and now it's 20ms. But with mypy taking 10s, it makes mostly no difference.
Still it makes the overall linting configuration easier to maintain.


If we go forward with this, I imagine a changelog is not needed? 

From 0e75392a82b3b1ddc965895468e6c30ab973f6e9 Mon Sep 17 00:00:00 2001
From: Hood Chatham <roberthoodchatham@gmail.com>
Date: Mon, 29 Aug 2022 16:45:21 -0700
Subject: [PATCH 11/13] Change qh_eachvoronoi_all FILE type

---
 scipy/spatial/_qhull.pyx | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/scipy/spatial/_qhull.pyx b/scipy/spatial/_qhull.pyx
index 8c9135adc..5726cc704 100644
--- a/scipy/spatial/_qhull.pyx
+++ b/scipy/spatial/_qhull.pyx
@@ -18,6 +18,7 @@ from . cimport _qhull
 from . cimport setlist
 from libc cimport stdlib
 from scipy._lib.messagestream cimport MessageStream
+from libc.stdio cimport FILE
 
 import os
 import sys
@@ -185,7 +186,7 @@ cdef extern from "qhull_src/src/io_r.h":
 
     ctypedef void printvridgeT(qhT *, void *fp, vertexT *vertex, vertexT *vertexA,
                                setT *centers, boolT unbounded)
-    int qh_eachvoronoi_all(qhT *, void *fp, void* printvridge,
+    int qh_eachvoronoi_all(qhT *, FILE *fp, void* printvridge,
                            boolT isUpper, qh_RIDGE innerouter,
                            boolT inorder) nogil
 
@@ -830,7 +831,7 @@ cdef class _Qhull:
         self._ridge_points = np.empty((10, 2), np.intc)
         self._ridge_vertices = []
 
-        qh_eachvoronoi_all(self._qh, <void*>self, &_visit_voronoi, self._qh[0].UPPERdelaunay,
+        qh_eachvoronoi_all(self._qh, <FILE*>self, &_visit_voronoi, self._qh[0].UPPERdelaunay,
                            qh_RIDGEall, 1)
 
         self._ridge_points = self._ridge_points[:self._nridges]
@@ -992,7 +993,7 @@ cdef class _Qhull:
         return extremes_arr
 
 
-cdef void _visit_voronoi(qhT *_qh, void *ptr, vertexT *vertex, vertexT *vertexA,
+cdef void _visit_voronoi(qhT *_qh, FILE *ptr, vertexT *vertex, vertexT *vertexA,
                          setT *centers, boolT unbounded):
     cdef _Qhull qh = <_Qhull>ptr
     cdef int point_1, point_2, ix
-- 
2.25.1


From 0e75392a82b3b1ddc965895468e6c30ab973f6e9 Mon Sep 17 00:00:00 2001
From: Hood Chatham <roberthoodchatham@gmail.com>
Date: Mon, 29 Aug 2022 16:45:21 -0700
Subject: [PATCH 11/13] Change qh_eachvoronoi_all FILE type

---
 scipy/spatial/_qhull.pyx | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/scipy/spatial/_qhull.pyx b/scipy/spatial/_qhull.pyx
index 8c9135adc..5726cc704 100644
--- a/scipy/spatial/_qhull.pyx
+++ b/scipy/spatial/_qhull.pyx
@@ -18,6 +18,7 @@ from . cimport _qhull
 from . cimport setlist
 from libc cimport stdlib
 from scipy._lib.messagestream cimport MessageStream
+from libc.stdio cimport FILE
 
 import os
 import sys
@@ -185,7 +186,7 @@ cdef extern from "qhull_src/src/io_r.h":
 
     ctypedef void printvridgeT(qhT *, void *fp, vertexT *vertex, vertexT *vertexA,
                                setT *centers, boolT unbounded)
-    int qh_eachvoronoi_all(qhT *, void *fp, void* printvridge,
+    int qh_eachvoronoi_all(qhT *, FILE *fp, void* printvridge,
                            boolT isUpper, qh_RIDGE innerouter,
                            boolT inorder) nogil
 
@@ -830,7 +831,7 @@ cdef class _Qhull:
         self._ridge_points = np.empty((10, 2), np.intc)
         self._ridge_vertices = []
 
-        qh_eachvoronoi_all(self._qh, <void*>self, &_visit_voronoi, self._qh[0].UPPERdelaunay,
+        qh_eachvoronoi_all(self._qh, <FILE*>self, &_visit_voronoi, self._qh[0].UPPERdelaunay,
                            qh_RIDGEall, 1)
 
         self._ridge_points = self._ridge_points[:self._nridges]
@@ -992,7 +993,7 @@ cdef class _Qhull:
         return extremes_arr
 
 
-cdef void _visit_voronoi(qhT *_qh, void *ptr, vertexT *vertex, vertexT *vertexA,
+cdef void _visit_voronoi(qhT *_qh, FILE *ptr, vertexT *vertex, vertexT *vertexA,
                          setT *centers, boolT unbounded):
     cdef _Qhull qh = <_Qhull>ptr
     cdef int point_1, point_2, ix
-- 
2.25.1

