1{ 2 buildPackages, 3 buildPythonPackage, 4 fetchpatch, 5 isPyPy, 6 lib, 7 stdenv, 8 numpy, 9 protobuf, 10 pytestCheckHook, 11 pythonAtLeast, 12 replaceVars, 13 tzdata, 14}: 15 16assert lib.versionOlder protobuf.version "21" -> throw "Protobuf 21 or newer required"; 17 18let 19 protobufVersionMajor = lib.versions.major protobuf.version; 20 protobufVersionMinor = lib.versions.minor protobuf.version; 21in 22buildPythonPackage { 23 inherit (protobuf) pname src; 24 25 # protobuf 21 corresponds with its python library 4.21 26 version = "4.${protobufVersionMajor}.${protobufVersionMinor}"; 27 format = "setuptools"; 28 29 sourceRoot = "${protobuf.src.name}/python"; 30 31 patches = 32 lib.optionals (lib.versionAtLeast protobuf.version "22") [ 33 # Replace the vendored abseil-cpp with nixpkgs' 34 (replaceVars ./use-nixpkgs-abseil-cpp.patch { 35 abseil_cpp_include_path = "${lib.getDev protobuf.abseil-cpp}/include"; 36 }) 37 ] 38 ++ lib.optionals (pythonAtLeast "3.11" && lib.versionOlder protobuf.version "22") [ 39 (fetchpatch { 40 name = "support-python311.patch"; 41 url = "https://github.com/protocolbuffers/protobuf/commit/2206b63c4649cf2e8a06b66c9191c8ef862ca519.diff"; 42 stripLen = 1; # because sourceRoot above 43 hash = "sha256-3GaoEyZIhS3QONq8LEvJCH5TdO9PKnOgcQF0GlEiwFo="; 44 }) 45 ]; 46 47 prePatch = '' 48 if [[ "$(<../version.json)" != *'"python": "'"$version"'"'* ]]; then 49 echo "Python library version mismatch. Derivation version: $version, actual: $(<../version.json)" 50 exit 1 51 fi 52 ''; 53 54 # Remove the line in setup.py that forces compiling with C++14. Upstream's 55 # CMake build has been updated to support compiling with other versions of 56 # C++, but the Python build has not. Without this, we observe compile-time 57 # errors using GCC. 58 # 59 # Fedora appears to do the same, per this comment: 60 # 61 # https://github.com/protocolbuffers/protobuf/issues/12104#issuecomment-1542543967 62 # 63 postPatch = '' 64 sed -i "/extra_compile_args.append('-std=c++14')/d" setup.py 65 66 # The former function has been renamed into the latter in Python 3.12. 67 # Does not apply to all protobuf versions, hence --replace-warn. 68 substituteInPlace google/protobuf/internal/json_format_test.py \ 69 --replace-warn assertRaisesRegexp assertRaisesRegex 70 ''; 71 72 nativeBuildInputs = lib.optional isPyPy tzdata; 73 74 buildInputs = [ protobuf ]; 75 76 propagatedNativeBuildInputs = [ 77 # For protoc of the same version. 78 buildPackages."protobuf_${protobufVersionMajor}" 79 ]; 80 81 setupPyGlobalFlags = [ "--cpp_implementation" ]; 82 83 nativeCheckInputs = [ 84 pytestCheckHook 85 ] 86 ++ lib.optionals (lib.versionAtLeast protobuf.version "22") [ numpy ]; 87 88 disabledTests = 89 lib.optionals isPyPy [ 90 # error message differs 91 "testInvalidTimestamp" 92 # requires tracemalloc which pypy does not implement 93 # https://foss.heptapod.net/pypy/pypy/-/issues/3048 94 "testUnknownFieldsNoMemoryLeak" 95 # assertion is not raised for some reason 96 "testStrictUtf8Check" 97 ] 98 ++ lib.optionals stdenv.hostPlatform.is32bit [ 99 # OverflowError: timestamp out of range for platform time_t 100 "testTimezoneAwareDatetimeConversionWhereTimestampLosesPrecision" 101 "testTimezoneNaiveDatetimeConversionWhereTimestampLosesPrecision" 102 ]; 103 104 disabledTestPaths = 105 lib.optionals (lib.versionAtLeast protobuf.version "23") [ 106 # The following commit (I think) added some internal test logic for Google 107 # that broke generator_test.py. There is a new proto file that setup.py is 108 # not generating into a .py file. However, adding this breaks a bunch of 109 # conflict detection in descriptor_test.py that I don't understand. So let's 110 # just disable generator_test.py for now. 111 # 112 # https://github.com/protocolbuffers/protobuf/commit/5abab0f47e81ac085f0b2d17ec3b3a3b252a11f1 113 # 114 "google/protobuf/internal/generator_test.py" 115 ] 116 ++ lib.optionals (lib.versionAtLeast protobuf.version "25") [ 117 "minimal_test.py" # ModuleNotFoundError: No module named 'google3' 118 ]; 119 120 pythonImportsCheck = [ 121 "google.protobuf" 122 "google.protobuf.internal._api_implementation" # Verify that --cpp_implementation worked 123 ]; 124 125 passthru = { 126 inherit protobuf; 127 }; 128 129 meta = with lib; { 130 description = "Protocol Buffers are Google's data interchange format"; 131 homepage = "https://developers.google.com/protocol-buffers/"; 132 license = licenses.bsd3; 133 maintainers = with maintainers; [ ]; 134 broken = lib.versionAtLeast protobuf.version "26"; 135 }; 136}