version.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. # SPDX-FileCopyrightText: 2024 geisserml <geisserml@gmail.com>
  2. # SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
  3. __all__ = []
  4. import sys
  5. import json
  6. import functools
  7. from pathlib import Path
  8. from types import MappingProxyType
  9. import pypdfium2_raw
  10. # TODO move to shared compat file
  11. if sys.version_info < (3, 8):
  12. def cached_property(func):
  13. return property( functools.lru_cache(maxsize=1)(func) )
  14. else:
  15. cached_property = functools.cached_property
  16. class _abc_version:
  17. @cached_property
  18. def _data(self):
  19. with open(self._FILE, "r") as buf:
  20. data = json.load(buf)
  21. self._process_data(data)
  22. return MappingProxyType(data)
  23. def _process_data(self, data):
  24. pass
  25. def __getattr__(self, attr):
  26. return self._data[attr]
  27. def __setattr__(self, name, value):
  28. raise AttributeError(f"Version class is immutable - assignment '{name} = {value}' not allowed")
  29. def __repr__(self):
  30. return self.version
  31. @cached_property
  32. def api_tag(self):
  33. return tuple(self._data[k] for k in self._TAG_FIELDS)
  34. def _craft_tag(self):
  35. return ".".join(str(v) for v in self.api_tag)
  36. def _craft_desc(self, extra=[]):
  37. local_ver = []
  38. if self.n_commits > 0:
  39. local_ver += [str(self.n_commits), str(self.hash)]
  40. local_ver += extra
  41. desc = ""
  42. if local_ver:
  43. desc += "+" + ".".join(local_ver)
  44. return desc
  45. @cached_property
  46. def version(self):
  47. return self.tag + self.desc
  48. class _version_pypdfium2 (_abc_version):
  49. _FILE = Path(__file__).parent / "version.json"
  50. _TAG_FIELDS = ("major", "minor", "patch")
  51. @cached_property
  52. def tag(self):
  53. tag = self._craft_tag()
  54. if self.beta is not None:
  55. tag += f"b{self.beta}"
  56. return tag
  57. @cached_property
  58. def desc(self):
  59. extra = []
  60. if self.dirty:
  61. extra += ["dirty"]
  62. desc = self._craft_desc(extra)
  63. if self.data_source != "git":
  64. desc += f":{self.data_source}"
  65. if self.is_editable:
  66. desc += "@editable"
  67. return desc
  68. class _version_pdfium (_abc_version):
  69. _FILE = Path(pypdfium2_raw.__file__).parent / "version.json"
  70. _TAG_FIELDS = ("major", "minor", "build", "patch")
  71. def _process_data(self, data):
  72. data["flags"] = tuple(data["flags"])
  73. @cached_property
  74. def tag(self):
  75. return self._craft_tag()
  76. @cached_property
  77. def desc(self):
  78. desc = self._craft_desc()
  79. if self.flags:
  80. desc += ":{%s}" % ",".join(self.flags)
  81. if self.origin != "pdfium-binaries":
  82. desc += f"@{self.origin}"
  83. return desc
  84. # TODO(future) add bindings info (e.g. ctypesgen version, reference/generated, runtime libdirs)
  85. # Current API
  86. PYPDFIUM_INFO = _version_pypdfium2()
  87. PDFIUM_INFO = _version_pdfium()
  88. __all__ += ["PYPDFIUM_INFO", "PDFIUM_INFO"]
  89. # -----
  90. # Deprecated API, to be removed with v5
  91. # Known issue: causes eager evaluation of the new API's theoretically deferred properties.
  92. V_PYPDFIUM2 = PYPDFIUM_INFO.version
  93. V_LIBPDFIUM = str(PDFIUM_INFO.build)
  94. V_BUILDNAME = PDFIUM_INFO.origin
  95. V_PDFIUM_IS_V8 = "V8" in PDFIUM_INFO.flags # implies XFA
  96. V_LIBPDFIUM_FULL = PDFIUM_INFO.version
  97. __all__ += ["V_PYPDFIUM2", "V_LIBPDFIUM", "V_LIBPDFIUM_FULL", "V_BUILDNAME", "V_PDFIUM_IS_V8"]
  98. # -----
  99. # Docs
  100. PYPDFIUM_INFO = PYPDFIUM_INFO
  101. """
  102. pypdfium2 helpers version.
  103. It is suggesed to compare against *api_tag* and possibly also *beta* (see below).
  104. Parameters:
  105. version (str):
  106. Joined tag and desc, forming the full version.
  107. tag (str):
  108. Version ciphers joined as str, including possible beta. Corresponds to the latest release tag at install time.
  109. desc (str):
  110. Non-cipher descriptors represented as str.
  111. api_tag (tuple[int]):
  112. Version ciphers joined as tuple, excluding possible beta.
  113. major (int):
  114. Major cipher.
  115. minor (int):
  116. Minor cipher.
  117. patch (int):
  118. Patch cipher.
  119. beta (int | None):
  120. Beta cipher, or None if not a beta version.
  121. n_commits (int):
  122. Number of commits after tag at install time. 0 for release.
  123. hash (str | None):
  124. Hash of head commit if n_commits > 0, None otherwise.
  125. dirty (bool):
  126. True if there were uncommitted changes at install time, False otherwise.
  127. data_source (str):
  128. Source of this version info. Possible values:\n
  129. - ``git``: Parsed from git describe. Always used if available. Highest accuracy.
  130. - ``given``: Pre-supplied version file (e.g. packaged with sdist, or else created by caller).
  131. - ``record``: Parsed from autorelease record. Implies that possible changes after tag are unknown.
  132. is_editable (bool | None):
  133. True for editable install, False otherwise. None if unknown.\n
  134. If True, the version info is the one captured at install time. An arbitrary number of forward or reverse changes may have happened since. The actual current state is unknown.
  135. """
  136. PDFIUM_INFO = PDFIUM_INFO
  137. """
  138. PDFium version.
  139. It is suggesed to compare against *build* (see below).
  140. Parameters:
  141. version (str):
  142. Joined tag and desc, forming the full version.
  143. tag (str):
  144. Version ciphers joined as str.
  145. desc (str):
  146. Descriptors (origin, flags) represented as str.
  147. api_tag (tuple[int]):
  148. Version ciphers joined as tuple.
  149. major (int):
  150. Chromium major cipher.
  151. minor (int):
  152. Chromium minor cipher.
  153. build (int):
  154. Chromium/pdfium build cipher.
  155. This value allows to uniquely identify the pdfium sources the binary was built from.
  156. patch (int):
  157. Chromium patch cipher.
  158. n_commits (int):
  159. Number of commits after tag at install time. 0 for tagged build commit.
  160. hash (str | None):
  161. Hash of head commit if n_commits > 0, None otherwise.
  162. origin (str):
  163. The pdfium binary's origin. Possible values:\n
  164. - ``pdfium-binaries``: Compiled by bblanchon/pdfium-binaries, and bundled into pypdfium2.
  165. - ``sourcebuild``: Provided by the caller (commonly compiled using pypdfium2's integrated build script), and bundled into pypdfium2.
  166. - ``system``: Loaded from a standard system location using :func:`ctypes.util.find_library()`, or an explicit directory provided at setup time.
  167. flags (tuple[str]):
  168. Tuple of pdfium feature flags. Empty for default build. (V8, XFA) for pdfium-binaries V8 build.
  169. """
  170. # -----