[pygobject] setup.py: look up pycairo headers without importing the module
- From: Christoph Reiter <creiter src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] setup.py: look up pycairo headers without importing the module
- Date: Wed, 13 Apr 2022 22:09:10 +0000 (UTC)
commit 5f614b36b8f61caab581a56ccf320fee3177051b
Author: Christoph Reiter <reiter christoph gmail com>
Date: Sat Apr 9 11:46:58 2022 +0200
setup.py: look up pycairo headers without importing the module
Up until now pycairo provided a cairo.get_include() helper which
could be used to find the required include directory matching the module,
considering various scenarios.
Starting with 3.8 this leads to problems on Windows since CPython on Windows
will no longer use PATH for the DLL lookup and expects the library user to
explicitely pass the directory where the cairo DLL can be found.
In a build environment the user has no control over this though, so we have to
find the include directory without loading/importing pycairo again.
This now uses a combination of importlib.util.find_spec() for finding the module
and importlib.metadata.distribution() for finding the package version.
Hopefully this covers all cases.
setup.py | 78 ++++++++++++++++++++++++++--------------------------------------
1 file changed, 31 insertions(+), 47 deletions(-)
---
diff --git a/setup.py b/setup.py
index 5f801607..f50c3052 100755
--- a/setup.py
+++ b/setup.py
@@ -22,7 +22,6 @@ import sys
import errno
import subprocess
import tarfile
-import sysconfig
import tempfile
import posixpath
@@ -827,7 +826,9 @@ def get_pycairo_include_dir():
pkg_config_name = "py3cairo"
min_version = get_version_requirement(pkg_config_name)
- min_version_info = tuple(int(p) for p in min_version.split("."))
+
+ def parse_version(string):
+ return tuple(int(p) for p in string.split("."))
def check_path(include_dir):
log.info("pycairo: trying include directory: %r" % include_dir)
@@ -843,61 +844,44 @@ def get_pycairo_include_dir():
if check_path(p):
return p
- def find_new_api():
- log.info("pycairo: new API")
- import cairo
-
- if cairo.version_info < min_version_info:
- raise DistutilsSetupError(
- "pycairo >= %s required, %s found." % (
- min_version, ".".join(map(str, cairo.version_info))))
-
- if hasattr(cairo, "get_include"):
- return [cairo.get_include()]
- log.info("pycairo: no get_include()")
- return []
+ def find_python():
+ """This tries to find the pycairo module without importing it"""
- def find_old_api():
- log.info("pycairo: old API")
+ from importlib.util import find_spec
- import cairo
+ # Find the module path
+ spec = find_spec("cairo")
+ if spec is None:
+ log.info("pycairo: cairo module not found via importlib")
+ return []
+ package_path = os.path.dirname(spec.origin)
- if cairo.version_info < min_version_info:
- raise DistutilsSetupError(
- "pycairo >= %s required, %s found." % (
- min_version, ".".join(map(str, cairo.version_info))))
-
- location = os.path.dirname(os.path.abspath(cairo.__path__[0]))
- log.info("pycairo: found %r" % location)
-
- def get_sys_path(location, name):
- # Returns the sysconfig path for a distribution, or None
- for scheme in sysconfig.get_scheme_names():
- for path_type in ["platlib", "purelib"]:
- path = sysconfig.get_path(path_type, scheme)
- try:
- if os.path.samefile(path, location):
- return sysconfig.get_path(name, scheme)
- except EnvironmentError:
- pass
+ # With Python 3.8 we can also check the package version
+ try:
+ from importlib.metadata import distribution, PackageNotFoundError
+ except ImportError:
+ # Python <3.8
+ pass
+ else:
+ try:
+ d = distribution("pycairo")
+ except PackageNotFoundError:
+ log.info("pycairo: pycairo distribution not found via importlib")
+ else:
+ if parse_version(d.version) < parse_version(min_version):
+ raise DistutilsSetupError(
+ "pycairo >= %s required, %s found (%s)." % (
+ min_version, d.version, package_path))
- data_path = get_sys_path(location, "data") or sys.prefix
- return [os.path.join(data_path, "include", "pycairo")]
+ return [os.path.join(package_path, 'include')]
def find_pkg_config():
log.info("pycairo: pkg-config")
pkg_config_version_check(pkg_config_name, min_version)
return pkg_config_parse("--cflags-only-I", pkg_config_name)
- # First the new get_include() API added in >1.15.6
- include_dir = find_path(find_new_api())
- if include_dir is not None:
- return include_dir
-
- # Then try to find it in the data prefix based on the module path.
- # This works with many virtualenv/userdir setups, but not all apparently,
- # see https://gitlab.gnome.org/GNOME/pygobject/issues/150
- include_dir = find_path(find_old_api())
+ # First look in the current Python installation/venv
+ include_dir = find_path(find_python())
if include_dir is not None:
return include_dir
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]