Repository: cython/cython

Issue:
`numpy.distutils` is deprecated.
### Describe your issue

When running test suite, I have discovered following warning:

```
[-1] compiling (c/cy2) and running numpy_cimport ...
=== C/C++ compiler error output: ===
/Users/ness-skmac3/dev/cython/runtests.py:250: DeprecationWarning:

  `numpy.distutils` is deprecated since NumPy 1.23.0, as a result
  of the deprecation of `distutils` itself. It will be removed for
  Python >= 3.12. For older Python versions it will remain present.
  It is recommended to use `setuptools < 60.0` for those Python versions.
  For more details, see:
    https://numpy.org/devdocs/reference/distutils_status_migration.html


  from numpy.distutils.misc_util import get_info
====================================
```

Moreover, `numpy.distutils` is also used here:
https://github.com/cython/cython/blob/6ad6ca0e9e7d030354b7fe7d7b56c3f6e6a4bc23/Demos/setup.py#L15

I suppose it should be fix before python 3.12. Ref. https://github.com/numpy/numpy/issues/18588


Discussion:
@mattip is there any preferred way how to replace mentioned functions? I was not able to figure out from the documentation (but I did not go deep to be honest).
Does `numpy.get_include()` work for the directories? (I haven't looked to see if there's anything else we use)
I only see those two
```
$ git grep "numpy.distutils"
Demos/setup.py:    from numpy.distutils.misc_util import get_numpy_include_dirs
runtests.py:    from numpy.distutils.misc_util import get_info
```

The first has been moved, as you said, to `numpy.get_include()`
The second is a little more involved. We prefer people move away from `setup.py` to meson. There is still an example `setup.py` in [the 1.25 docs](https://numpy.org/doc/stable/reference/random/examples/cython/setup.py.html#setup-py). The recommended pattern is to use
```
defs = [('NPY_NO_DEPRECATED_API', 0)]
inc_path = np.get_include()
# Add paths for npyrandom and npymath libraries:
lib_path = [
    abspath(join(np.get_include(), '..', '..', 'random', 'lib')),
    abspath(join(np.get_include(), '..', 'lib'))
]
ext = Extension("extending_distributions",
                          sources=[join('.', 'extending_distributions.pyx')],
                          include_dirs=[inc_path],
                          library_dirs=lib_path,
                          libraries=['npyrandom', 'npymath'],
                          define_macros=defs,
                          )
```


Resolving patch:
diff --git a/Demos/setup.py b/Demos/setup.py
--- a/Demos/setup.py
+++ b/Demos/setup.py
@@ -12,13 +12,14 @@
 
 # Only compile the following if numpy is installed.
 try:
-    from numpy.distutils.misc_util import get_numpy_include_dirs
+    from numpy import get_include
+except ImportError:
+    pass
+else:
     numpy_demo = [Extension("*",
                             ["numpy_*.pyx"],
-                            include_dirs=get_numpy_include_dirs())]
+                            include_dirs=get_include())]
     ext_modules.extend(cythonize(numpy_demo))
-except ImportError:
-    pass
 
 setup(
   name = 'Demos',
diff --git a/runtests.py b/runtests.py
--- a/runtests.py
+++ b/runtests.py
@@ -246,19 +246,22 @@ def update_linetrace_extension(ext):
 
 
 def update_numpy_extension(ext, set_api17_macro=True):
-    import numpy
-    from numpy.distutils.misc_util import get_info
-
-    ext.include_dirs.append(numpy.get_include())
+    import numpy as np
+    # Add paths for npyrandom and npymath libraries:
+    lib_path = [
+        os.path.abspath(os.path.join(np.get_include(), '..', '..', 'random', 'lib')),
+        os.path.abspath(os.path.join(np.get_include(), '..', 'lib'))
+    ]
+    ext.library_dirs += lib_path
+    if sys.platform == "win32":
+        ext.libraries += ["npymath"]
+    else:
+        ext.libraries += ["npymath", "m"]
+    ext.include_dirs.append(np.get_include())
 
-    if set_api17_macro and getattr(numpy, '__version__', '') not in ('1.19.0', '1.19.1'):
+    if set_api17_macro and getattr(np, '__version__', '') not in ('1.19.0', '1.19.1'):
         ext.define_macros.append(('NPY_NO_DEPRECATED_API', 'NPY_1_7_API_VERSION'))
-
-    # We need the npymath library for numpy.math.
-    # This is typically a static-only library.
-    for attr, value in get_info('npymath').items():
-        getattr(ext, attr).extend(value)
-
+    del np
 
 def update_gdb_extension(ext, _has_gdb=[None]):
     # We should probably also check for Python support.


Test patch: