mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-24 22:27:55 -05:00
grpcio-tools 1.82.0+ (including its 1.82.0 pre-releases) bundles a protoc that emits protobuf 7.35.x gencode, which no protobuf 6 runtime can load. Pin grpcio-tools below that (excluding pre-releases via the '.dev0' trick, since a plain '<1.82' bound already let a 1.82.0rc release slip through once) and add a CI check that verifies the generated *_pb2.py files stay within the protobuf floor declared in pyproject.toml. Only the load-bearing bounds are kept: protobuf's '>=6.33.5' floor (must match the emitted gencode) and grpcio-tools' '<1.82.0.dev0' ceiling. Non-load-bearing bounds (protobuf's '<8', grpcio-tools' '>=1.81') were dropped since they don't change dependency resolution or protect against anything the above doesn't already cover.
78 lines
2.7 KiB
Python
78 lines
2.7 KiB
Python
"""Check that the generated protobuf code can be loaded by every supported runtime.
|
|
|
|
The protobuf runtime refuses to load gencode newer than itself, so the gencode
|
|
version emitted by grpcio-tools must not exceed the lower bound declared for
|
|
protobuf in pyproject.toml. Nothing ties those two together: a grpcio-tools
|
|
upgrade can move the gencode a full major version without any edit here, and
|
|
the resulting package still installs cleanly and only fails at import time.
|
|
"""
|
|
|
|
import re
|
|
import sys
|
|
import tomllib
|
|
from pathlib import Path
|
|
|
|
from packaging.requirements import Requirement
|
|
from packaging.version import Version
|
|
|
|
HERE = Path(__file__).parent
|
|
GENERATED = HERE / "rips" / "generated"
|
|
GENCODE_PATTERN = re.compile(r"^# Protobuf Python Version: (\S+)", re.MULTILINE)
|
|
|
|
|
|
def declared_protobuf_floor() -> Version:
|
|
"""Lowest protobuf runtime a user of this package can end up with."""
|
|
with (HERE / "pyproject.toml").open("rb") as f:
|
|
dependencies = tomllib.load(f)["project"]["dependencies"]
|
|
|
|
requirements = [Requirement(d) for d in dependencies]
|
|
protobuf = next((r for r in requirements if r.name == "protobuf"), None)
|
|
if protobuf is None:
|
|
sys.exit("protobuf is not declared in [project].dependencies")
|
|
|
|
floors = [
|
|
Version(s.version) for s in protobuf.specifier if s.operator in (">=", "==")
|
|
]
|
|
if not floors:
|
|
sys.exit(
|
|
f"protobuf dependency '{protobuf}' has no lower bound to check against"
|
|
)
|
|
|
|
return max(floors)
|
|
|
|
|
|
def gencode_versions() -> dict[str, Version]:
|
|
versions = {}
|
|
for path in sorted(GENERATED.glob("*_pb2.py")):
|
|
match = GENCODE_PATTERN.search(path.read_text(encoding="utf-8"))
|
|
if match is None:
|
|
sys.exit(f"{path.name} has no gencode version header")
|
|
versions[path.name] = Version(match.group(1))
|
|
return versions
|
|
|
|
|
|
def main() -> None:
|
|
floor = declared_protobuf_floor()
|
|
versions = gencode_versions()
|
|
if not versions:
|
|
sys.exit(f"no generated *_pb2.py files in {GENERATED}, nothing was verified")
|
|
|
|
too_new = {name: v for name, v in versions.items() if v > floor}
|
|
if too_new:
|
|
listing = "\n".join(f" {name}: gencode {v}" for name, v in too_new.items())
|
|
sys.exit(
|
|
f"Generated code is newer than the oldest supported protobuf runtime ({floor}).\n"
|
|
f"{listing}\n"
|
|
"Pin grpcio-tools to a release emitting older gencode, or raise the protobuf "
|
|
"lower bound in pyproject.toml. Note that raising it drops support for runtimes "
|
|
"below the new bound."
|
|
)
|
|
|
|
print(
|
|
f"{len(versions)} generated files, gencode {max(versions.values())}, runtime floor {floor}: OK"
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|