1# Copyright 2015 gRPC authors. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14"""A setup module for the GRPC Python package.""" 15 16# NOTE(https://github.com/grpc/grpc/issues/24028): allow setuptools to monkey 17# patch distutils 18import setuptools # isort:skip 19 20# Monkey Patch the unix compiler to accept ASM 21# files used by boring SSL. 22from distutils.unixccompiler import UnixCCompiler 23 24UnixCCompiler.src_extensions.append(".S") 25del UnixCCompiler 26 27import os 28import os.path 29import pathlib 30import platform 31import re 32import shlex 33import shutil 34import subprocess 35from subprocess import PIPE 36import sys 37import sysconfig 38 39import _metadata 40from setuptools import Extension 41from setuptools.command import egg_info 42 43# Redirect the manifest template from MANIFEST.in to PYTHON-MANIFEST.in. 44egg_info.manifest_maker.template = "PYTHON-MANIFEST.in" 45 46PY3 = sys.version_info.major == 3 47PYTHON_STEM = os.path.join("src", "python", "grpcio") 48CORE_INCLUDE = ( 49 "include", 50 ".", 51) 52ABSL_INCLUDE = (os.path.join("third_party", "abseil-cpp"),) 53ADDRESS_SORTING_INCLUDE = ( 54 os.path.join("third_party", "address_sorting", "include"), 55) 56CARES_INCLUDE = ( 57 os.path.join("third_party", "cares", "cares", "include"), 58 os.path.join("third_party", "cares"), 59 os.path.join("third_party", "cares", "cares"), 60) 61if "darwin" in sys.platform: 62 CARES_INCLUDE += (os.path.join("third_party", "cares", "config_darwin"),) 63if "freebsd" in sys.platform: 64 CARES_INCLUDE += (os.path.join("third_party", "cares", "config_freebsd"),) 65if "linux" in sys.platform: 66 CARES_INCLUDE += (os.path.join("third_party", "cares", "config_linux"),) 67if "openbsd" in sys.platform: 68 CARES_INCLUDE += (os.path.join("third_party", "cares", "config_openbsd"),) 69RE2_INCLUDE = (os.path.join("third_party", "re2"),) 70SSL_INCLUDE = ( 71 os.path.join("third_party", "boringssl-with-bazel", "src", "include"), 72) 73UPB_INCLUDE = (os.path.join("third_party", "upb"),) 74UPB_GRPC_GENERATED_INCLUDE = (os.path.join("src", "core", "ext", "upb-gen"),) 75UPBDEFS_GRPC_GENERATED_INCLUDE = ( 76 os.path.join("src", "core", "ext", "upbdefs-gen"), 77) 78UTF8_RANGE_INCLUDE = (os.path.join("third_party", "utf8_range"),) 79XXHASH_INCLUDE = (os.path.join("third_party", "xxhash"),) 80ZLIB_INCLUDE = (os.path.join("third_party", "zlib"),) 81README = os.path.join(PYTHON_STEM, "README.rst") 82 83# Ensure we're in the proper directory whether or not we're being used by pip. 84os.chdir(os.path.dirname(os.path.abspath(__file__))) 85sys.path.insert(0, os.path.abspath(PYTHON_STEM)) 86 87# Break import-style to ensure we can actually find our in-repo dependencies. 88import _parallel_compile_patch 89import _spawn_patch 90import grpc_core_dependencies 91 92import commands 93import grpc_version 94 95_parallel_compile_patch.monkeypatch_compile_maybe() 96_spawn_patch.monkeypatch_spawn() 97 98LICENSE = "Apache License 2.0" 99 100CLASSIFIERS = [ 101 "Development Status :: 5 - Production/Stable", 102 "Programming Language :: Python", 103 "Programming Language :: Python :: 3", 104 "Programming Language :: Python :: 3.8", 105 "Programming Language :: Python :: 3.9", 106 "Programming Language :: Python :: 3.10", 107 "Programming Language :: Python :: 3.11", 108 "Programming Language :: Python :: 3.12", 109 "License :: OSI Approved :: Apache Software License", 110] 111 112 113def _env_bool_value(env_name, default): 114 """Parses a bool option from an environment variable""" 115 return os.environ.get(env_name, default).upper() not in ["FALSE", "0", ""] 116 117 118BUILD_WITH_BORING_SSL_ASM = _env_bool_value( 119 "GRPC_BUILD_WITH_BORING_SSL_ASM", "True" 120) 121 122# Export this environment variable to override the platform variant that will 123# be chosen for boringssl assembly optimizations. This option is useful when 124# crosscompiling and the host platform as obtained by sysconfig.get_platform() 125# doesn't match the platform we are targetting. 126# Example value: "linux-aarch64" 127BUILD_OVERRIDE_BORING_SSL_ASM_PLATFORM = os.environ.get( 128 "GRPC_BUILD_OVERRIDE_BORING_SSL_ASM_PLATFORM", "" 129) 130 131# Environment variable to determine whether or not the Cython extension should 132# *use* Cython or use the generated C files. Note that this requires the C files 133# to have been generated by building first *with* Cython support. Even if this 134# is set to false, if the script detects that the generated `.c` file isn't 135# present, then it will still attempt to use Cython. 136BUILD_WITH_CYTHON = _env_bool_value("GRPC_PYTHON_BUILD_WITH_CYTHON", "False") 137 138# Export this variable to use the system installation of openssl. You need to 139# have the header files installed (in /usr/include/openssl) and during 140# runtime, the shared library must be installed 141BUILD_WITH_SYSTEM_OPENSSL = _env_bool_value( 142 "GRPC_PYTHON_BUILD_SYSTEM_OPENSSL", "False" 143) 144 145# Export this variable to use the system installation of zlib. You need to 146# have the header files installed (in /usr/include/) and during 147# runtime, the shared library must be installed 148BUILD_WITH_SYSTEM_ZLIB = _env_bool_value( 149 "GRPC_PYTHON_BUILD_SYSTEM_ZLIB", "False" 150) 151 152# Export this variable to use the system installation of cares. You need to 153# have the header files installed (in /usr/include/) and during 154# runtime, the shared library must be installed 155BUILD_WITH_SYSTEM_CARES = _env_bool_value( 156 "GRPC_PYTHON_BUILD_SYSTEM_CARES", "False" 157) 158 159# Export this variable to use the system installation of re2. You need to 160# have the header files installed (in /usr/include/re2) and during 161# runtime, the shared library must be installed 162BUILD_WITH_SYSTEM_RE2 = _env_bool_value("GRPC_PYTHON_BUILD_SYSTEM_RE2", "False") 163 164# Export this variable to use the system installation of abseil. You need to 165# have the header files installed (in /usr/include/absl) and during 166# runtime, the shared library must be installed 167BUILD_WITH_SYSTEM_ABSL = os.environ.get("GRPC_PYTHON_BUILD_SYSTEM_ABSL", False) 168 169# Export this variable to force building the python extension with a statically linked libstdc++. 170# At least on linux, this is normally not needed as we can build manylinux-compatible wheels on linux just fine 171# without statically linking libstdc++ (which leads to a slight increase in the wheel size). 172# This option is useful when crosscompiling wheels for aarch64 where 173# it's difficult to ensure that the crosscompilation toolchain has a high-enough version 174# of GCC (we require >=5.1) but still uses old-enough libstdc++ symbols. 175# TODO(jtattermusch): remove this workaround once issues with crosscompiler version are resolved. 176BUILD_WITH_STATIC_LIBSTDCXX = _env_bool_value( 177 "GRPC_PYTHON_BUILD_WITH_STATIC_LIBSTDCXX", "False" 178) 179 180# For local development use only: This skips building gRPC Core and its 181# dependencies, including protobuf and boringssl. This allows "incremental" 182# compilation by first building gRPC Core using make, then building only the 183# Python/Cython layers here. 184# 185# Note that this requires libboringssl.a in the libs/{dbg,opt}/ directory, which 186# may require configuring make to not use the system openssl implementation: 187# 188# make HAS_SYSTEM_OPENSSL_ALPN=0 189# 190# TODO(ericgribkoff) Respect the BUILD_WITH_SYSTEM_* flags alongside this option 191USE_PREBUILT_GRPC_CORE = _env_bool_value( 192 "GRPC_PYTHON_USE_PREBUILT_GRPC_CORE", "False" 193) 194 195# Environment variable to determine whether or not to enable coverage analysis 196# in Cython modules. 197ENABLE_CYTHON_TRACING = _env_bool_value( 198 "GRPC_PYTHON_ENABLE_CYTHON_TRACING", "False" 199) 200 201# Environment variable specifying whether or not there's interest in setting up 202# documentation building. 203ENABLE_DOCUMENTATION_BUILD = _env_bool_value( 204 "GRPC_PYTHON_ENABLE_DOCUMENTATION_BUILD", "False" 205) 206 207 208def check_linker_need_libatomic(): 209 """Test if linker on system needs libatomic.""" 210 code_test = ( 211 b"#include <atomic>\n" 212 + b"int main() { return std::atomic<int64_t>{}; }" 213 ) 214 cxx = shlex.split(os.environ.get("CXX", "c++")) 215 cpp_test = subprocess.Popen( 216 cxx + ["-x", "c++", "-std=c++14", "-"], 217 stdin=PIPE, 218 stdout=PIPE, 219 stderr=PIPE, 220 ) 221 cpp_test.communicate(input=code_test) 222 if cpp_test.returncode == 0: 223 return False 224 # Double-check to see if -latomic actually can solve the problem. 225 # https://github.com/grpc/grpc/issues/22491 226 cpp_test = subprocess.Popen( 227 cxx + ["-x", "c++", "-std=c++14", "-", "-latomic"], 228 stdin=PIPE, 229 stdout=PIPE, 230 stderr=PIPE, 231 ) 232 cpp_test.communicate(input=code_test) 233 return cpp_test.returncode == 0 234 235 236# There are some situations (like on Windows) where CC, CFLAGS, and LDFLAGS are 237# entirely ignored/dropped/forgotten by distutils and its Cygwin/MinGW support. 238# We use these environment variables to thus get around that without locking 239# ourselves in w.r.t. the multitude of operating systems this ought to build on. 240# We can also use these variables as a way to inject environment-specific 241# compiler/linker flags. We assume GCC-like compilers and/or MinGW as a 242# reasonable default. 243EXTRA_ENV_COMPILE_ARGS = os.environ.get("GRPC_PYTHON_CFLAGS", None) 244EXTRA_ENV_LINK_ARGS = os.environ.get("GRPC_PYTHON_LDFLAGS", None) 245if EXTRA_ENV_COMPILE_ARGS is None: 246 EXTRA_ENV_COMPILE_ARGS = "" 247 if "win32" in sys.platform: 248 # MSVC by defaults uses C++14 so C11 needs to be specified. 249 EXTRA_ENV_COMPILE_ARGS += " /std:c11" 250 # We need to statically link the C++ Runtime, only the C runtime is 251 # available dynamically 252 EXTRA_ENV_COMPILE_ARGS += " /MT" 253 elif "linux" in sys.platform: 254 # GCC by defaults uses C17 so only C++14 needs to be specified. 255 EXTRA_ENV_COMPILE_ARGS += " -std=c++14" 256 EXTRA_ENV_COMPILE_ARGS += ( 257 " -fvisibility=hidden -fno-wrapv -fno-exceptions" 258 ) 259 elif "darwin" in sys.platform: 260 # AppleClang by defaults uses C17 so only C++14 needs to be specified. 261 EXTRA_ENV_COMPILE_ARGS += " -std=c++14" 262 EXTRA_ENV_COMPILE_ARGS += ( 263 " -stdlib=libc++ -fvisibility=hidden -fno-wrapv -fno-exceptions" 264 " -DHAVE_UNISTD_H" 265 ) 266 267if EXTRA_ENV_LINK_ARGS is None: 268 EXTRA_ENV_LINK_ARGS = "" 269 if "linux" in sys.platform or "darwin" in sys.platform: 270 EXTRA_ENV_LINK_ARGS += " -lpthread" 271 if check_linker_need_libatomic(): 272 EXTRA_ENV_LINK_ARGS += " -latomic" 273 if "linux" in sys.platform: 274 EXTRA_ENV_LINK_ARGS += " -static-libgcc" 275 276# Explicitly link Core Foundation framework for MacOS to ensure no symbol is 277# missing when compiled using package managers like Conda. 278if "darwin" in sys.platform: 279 EXTRA_ENV_LINK_ARGS += " -framework CoreFoundation" 280 281EXTRA_COMPILE_ARGS = shlex.split(EXTRA_ENV_COMPILE_ARGS) 282EXTRA_LINK_ARGS = shlex.split(EXTRA_ENV_LINK_ARGS) 283 284if BUILD_WITH_STATIC_LIBSTDCXX: 285 EXTRA_LINK_ARGS.append("-static-libstdc++") 286 287CYTHON_EXTENSION_PACKAGE_NAMES = () 288 289CYTHON_EXTENSION_MODULE_NAMES = ("grpc._cython.cygrpc",) 290 291CYTHON_HELPER_C_FILES = () 292 293CORE_C_FILES = tuple(grpc_core_dependencies.CORE_SOURCE_FILES) 294if "win32" in sys.platform: 295 CORE_C_FILES = filter(lambda x: "third_party/cares" not in x, CORE_C_FILES) 296 297if BUILD_WITH_SYSTEM_OPENSSL: 298 CORE_C_FILES = filter( 299 lambda x: "third_party/boringssl" not in x, CORE_C_FILES 300 ) 301 CORE_C_FILES = filter(lambda x: "src/boringssl" not in x, CORE_C_FILES) 302 SSL_INCLUDE = (os.path.join("/usr", "include", "openssl"),) 303 304if BUILD_WITH_SYSTEM_ZLIB: 305 CORE_C_FILES = filter(lambda x: "third_party/zlib" not in x, CORE_C_FILES) 306 ZLIB_INCLUDE = (os.path.join("/usr", "include"),) 307 308if BUILD_WITH_SYSTEM_CARES: 309 CORE_C_FILES = filter(lambda x: "third_party/cares" not in x, CORE_C_FILES) 310 CARES_INCLUDE = (os.path.join("/usr", "include"),) 311 312if BUILD_WITH_SYSTEM_RE2: 313 CORE_C_FILES = filter(lambda x: "third_party/re2" not in x, CORE_C_FILES) 314 RE2_INCLUDE = (os.path.join("/usr", "include", "re2"),) 315 316if BUILD_WITH_SYSTEM_ABSL: 317 CORE_C_FILES = filter( 318 lambda x: "third_party/abseil-cpp" not in x, CORE_C_FILES 319 ) 320 ABSL_INCLUDE = (os.path.join("/usr", "include"),) 321 322EXTENSION_INCLUDE_DIRECTORIES = ( 323 (PYTHON_STEM,) 324 + CORE_INCLUDE 325 + ABSL_INCLUDE 326 + ADDRESS_SORTING_INCLUDE 327 + CARES_INCLUDE 328 + RE2_INCLUDE 329 + SSL_INCLUDE 330 + UPB_INCLUDE 331 + UPB_GRPC_GENERATED_INCLUDE 332 + UPBDEFS_GRPC_GENERATED_INCLUDE 333 + UTF8_RANGE_INCLUDE 334 + XXHASH_INCLUDE 335 + ZLIB_INCLUDE 336) 337 338EXTENSION_LIBRARIES = () 339if "linux" in sys.platform: 340 EXTENSION_LIBRARIES += ("rt",) 341if not "win32" in sys.platform: 342 EXTENSION_LIBRARIES += ("m",) 343if "win32" in sys.platform: 344 EXTENSION_LIBRARIES += ( 345 "advapi32", 346 "bcrypt", 347 "dbghelp", 348 "ws2_32", 349 ) 350if BUILD_WITH_SYSTEM_OPENSSL: 351 EXTENSION_LIBRARIES += ( 352 "ssl", 353 "crypto", 354 ) 355if BUILD_WITH_SYSTEM_ZLIB: 356 EXTENSION_LIBRARIES += ("z",) 357if BUILD_WITH_SYSTEM_CARES: 358 EXTENSION_LIBRARIES += ("cares",) 359if BUILD_WITH_SYSTEM_RE2: 360 EXTENSION_LIBRARIES += ("re2",) 361if BUILD_WITH_SYSTEM_ABSL: 362 EXTENSION_LIBRARIES += tuple( 363 lib.stem[3:] 364 for lib in sorted(pathlib.Path("/usr").glob("lib*/libabsl_*.so")) 365 ) 366 367DEFINE_MACROS = (("_WIN32_WINNT", 0x600),) 368asm_files = [] 369 370 371# Quotes on Windows build macros are evaluated differently from other platforms, 372# so we must apply quotes asymmetrically in order to yield the proper result in 373# the binary. 374def _quote_build_define(argument): 375 if "win32" in sys.platform: 376 return '"\\"{}\\""'.format(argument) 377 return '"{}"'.format(argument) 378 379 380DEFINE_MACROS += ( 381 ("GRPC_XDS_USER_AGENT_NAME_SUFFIX", _quote_build_define("Python")), 382 ( 383 "GRPC_XDS_USER_AGENT_VERSION_SUFFIX", 384 _quote_build_define(_metadata.__version__), 385 ), 386) 387 388asm_key = "" 389if BUILD_WITH_BORING_SSL_ASM and not BUILD_WITH_SYSTEM_OPENSSL: 390 boringssl_asm_platform = ( 391 BUILD_OVERRIDE_BORING_SSL_ASM_PLATFORM 392 if BUILD_OVERRIDE_BORING_SSL_ASM_PLATFORM 393 else sysconfig.get_platform() 394 ) 395 if "i686" in boringssl_asm_platform: 396 print("Enabling SSE2 on %s platform" % boringssl_asm_platform) 397 EXTRA_COMPILE_ARGS.append("-msse2") 398 else: 399 print("SSE2 not enabled on %s platform" % boringssl_asm_platform) 400 # BoringSSL's gas-compatible assembly files are all internally conditioned 401 # by the preprocessor. Provided the platform has a gas-compatible assembler 402 # (i.e. not Windows), we can include the assembly files and let BoringSSL 403 # decide which ones should and shouldn't be used for the build. 404 if not boringssl_asm_platform.startswith("win"): 405 asm_key = "crypto_asm" 406 else: 407 print( 408 "ASM Builds for BoringSSL currently not supported on:", 409 boringssl_asm_platform, 410 ) 411if asm_key: 412 asm_files = grpc_core_dependencies.ASM_SOURCE_FILES[asm_key] 413else: 414 DEFINE_MACROS += (("OPENSSL_NO_ASM", 1),) 415 416if "win32" in sys.platform: 417 # TODO(zyc): Re-enable c-ares on x64 and x86 windows after fixing the 418 # ares_library_init compilation issue 419 DEFINE_MACROS += ( 420 ("WIN32_LEAN_AND_MEAN", 1), 421 ("CARES_STATICLIB", 1), 422 ("GRPC_ARES", 0), 423 ("NTDDI_VERSION", 0x06000000), 424 ("NOMINMAX", 1), 425 ) 426 if "64bit" in platform.architecture()[0]: 427 DEFINE_MACROS += (("MS_WIN64", 1),) 428 elif sys.version_info >= (3, 5): 429 # For some reason, this is needed to get access to inet_pton/inet_ntop 430 # on msvc, but only for 32 bits 431 DEFINE_MACROS += (("NTDDI_VERSION", 0x06000000),) 432else: 433 DEFINE_MACROS += ( 434 ("HAVE_CONFIG_H", 1), 435 ("GRPC_ENABLE_FORK_SUPPORT", 1), 436 ) 437 438# Fix for multiprocessing support on Apple devices. 439# TODO(vigneshbabu): Remove this once the poll poller gets fork support. 440DEFINE_MACROS += (("GRPC_DO_NOT_INSTANTIATE_POSIX_POLLER", 1),) 441 442# Fix for Cython build issue in aarch64. 443# It's required to define this macro before include <inttypes.h>. 444# <inttypes.h> was included in core/lib/channel/call_tracer.h. 445# This macro should already be defined in grpc/grpc.h through port_platform.h, 446# but we're still having issue in aarch64, so we manually define the macro here. 447# TODO(xuanwn): Figure out what's going on in the aarch64 build so we can support 448# gcc + Bazel. 449DEFINE_MACROS += (("__STDC_FORMAT_MACROS", None),) 450 451LDFLAGS = tuple(EXTRA_LINK_ARGS) 452CFLAGS = tuple(EXTRA_COMPILE_ARGS) 453if "linux" in sys.platform or "darwin" in sys.platform: 454 pymodinit_type = "PyObject*" if PY3 else "void" 455 pymodinit = 'extern "C" __attribute__((visibility ("default"))) {}'.format( 456 pymodinit_type 457 ) 458 DEFINE_MACROS += (("PyMODINIT_FUNC", pymodinit),) 459 DEFINE_MACROS += (("GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK", 1),) 460 461 462def cython_extensions_and_necessity(): 463 cython_module_files = [ 464 os.path.join(PYTHON_STEM, name.replace(".", "/") + ".pyx") 465 for name in CYTHON_EXTENSION_MODULE_NAMES 466 ] 467 config = os.environ.get("CONFIG", "opt") 468 prefix = "libs/" + config + "/" 469 if USE_PREBUILT_GRPC_CORE: 470 extra_objects = [ 471 prefix + "libares.a", 472 prefix + "libboringssl.a", 473 prefix + "libgpr.a", 474 prefix + "libgrpc.a", 475 ] 476 core_c_files = [] 477 else: 478 core_c_files = list(CORE_C_FILES) 479 extra_objects = [] 480 extensions = [ 481 Extension( 482 name=module_name, 483 sources=( 484 [module_file] 485 + list(CYTHON_HELPER_C_FILES) 486 + core_c_files 487 + asm_files 488 ), 489 include_dirs=list(EXTENSION_INCLUDE_DIRECTORIES), 490 libraries=list(EXTENSION_LIBRARIES), 491 define_macros=list(DEFINE_MACROS), 492 extra_objects=extra_objects, 493 extra_compile_args=list(CFLAGS), 494 extra_link_args=list(LDFLAGS), 495 ) 496 for (module_name, module_file) in zip( 497 list(CYTHON_EXTENSION_MODULE_NAMES), cython_module_files 498 ) 499 ] 500 need_cython = BUILD_WITH_CYTHON 501 if not BUILD_WITH_CYTHON: 502 need_cython = ( 503 need_cython 504 or not commands.check_and_update_cythonization(extensions) 505 ) 506 # TODO: the strategy for conditional compiling and exposing the aio Cython 507 # dependencies will be revisited by https://github.com/grpc/grpc/issues/19728 508 return ( 509 commands.try_cythonize( 510 extensions, 511 linetracing=ENABLE_CYTHON_TRACING, 512 mandatory=BUILD_WITH_CYTHON, 513 ), 514 need_cython, 515 ) 516 517 518CYTHON_EXTENSION_MODULES, need_cython = cython_extensions_and_necessity() 519 520PACKAGE_DIRECTORIES = { 521 "": PYTHON_STEM, 522} 523 524INSTALL_REQUIRES = () 525 526EXTRAS_REQUIRES = { 527 "protobuf": "grpcio-tools>={version}".format(version=grpc_version.VERSION), 528} 529 530SETUP_REQUIRES = ( 531 INSTALL_REQUIRES + ("Sphinx~=1.8.1",) if ENABLE_DOCUMENTATION_BUILD else () 532) 533 534try: 535 import Cython 536except ImportError: 537 if BUILD_WITH_CYTHON: 538 sys.stderr.write( 539 "You requested a Cython build via GRPC_PYTHON_BUILD_WITH_CYTHON, " 540 "but do not have Cython installed. We won't stop you from using " 541 "other commands, but the extension files will fail to build.\n" 542 ) 543 elif need_cython: 544 sys.stderr.write( 545 "We could not find Cython. Setup may take 10-20 minutes.\n" 546 ) 547 SETUP_REQUIRES += ("cython>=3.0.0",) 548 549COMMAND_CLASS = { 550 "doc": commands.SphinxDocumentation, 551 "build_project_metadata": commands.BuildProjectMetadata, 552 "build_py": commands.BuildPy, 553 "build_ext": commands.BuildExt, 554 "gather": commands.Gather, 555 "clean": commands.Clean, 556} 557 558# Ensure that package data is copied over before any commands have been run: 559credentials_dir = os.path.join(PYTHON_STEM, "grpc", "_cython", "_credentials") 560try: 561 os.mkdir(credentials_dir) 562except OSError: 563 pass 564shutil.copyfile( 565 os.path.join("etc", "roots.pem"), os.path.join(credentials_dir, "roots.pem") 566) 567 568PACKAGE_DATA = { 569 # Binaries that may or may not be present in the final installation, but are 570 # mentioned here for completeness. 571 "grpc._cython": [ 572 "_credentials/roots.pem", 573 "_windows/grpc_c.32.python", 574 "_windows/grpc_c.64.python", 575 ], 576} 577PACKAGES = setuptools.find_packages(PYTHON_STEM) 578 579setuptools.setup( 580 name="grpcio", 581 version=grpc_version.VERSION, 582 description="HTTP/2-based RPC framework", 583 author="The gRPC Authors", 584 author_email="[email protected]", 585 url="https://grpc.io", 586 project_urls={ 587 "Source Code": "https://github.com/grpc/grpc", 588 "Bug Tracker": "https://github.com/grpc/grpc/issues", 589 "Documentation": "https://grpc.github.io/grpc/python", 590 }, 591 license=LICENSE, 592 classifiers=CLASSIFIERS, 593 long_description_content_type="text/x-rst", 594 long_description=open(README).read(), 595 ext_modules=CYTHON_EXTENSION_MODULES, 596 packages=list(PACKAGES), 597 package_dir=PACKAGE_DIRECTORIES, 598 package_data=PACKAGE_DATA, 599 python_requires=">=3.8", 600 install_requires=INSTALL_REQUIRES, 601 extras_require=EXTRAS_REQUIRES, 602 setup_requires=SETUP_REQUIRES, 603 cmdclass=COMMAND_CLASS, 604) 605