From 15c24df3f82443d09aa0be3abf978d19f6a1b6b5 Mon Sep 17 00:00:00 2001 From: geisserml Date: Mon, 23 Oct 2023 15:10:11 +0200 Subject: [PATCH] Add option to use reference bindings --- README.md | 5 +++- docs/devel/changelog_staging.md | 1 + setupsrc/pypdfium2_setup/packaging_base.py | 15 +++++++++++ src/pypdfium2/version.py | 31 +++++++++++++--------- 4 files changed, 38 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index b9140a541..af9c57b5d 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,10 @@ Note, the APIs below may change any time and are mostly of internal interset. - Version: If given, use the specified pdfium-binaries release. Otherwise, use the latest one. * `$PYPDFIUM_MODULES=[raw,helpers]` defines which modules to include. Metadata adapts dynamically. - May be used by packagers to decouple raw bindings and helpers, which can be important if packaging against system pdfium. - - It would also allow to install only the raw module without helpers, or only helpers with a custom raw module. + - Would also allow to install only the raw module without helpers, or only helpers with a custom raw module. +* `$PDFIUM_BINDINGS=reference` allows to override ctypesgen and use the reference bindings file `autorelease/bindings.py` instead. + - This is a convenience option to get pypdfium2 installed from source even if a working ctypesgen is not available in the install env. + - Warning: This might not be ABI-safe. Please make sure binary/bindings build headers match to avoid ABI issues. [^platform_ids]: This is mainly of internal interest for packaging, so that wheels can be crafted for any platform without access to a native host. diff --git a/docs/devel/changelog_staging.md b/docs/devel/changelog_staging.md index 30467de5c..527081c97 100644 --- a/docs/devel/changelog_staging.md +++ b/docs/devel/changelog_staging.md @@ -5,3 +5,4 @@ # Changelog for next release - Fixed faulty version repr (avoid trailing `+` if desc is empty). +- Added `PDFIUM_BINDINGS=reference` to use pre-built bindings when installing from source. diff --git a/setupsrc/pypdfium2_setup/packaging_base.py b/setupsrc/pypdfium2_setup/packaging_base.py index 69a7229a4..5a3271fe0 100644 --- a/setupsrc/pypdfium2_setup/packaging_base.py +++ b/setupsrc/pypdfium2_setup/packaging_base.py @@ -4,6 +4,7 @@ # No external dependencies shall be imported in this file # TODO improve consistency of variable names; think about variables to move in/out +import os import re import sys import json @@ -26,6 +27,10 @@ PlatTarget_Auto = "auto" # pdfium-binaries for host VerTarget_Latest = "latest" +BindSpec_EnvVar = "PDFIUM_BINDINGS" +BindTarget_Ref = "reference" +BindTarget = os.environ.get(BindSpec_EnvVar, None) + ModulesSpec_EnvVar = "PYPDFIUM_MODULES" ModuleRaw = "raw" ModuleHelpers = "helpers" @@ -158,7 +163,9 @@ def write_json(fp, data, indent=2): def write_pdfium_info(dir, version, origin, flags=[]): # TODO(future) embed library search path for use with a custom ctypesgen loader + # TODO consider embedding ctypesgen version info, probably using a separate file and class? info = dict(**PdfiumVer.to_full(version, origin), origin=origin, flags=flags) + info["bindings"] = BindTarget_Ref if BindTarget == BindTarget_Ref else "generated" write_json(dir/VersionFN, info) @@ -359,6 +366,14 @@ def run_cmd(command, cwd, capture=False, check=True, str_cast=True, **kwargs): def call_ctypesgen(target_dir, include_dir, pl_name, use_v8xfa=False, guard_symbols=False): + # quick and dirty patch to allow using the pre-built bindings instead of calling ctypesgen + if BindTarget == BindTarget_Ref: + print("Using ref bindings as requested by env var.",file=sys.stderr) + if use_v8xfa: + print("Warning: default ref bindings are not V8/XFA compatible, expecting prior overwrite.") + shutil.copyfile(RefBindingsFile, target_dir/BindingsFN) + return + # The commands below are tailored to our fork of ctypesgen, so make sure we have that # Import ctypesgen only in this function so it does not have to be available for other setup tasks import ctypesgen diff --git a/src/pypdfium2/version.py b/src/pypdfium2/version.py index daf9906d0..043bab5ef 100644 --- a/src/pypdfium2/version.py +++ b/src/pypdfium2/version.py @@ -37,15 +37,12 @@ def __getattr__(self, attr): def __setattr__(self, name, value): raise AttributeError(f"Version class is immutable - assignment '{name} = {value}' not allowed") - @cached_property - def version(self): - v = str(self.tag) - if self.desc: - v += "+" + str(self.desc) - return v - def __repr__(self): return self.version + + @cached_property + def version(self): + return self.tag + self.desc # TODO handle data source & editable installs @@ -68,13 +65,15 @@ def tag(self): @cached_property def desc(self): - desc = [] + desc = "" + local_ver = [] if self.n_commits > 0: - desc += [str(self.n_commits), str(self.hash)] + local_ver += [str(self.n_commits), str(self.hash)] if self.dirty: - desc += ["dirty"] - desc = ".".join(desc) + local_ver += ["dirty"] + if local_ver: + desc = "+" + ".".join(local_ver) if self.data_source != "git": desc += f":{self.data_source}" if self.is_editable: @@ -107,9 +106,13 @@ def tag(self): @cached_property def desc(self): - desc = f"{self.origin}" + desc = "" + if self.origin != "pdfium-binaries": + desc += f"+{self.origin}" if self.flags: - desc += ":{%s}" % ','.join(self.flags) + desc += ":{%s}" % ",".join(self.flags) + if self.bindings != "generated": + desc += f"@bindings:{self.bindings}" return desc @@ -218,6 +221,8 @@ def desc(self): - ``system``: Dynamically loaded from a standard system location using :func:`ctypes.util.find_library`. flags (tuple[str]): Tuple of pdfium feature flags. Empty for default build. (V8, XFA) for pdfium-binaries V8 build. + bindings (str): + Info on the used bindings (generated, reference). Note that the reference bindings can be ABI-unsafe. (This field is experimental. In the future, we may want to integrate bindings info separately with ctypesgen version.) """ # -----