mirror of https://github.com/apache/flink.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
197 lines
9.1 KiB
Python
197 lines
9.1 KiB
Python
################################################################################
|
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
# or more contributor license agreements. See the NOTICE file
|
|
# distributed with this work for additional information
|
|
# regarding copyright ownership. The ASF licenses this file
|
|
# to you under the Apache License, Version 2.0 (the
|
|
# "License"); you may not use this file except in compliance
|
|
# with the License. You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
################################################################################
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import print_function
|
|
|
|
import glob
|
|
import logging
|
|
import multiprocessing
|
|
import os
|
|
import platform
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
import warnings
|
|
|
|
import pkg_resources
|
|
|
|
GRPC_TOOLS = 'grpcio-tools>=1.29.0,<=1.50.0'
|
|
PROTO_PATHS = ['proto']
|
|
PYFLINK_ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
|
|
DEFAULT_PYTHON_OUTPUT_PATH = os.path.join(PYFLINK_ROOT_PATH, 'fn_execution')
|
|
|
|
|
|
def generate_proto_files(force=True, output_dir=DEFAULT_PYTHON_OUTPUT_PATH):
|
|
try:
|
|
import grpc_tools # noqa # pylint: disable=unused-import
|
|
except ImportError:
|
|
warnings.warn('Installing grpcio-tools is recommended for development.')
|
|
|
|
proto_dirs = [os.path.join(PYFLINK_ROOT_PATH, path) for path in PROTO_PATHS]
|
|
proto_files = sum(
|
|
[glob.glob(os.path.join(d, '*.proto')) for d in proto_dirs], [])
|
|
out_dir = os.path.join(PYFLINK_ROOT_PATH, output_dir)
|
|
out_files = [path for path in glob.glob(os.path.join(out_dir, '*_pb2.py*'))]
|
|
|
|
if out_files and not proto_files and not force:
|
|
# We have out_files but no protos; assume they're up to date.
|
|
# This is actually the common case (e.g. installation from an sdist).
|
|
logging.info('No proto files; using existing generated files.')
|
|
return
|
|
|
|
elif not out_files and not proto_files:
|
|
raise RuntimeError(
|
|
'No proto files found in %s.' % proto_dirs)
|
|
|
|
# Regenerate iff the proto files or this file are newer.
|
|
elif force or not out_files or len(out_files) < len(proto_files) or (
|
|
min(os.path.getmtime(path) for path in out_files)
|
|
<= max(os.path.getmtime(path)
|
|
for path in proto_files + [os.path.realpath(__file__)])):
|
|
try:
|
|
from grpc_tools import protoc
|
|
except ImportError:
|
|
if platform.system() == 'Windows':
|
|
# For Windows, grpcio-tools has to be installed manually.
|
|
raise RuntimeError(
|
|
'Cannot generate protos for Windows since grpcio-tools package is '
|
|
'not installed. Please install this package manually '
|
|
'using \'pip install "grpcio-tools>=1.29.0,<=1.50.0"\'.')
|
|
|
|
# Use a subprocess to avoid messing with this process' path and imports.
|
|
# Note that this requires a separate module from setup.py for Windows:
|
|
# https://docs.python.org/2/library/multiprocessing.html#windows
|
|
p = multiprocessing.Process(
|
|
target=_install_grpcio_tools_and_generate_proto_files(force, output_dir))
|
|
p.start()
|
|
p.join()
|
|
if p.exitcode:
|
|
raise ValueError("Proto generation failed (see log for details).")
|
|
else:
|
|
_check_grpcio_tools_version()
|
|
logging.info('Regenerating out-of-date Python proto definitions.')
|
|
builtin_protos = pkg_resources.resource_filename('grpc_tools', '_proto')
|
|
args = (
|
|
[sys.executable] + # expecting to be called from command line
|
|
['--proto_path=%s' % builtin_protos] +
|
|
['--proto_path=%s' % d for d in proto_dirs] +
|
|
['--python_out=%s' % out_dir] +
|
|
['--pyi_out=%s' % out_dir] +
|
|
proto_files)
|
|
ret_code = protoc.main(args)
|
|
if ret_code:
|
|
raise RuntimeError(
|
|
'Protoc returned non-zero status (see logs for details): '
|
|
'%s' % ret_code)
|
|
|
|
for output_file in os.listdir(output_dir):
|
|
if output_file.endswith('_pb2.py') or output_file.endswith('_pb2.pyi'):
|
|
_add_license_header(output_dir, output_file)
|
|
|
|
|
|
# Though wheels are available for grpcio-tools, setup_requires uses
|
|
# easy_install which doesn't understand them. This means that it is
|
|
# compiled from scratch (which is expensive as it compiles the full
|
|
# protoc compiler). Instead, we attempt to install a wheel in a temporary
|
|
# directory and add it to the path as needed.
|
|
# See https://github.com/pypa/setuptools/issues/377
|
|
def _install_grpcio_tools_and_generate_proto_files(force, output_dir):
|
|
install_path = os.path.join(PYFLINK_ROOT_PATH, '..', '.eggs', 'grpcio-wheels')
|
|
build_path = install_path + '-build'
|
|
if os.path.exists(build_path):
|
|
shutil.rmtree(build_path)
|
|
logging.warning('Installing grpcio-tools into %s', install_path)
|
|
try:
|
|
start = time.time()
|
|
# since '--prefix' option is only supported for pip 8.0+, so here we fallback to
|
|
# use '--install-option' when the pip version is lower than 8.0.0.
|
|
pip_version = pkg_resources.get_distribution("pip").version
|
|
from pkg_resources import parse_version
|
|
if parse_version(pip_version) >= parse_version('8.0.0'):
|
|
subprocess.check_call(
|
|
[sys.executable, '-m', 'pip', 'install',
|
|
'--prefix', install_path, '--build', build_path,
|
|
'--upgrade', GRPC_TOOLS, "-I"])
|
|
else:
|
|
subprocess.check_call(
|
|
[sys.executable, '-m', 'pip', 'install',
|
|
'--install-option', '--prefix=' + install_path, '--build', build_path,
|
|
'--upgrade', GRPC_TOOLS, "-I"])
|
|
from distutils.dist import Distribution
|
|
install_obj = Distribution().get_command_obj('install', create=True)
|
|
install_obj.prefix = install_path
|
|
install_obj.finalize_options()
|
|
logging.warning(
|
|
'Installing grpcio-tools took %0.2f seconds.', time.time() - start)
|
|
finally:
|
|
sys.stderr.flush()
|
|
shutil.rmtree(build_path, ignore_errors=True)
|
|
sys.path.append(install_obj.install_purelib)
|
|
pkg_resources.working_set.add_entry(install_obj.install_purelib)
|
|
if install_obj.install_purelib != install_obj.install_platlib:
|
|
sys.path.append(install_obj.install_platlib)
|
|
pkg_resources.working_set.add_entry(install_obj.install_platlib)
|
|
try:
|
|
generate_proto_files(force, output_dir)
|
|
finally:
|
|
sys.stderr.flush()
|
|
|
|
|
|
def _add_license_header(dir, file_name):
|
|
with open(os.path.join(dir, file_name), 'r') as original_file:
|
|
original_data = original_file.read()
|
|
tmp_file_name = file_name + '.tmp'
|
|
with open(os.path.join(dir, tmp_file_name), 'w') as tmp_file:
|
|
tmp_file.write(
|
|
'################################################################################\n'
|
|
'# Licensed to the Apache Software Foundation (ASF) under one\n'
|
|
'# or more contributor license agreements. See the NOTICE file\n'
|
|
'# distributed with this work for additional information\n'
|
|
'# regarding copyright ownership. The ASF licenses this file\n'
|
|
'# to you under the Apache License, Version 2.0 (the\n'
|
|
'# "License"); you may not use this file except in compliance\n'
|
|
'# with the License. You may obtain a copy of the License at\n'
|
|
'#\n'
|
|
'# http://www.apache.org/licenses/LICENSE-2.0\n'
|
|
'#\n'
|
|
'# Unless required by applicable law or agreed to in writing, software\n'
|
|
'# distributed under the License is distributed on an "AS IS" BASIS,\n'
|
|
'# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n'
|
|
'# See the License for the specific language governing permissions and\n'
|
|
'# limitations under the License.\n'
|
|
'################################################################################\n'
|
|
)
|
|
tmp_file.write(original_data)
|
|
if os.path.exists(os.path.join(dir, file_name)):
|
|
os.remove(os.path.join(dir, file_name))
|
|
os.rename(os.path.join(dir, tmp_file_name), os.path.join(dir, file_name))
|
|
|
|
|
|
def _check_grpcio_tools_version():
|
|
version = pkg_resources.get_distribution("grpcio-tools").parsed_version
|
|
from pkg_resources import parse_version
|
|
if version < parse_version('1.29.0') or version > parse_version('1.50.0'):
|
|
raise RuntimeError(
|
|
"Version of grpcio-tools must be between 1.29.0 and 1.50.0, got %s" % version)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
generate_proto_files()
|