diff --git a/doc/release/upcoming_changes/17530.improvement.rst b/doc/release/upcoming_changes/17530.improvement.rst new file mode 100644 index 000000000000..07a23f0e5e6b --- /dev/null +++ b/doc/release/upcoming_changes/17530.improvement.rst @@ -0,0 +1,5 @@ +`ctypeslib.load_library` can now take any path-like object +----------------------------------------------------------------------- +All parameters in the can now take any :term:`python:path-like object`. +This includes the likes of strings, bytes and objects implementing the +:meth:`__fspath__` protocol. diff --git a/numpy/ctypeslib.py b/numpy/ctypeslib.py index 8ba6f15e5a6d..8d105a248f17 100644 --- a/numpy/ctypeslib.py +++ b/numpy/ctypeslib.py @@ -90,18 +90,23 @@ def _dummy(*args, **kwds): def load_library(libname, loader_path): """ It is possible to load a library using + >>> lib = ctypes.cdll[] # doctest: +SKIP But there are cross-platform considerations, such as library file extensions, plus the fact Windows will just load the first library it finds with that name. NumPy supplies the load_library function as a convenience. + .. versionchanged:: 1.20.0 + Allow libname and loader_path to take any + :term:`python:path-like object`. + Parameters ---------- - libname : str + libname : path-like Name of the library, which can have 'lib' as a prefix, but without an extension. - loader_path : str + loader_path : path-like Where the library can be found. Returns @@ -120,6 +125,10 @@ def load_library(libname, loader_path): warnings.warn("All features of ctypes interface may not work " "with ctypes < 1.0.1", stacklevel=2) + # Convert path-like objects into strings + libname = os.fsdecode(libname) + loader_path = os.fsdecode(loader_path) + ext = os.path.splitext(libname)[1] if not ext: # Try to load library with platform-specific name, otherwise diff --git a/numpy/tests/test_ctypeslib.py b/numpy/tests/test_ctypeslib.py index af3730df1cc9..1ea0837008b7 100644 --- a/numpy/tests/test_ctypeslib.py +++ b/numpy/tests/test_ctypeslib.py @@ -1,6 +1,7 @@ import sys import pytest import weakref +from pathlib import Path import numpy as np from numpy.ctypeslib import ndpointer, load_library, as_array @@ -37,13 +38,15 @@ reason="Known to fail on cygwin") class TestLoadLibrary: def test_basic(self): - try: - # Should succeed - load_library('_multiarray_umath', np.core._multiarray_umath.__file__) - except ImportError as e: - msg = ("ctypes is not available on this python: skipping the test" - " (import error was: %s)" % str(e)) - print(msg) + loader_path = np.core._multiarray_umath.__file__ + + out1 = load_library('_multiarray_umath', loader_path) + out2 = load_library(Path('_multiarray_umath'), loader_path) + out3 = load_library('_multiarray_umath', Path(loader_path)) + out4 = load_library(b'_multiarray_umath', loader_path) + + assert isinstance(out1, ctypes.CDLL) + assert out1 is out2 is out3 is out4 def test_basic2(self): # Regression for #801: load_library with a full library name