Merge pull request #7374 from kpayson64/python_health_check_rename
Polish grpcio_health_checking package
This commit is contained in:
commit
413d302d4b
|
|
@ -119,7 +119,7 @@
|
|||
// libraries; it should be integrated with the `__linux__` definitions below.
|
||||
#define GPR_PLATFORM_STRING "manylinux"
|
||||
#define GPR_POSIX_CRASH_HANDLER 1
|
||||
#define GPR_CPU_LINUX 1
|
||||
#define GPR_CPU_POSIX 1
|
||||
#define GPR_GCC_ATOMIC 1
|
||||
#define GPR_GCC_TLS 1
|
||||
#define GPR_LINUX 1
|
||||
|
|
|
|||
|
|
@ -9,5 +9,5 @@ build_base=python_build
|
|||
[build_ext]
|
||||
inplace=1
|
||||
|
||||
[build_proto_modules]
|
||||
[build_package_protos]
|
||||
exclude=.*protoc_plugin/protoc_plugin_test\.proto$
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
include grpc_version.py
|
||||
include health_commands.py
|
||||
graft grpc_health
|
||||
graft grpc
|
||||
global-exclude *.pyc
|
||||
|
|
|
|||
|
|
@ -27,4 +27,4 @@
|
|||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
__import__('pkg_resources').declare_namespace(__name__)
|
||||
|
|
@ -31,10 +31,12 @@
|
|||
|
||||
import threading
|
||||
|
||||
from grpc_health.health.v1 import health_pb2
|
||||
import grpc
|
||||
|
||||
from grpc.health.v1 import health_pb2
|
||||
|
||||
|
||||
class HealthServicer(health_pb2.BetaHealthServicer):
|
||||
class HealthServicer(health_pb2.HealthServicer):
|
||||
"""Servicer handling RPCs for service statuses."""
|
||||
|
||||
def __init__(self):
|
||||
|
|
@ -43,14 +45,12 @@ class HealthServicer(health_pb2.BetaHealthServicer):
|
|||
|
||||
def Check(self, request, context):
|
||||
with self._server_status_lock:
|
||||
if request.service not in self._server_status:
|
||||
# TODO(atash): once the Python API has a way of setting the server
|
||||
# status, bring us into conformance with the health check spec by
|
||||
# returning the NOT_FOUND status here.
|
||||
raise NotImplementedError()
|
||||
status = self._server_status.get(request.service)
|
||||
if status is None:
|
||||
context.set_code(grpc.StatusCode.NOT_FOUND)
|
||||
return health_pb2.HealthCheckResponse()
|
||||
else:
|
||||
return health_pb2.HealthCheckResponse(
|
||||
status=self._server_status[request.service])
|
||||
return health_pb2.HealthCheckResponse(status=status)
|
||||
|
||||
def set(self, service, status):
|
||||
"""Sets the status of a service.
|
||||
|
|
@ -63,4 +63,3 @@ class HealthServicer(health_pb2.BetaHealthServicer):
|
|||
"""
|
||||
with self._server_status_lock:
|
||||
self._server_status[service] = status
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
# Copyright 2016, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!!
|
||||
|
||||
VERSION='1.0.0rc1'
|
||||
|
|
@ -29,16 +29,10 @@
|
|||
|
||||
"""Provides distutils command classes for the GRPC Python setup process."""
|
||||
|
||||
import distutils
|
||||
import glob
|
||||
import os
|
||||
import os.path
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import setuptools
|
||||
from setuptools.command import build_py
|
||||
|
||||
ROOT_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__)))
|
||||
HEALTH_PROTO = os.path.join(ROOT_DIR, '../../proto/grpc/health/v1/health.proto')
|
||||
|
|
@ -60,12 +54,25 @@ class CopyProtoModules(setuptools.Command):
|
|||
if os.path.isfile(HEALTH_PROTO):
|
||||
shutil.copyfile(
|
||||
HEALTH_PROTO,
|
||||
os.path.join(ROOT_DIR, 'grpc_health/health/v1/health.proto'))
|
||||
os.path.join(ROOT_DIR, 'grpc/health/v1/health.proto'))
|
||||
|
||||
|
||||
class BuildPy(build_py.build_py):
|
||||
"""Custom project build command."""
|
||||
class BuildPackageProtos(setuptools.Command):
|
||||
"""Command to generate project *_pb2.py modules from proto files."""
|
||||
|
||||
description = 'build grpc protobuf modules'
|
||||
user_options = []
|
||||
|
||||
def initialize_options(self):
|
||||
pass
|
||||
|
||||
def finalize_options(self):
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
self.run_command('build_proto_modules')
|
||||
build_py.build_py.run(self)
|
||||
# due to limitations of the proto generator, we require that only *one*
|
||||
# directory is provided as an 'include' directory. We assume it's the '' key
|
||||
# to `self.distribution.package_dir` (and get a key error if it's not
|
||||
# there).
|
||||
from grpc.tools import command
|
||||
command.build_package_protos(self.distribution.package_dir[''])
|
||||
|
|
|
|||
|
|
@ -30,49 +30,42 @@
|
|||
"""Setup module for the GRPC Python package's optional health checking."""
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
from distutils import core as _core
|
||||
import setuptools
|
||||
|
||||
import grpc.tools.command
|
||||
|
||||
# Ensure we're in the proper directory whether or not we're being used by pip.
|
||||
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
# Break import-style to ensure we can actually find our commands module.
|
||||
import health_commands
|
||||
|
||||
PACKAGES = (
|
||||
setuptools.find_packages('.')
|
||||
)
|
||||
import grpc_version
|
||||
|
||||
PACKAGE_DIRECTORIES = {
|
||||
'': '.',
|
||||
}
|
||||
|
||||
SETUP_REQUIRES = (
|
||||
'grpcio-tools>=0.14.0',
|
||||
'grpcio-tools>=0.15.0',
|
||||
)
|
||||
|
||||
INSTALL_REQUIRES = (
|
||||
'grpcio>=0.13.1',
|
||||
'grpcio>=0.15.0',
|
||||
)
|
||||
|
||||
COMMAND_CLASS = {
|
||||
# Run preprocess from the repository *before* doing any packaging!
|
||||
'preprocess': health_commands.CopyProtoModules,
|
||||
|
||||
'build_proto_modules': grpc.tools.command.BuildProtoModules,
|
||||
'build_py': health_commands.BuildPy,
|
||||
'build_package_protos': health_commands.BuildPackageProtos,
|
||||
}
|
||||
|
||||
setuptools.setup(
|
||||
name='grpcio-health-checking',
|
||||
version='0.14.0',
|
||||
packages=list(PACKAGES),
|
||||
version=grpc_version.VERSION,
|
||||
license='3-clause BSD',
|
||||
package_dir=PACKAGE_DIRECTORIES,
|
||||
packages=setuptools.find_packages('.'),
|
||||
namespace_packages=['grpc'],
|
||||
install_requires=INSTALL_REQUIRES,
|
||||
setup_requires=SETUP_REQUIRES,
|
||||
cmdclass=COMMAND_CLASS
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ class BuildPy(build_py.build_py):
|
|||
|
||||
def run(self):
|
||||
try:
|
||||
self.run_command('build_proto_modules')
|
||||
self.run_command('build_package_protos')
|
||||
except CommandError as error:
|
||||
sys.stderr.write('warning: %s\n' % error.message)
|
||||
build_py.build_py.run(self)
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ COMMAND_CLASS = {
|
|||
# Run `preprocess` *before* doing any packaging!
|
||||
'preprocess': commands.GatherProto,
|
||||
|
||||
'build_proto_modules': grpc.tools.command.BuildProtoModules,
|
||||
'build_package_protos': grpc.tools.command.BuildPackageProtos,
|
||||
'build_py': commands.BuildPy,
|
||||
'run_interop': commands.RunInterop,
|
||||
'test_lite': commands.TestLite
|
||||
|
|
|
|||
|
|
@ -27,48 +27,68 @@
|
|||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"""Tests of grpc_health.health.v1.health."""
|
||||
"""Tests of grpc.health.v1.health."""
|
||||
|
||||
import unittest
|
||||
|
||||
from grpc_health.health.v1 import health
|
||||
from grpc_health.health.v1 import health_pb2
|
||||
import grpc
|
||||
from grpc.framework.foundation import logging_pool
|
||||
from grpc.health.v1 import health
|
||||
from grpc.health.v1 import health_pb2
|
||||
|
||||
from tests.unit.framework.common import test_constants
|
||||
|
||||
|
||||
class HealthServicerTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.servicer = health.HealthServicer()
|
||||
self.servicer.set('', health_pb2.HealthCheckResponse.SERVING)
|
||||
self.servicer.set('grpc.test.TestServiceServing',
|
||||
health_pb2.HealthCheckResponse.SERVING)
|
||||
self.servicer.set('grpc.test.TestServiceUnknown',
|
||||
health_pb2.HealthCheckResponse.UNKNOWN)
|
||||
self.servicer.set('grpc.test.TestServiceNotServing',
|
||||
health_pb2.HealthCheckResponse.NOT_SERVING)
|
||||
servicer = health.HealthServicer()
|
||||
servicer.set('', health_pb2.HealthCheckResponse.SERVING)
|
||||
servicer.set('grpc.test.TestServiceServing',
|
||||
health_pb2.HealthCheckResponse.SERVING)
|
||||
servicer.set('grpc.test.TestServiceUnknown',
|
||||
health_pb2.HealthCheckResponse.UNKNOWN)
|
||||
servicer.set('grpc.test.TestServiceNotServing',
|
||||
health_pb2.HealthCheckResponse.NOT_SERVING)
|
||||
server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY)
|
||||
self._server = grpc.server(server_pool)
|
||||
port = self._server.add_insecure_port('[::]:0')
|
||||
health_pb2.add_HealthServicer_to_server(servicer, self._server)
|
||||
self._server.start()
|
||||
|
||||
channel = grpc.insecure_channel('localhost:%d' % port)
|
||||
self._stub = health_pb2.HealthStub(channel)
|
||||
|
||||
def test_empty_service(self):
|
||||
request = health_pb2.HealthCheckRequest()
|
||||
resp = self.servicer.Check(request, None)
|
||||
self.assertEqual(resp.status, health_pb2.HealthCheckResponse.SERVING)
|
||||
resp = self._stub.Check(request)
|
||||
self.assertEqual(health_pb2.HealthCheckResponse.SERVING, resp.status)
|
||||
|
||||
def test_serving_service(self):
|
||||
request = health_pb2.HealthCheckRequest(
|
||||
service='grpc.test.TestServiceServing')
|
||||
resp = self.servicer.Check(request, None)
|
||||
self.assertEqual(resp.status, health_pb2.HealthCheckResponse.SERVING)
|
||||
resp = self._stub.Check(request)
|
||||
self.assertEqual(health_pb2.HealthCheckResponse.SERVING, resp.status)
|
||||
|
||||
def test_unknown_serivce(self):
|
||||
request = health_pb2.HealthCheckRequest(
|
||||
service='grpc.test.TestServiceUnknown')
|
||||
resp = self.servicer.Check(request, None)
|
||||
self.assertEqual(resp.status, health_pb2.HealthCheckResponse.UNKNOWN)
|
||||
resp = self._stub.Check(request)
|
||||
self.assertEqual(health_pb2.HealthCheckResponse.UNKNOWN, resp.status)
|
||||
|
||||
def test_not_serving_service(self):
|
||||
request = health_pb2.HealthCheckRequest(
|
||||
service='grpc.test.TestServiceNotServing')
|
||||
resp = self.servicer.Check(request, None)
|
||||
self.assertEqual(resp.status, health_pb2.HealthCheckResponse.NOT_SERVING)
|
||||
resp = self._stub.Check(request)
|
||||
self.assertEqual(health_pb2.HealthCheckResponse.NOT_SERVING, resp.status)
|
||||
|
||||
def test_not_found_service(self):
|
||||
request = health_pb2.HealthCheckRequest(
|
||||
service='not-found')
|
||||
with self.assertRaises(grpc.RpcError) as context:
|
||||
resp = self._stub.Check(request)
|
||||
|
||||
self.assertEqual(grpc.StatusCode.NOT_FOUND, context.exception.code())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
%YAML 1.2
|
||||
--- |
|
||||
# Copyright 2016, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!!
|
||||
|
||||
VERSION='${settings.python_version.pep440()}'
|
||||
|
|
@ -35,7 +35,26 @@ import setuptools
|
|||
from grpc.tools import protoc
|
||||
|
||||
|
||||
class BuildProtoModules(setuptools.Command):
|
||||
def build_package_protos(package_root):
|
||||
proto_files = []
|
||||
inclusion_root = os.path.abspath(package_root)
|
||||
for root, _, files in os.walk(inclusion_root):
|
||||
for filename in files:
|
||||
if filename.endswith('.proto'):
|
||||
proto_files.append(os.path.abspath(os.path.join(root, filename)))
|
||||
|
||||
for proto_file in proto_files:
|
||||
command = [
|
||||
'grpc.tools.protoc',
|
||||
'--proto_path={}'.format(inclusion_root),
|
||||
'--python_out={}'.format(inclusion_root),
|
||||
'--grpc_python_out={}'.format(inclusion_root),
|
||||
] + [proto_file]
|
||||
if protoc.main(command) != 0:
|
||||
sys.stderr.write('warning: {} failed'.format(command))
|
||||
|
||||
|
||||
class BuildPackageProtos(setuptools.Command):
|
||||
"""Command to generate project *_pb2.py modules from proto files."""
|
||||
|
||||
description = 'build grpc protobuf modules'
|
||||
|
|
@ -52,19 +71,4 @@ class BuildProtoModules(setuptools.Command):
|
|||
# directory is provided as an 'include' directory. We assume it's the '' key
|
||||
# to `self.distribution.package_dir` (and get a key error if it's not
|
||||
# there).
|
||||
proto_files = []
|
||||
inclusion_root = os.path.abspath(self.distribution.package_dir[''])
|
||||
for root, _, files in os.walk(inclusion_root):
|
||||
for filename in files:
|
||||
if filename.endswith('.proto'):
|
||||
proto_files.append(os.path.abspath(os.path.join(root, filename)))
|
||||
|
||||
for proto_file in proto_files:
|
||||
command = [
|
||||
'grpc.tools.protoc',
|
||||
'--proto_path={}'.format(inclusion_root),
|
||||
'--python_out={}'.format(inclusion_root),
|
||||
'--grpc_python_out={}'.format(inclusion_root),
|
||||
] + [proto_file]
|
||||
if protoc.main(command) != 0:
|
||||
sys.stderr.write('warning: {} failed'.format(command))
|
||||
build_package_protos(self.distribution.package_dir[''])
|
||||
|
|
|
|||
|
|
@ -113,12 +113,12 @@ class PythonArtifact:
|
|||
# special places...
|
||||
environ['PYTHON'] = '/opt/python/{}/bin/python'.format(self.manylinux_build)
|
||||
environ['PIP'] = '/opt/python/{}/bin/pip'.format(self.manylinux_build)
|
||||
environ['SKIP_PIP_INSTALL'] = '1'
|
||||
# Platform autodetection for the manylinux1 image breaks so we set the
|
||||
# defines ourselves.
|
||||
# TODO(atash) get better platform-detection support in core so we don't
|
||||
# need to do this manually...
|
||||
environ['CFLAGS'] = '-DGPR_MANYLINUX1=1'
|
||||
environ['BUILD_HEALTH_CHECKING'] = 'TRUE'
|
||||
return create_docker_jobspec(self.name,
|
||||
'tools/dockerfile/grpc_artifact_python_manylinux_%s' % self.arch,
|
||||
'tools/run_tests/build_artifact_python.sh',
|
||||
|
|
@ -132,7 +132,6 @@ class PythonArtifact:
|
|||
],
|
||||
shell=True)
|
||||
else:
|
||||
environ['SKIP_PIP_INSTALL'] = 'TRUE'
|
||||
environ['PYTHON'] = 'python{}'.format(self.python_version)
|
||||
return create_jobspec(self.name,
|
||||
['tools/run_tests/build_artifact_python.sh'],
|
||||
|
|
|
|||
|
|
@ -39,15 +39,6 @@ export PIP=${PIP:-pip}
|
|||
export AUDITWHEEL=${AUDITWHEEL:-auditwheel}
|
||||
|
||||
|
||||
if [ "$SKIP_PIP_INSTALL" == "" ]
|
||||
then
|
||||
${PIP} install --upgrade six
|
||||
# There's a bug in newer versions of setuptools (see
|
||||
# https://bitbucket.org/pypa/setuptools/issues/503/pkg_resources_vendorpackagingrequirementsi)
|
||||
${PIP} pip install --upgrade 'setuptools==18'
|
||||
${PIP} install -rrequirements.txt
|
||||
fi
|
||||
|
||||
# Build the source distribution first because MANIFEST.in cannot override
|
||||
# exclusion of built shared objects among package resources (for some
|
||||
# inexplicable reason).
|
||||
|
|
@ -81,5 +72,21 @@ then
|
|||
done
|
||||
fi
|
||||
|
||||
# We need to use the built grpcio-tools/grpcio to compile the health proto
|
||||
# Wheels are not supported by setup_requires/dependency_links, so we
|
||||
# manually install the dependency. Note we should only do this if we
|
||||
# are in a docker image or in a virtualenv.
|
||||
if [ "$BUILD_HEALTH_CHECKING" != "" ]
|
||||
then
|
||||
${PIP} install -rrequirements.txt
|
||||
${PIP} install grpcio --no-index --find-links "file://${PWD}/artifacts/"
|
||||
${PIP} install grpcio-tools --no-index --find-links "file://${PWD}/artifacts/"
|
||||
|
||||
# Build gRPC health check source distribution
|
||||
${SETARCH_CMD} ${PYTHON} src/python/grpcio_health_checking/setup.py \
|
||||
preprocess build_package_protos sdist
|
||||
cp -r src/python/grpcio_health_checking/dist/* artifacts
|
||||
fi
|
||||
|
||||
cp -r dist/* artifacts
|
||||
cp -r tools/distrib/python/grpcio_tools/dist/* artifacts
|
||||
|
|
|
|||
|
|
@ -177,7 +177,8 @@ pip_install_dir $ROOT/tools/distrib/python/grpcio_tools
|
|||
# etc...
|
||||
pip_install_dir $ROOT
|
||||
$VENV_PYTHON $ROOT/src/python/grpcio_health_checking/setup.py preprocess
|
||||
$VENV_PYTHON $ROOT/src/python/grpcio_health_checking/setup.py build_package_protos
|
||||
pip_install_dir $ROOT/src/python/grpcio_health_checking
|
||||
$VENV_PYTHON $ROOT/src/python/grpcio_tests/setup.py preprocess
|
||||
$VENV_PYTHON $ROOT/src/python/grpcio_tests/setup.py build_proto_modules
|
||||
$VENV_PYTHON $ROOT/src/python/grpcio_tests/setup.py build_package_protos
|
||||
pip_install_dir $ROOT/src/python/grpcio_tests
|
||||
|
|
|
|||
Loading…
Reference in New Issue