1#! /usr/bin/env python 2# 3# See README for usage instructions. 4import glob 5import os 6import subprocess 7import sys 8 9# We must use setuptools, not distutils, because we need to use the 10# namespace_packages option for the "google" package. 11from setuptools import setup, Extension, find_packages 12 13from distutils.command.clean import clean as _clean 14 15if sys.version_info[0] == 3: 16 # Python 3 17 from distutils.command.build_py import build_py_2to3 as _build_py 18else: 19 # Python 2 20 from distutils.command.build_py import build_py as _build_py 21from distutils.spawn import find_executable 22 23# Find the Protocol Compiler. 24if 'PROTOC' in os.environ and os.path.exists(os.environ['PROTOC']): 25 protoc = os.environ['PROTOC'] 26elif os.path.exists("../src/protoc"): 27 protoc = "../src/protoc" 28elif os.path.exists("../src/protoc.exe"): 29 protoc = "../src/protoc.exe" 30elif os.path.exists("../vsprojects/Debug/protoc.exe"): 31 protoc = "../vsprojects/Debug/protoc.exe" 32elif os.path.exists("../vsprojects/Release/protoc.exe"): 33 protoc = "../vsprojects/Release/protoc.exe" 34else: 35 protoc = find_executable("protoc") 36 37 38def GetVersion(): 39 """Gets the version from google/protobuf/__init__.py 40 41 Do not import google.protobuf.__init__ directly, because an installed 42 protobuf library may be loaded instead.""" 43 44 with open(os.path.join('google', 'protobuf', '__init__.py')) as version_file: 45 exec(version_file.read(), globals()) 46 return __version__ 47 48 49def generate_proto(source, require = True): 50 """Invokes the Protocol Compiler to generate a _pb2.py from the given 51 .proto file. Does nothing if the output already exists and is newer than 52 the input.""" 53 54 if not require and not os.path.exists(source): 55 return 56 57 output = source.replace(".proto", "_pb2.py").replace("../src/", "") 58 59 if (not os.path.exists(output) or 60 (os.path.exists(source) and 61 os.path.getmtime(source) > os.path.getmtime(output))): 62 print("Generating %s..." % output) 63 64 if not os.path.exists(source): 65 sys.stderr.write("Can't find required file: %s\n" % source) 66 sys.exit(-1) 67 68 if protoc is None: 69 sys.stderr.write( 70 "protoc is not installed nor found in ../src. Please compile it " 71 "or install the binary package.\n") 72 sys.exit(-1) 73 74 protoc_command = [ protoc, "-I../src", "-I.", "--python_out=.", source ] 75 if subprocess.call(protoc_command) != 0: 76 sys.exit(-1) 77 78def GenerateUnittestProtos(): 79 generate_proto("../src/google/protobuf/any_test.proto", False) 80 generate_proto("../src/google/protobuf/map_unittest.proto", False) 81 generate_proto("../src/google/protobuf/unittest_arena.proto", False) 82 generate_proto("../src/google/protobuf/unittest_no_arena.proto", False) 83 generate_proto("../src/google/protobuf/unittest_no_arena_import.proto", False) 84 generate_proto("../src/google/protobuf/unittest.proto", False) 85 generate_proto("../src/google/protobuf/unittest_custom_options.proto", False) 86 generate_proto("../src/google/protobuf/unittest_import.proto", False) 87 generate_proto("../src/google/protobuf/unittest_import_public.proto", False) 88 generate_proto("../src/google/protobuf/unittest_mset.proto", False) 89 generate_proto("../src/google/protobuf/unittest_mset_wire_format.proto", False) 90 generate_proto("../src/google/protobuf/unittest_no_generic_services.proto", False) 91 generate_proto("../src/google/protobuf/unittest_proto3_arena.proto", False) 92 generate_proto("../src/google/protobuf/util/json_format_proto3.proto", False) 93 generate_proto("google/protobuf/internal/any_test.proto", False) 94 generate_proto("google/protobuf/internal/descriptor_pool_test1.proto", False) 95 generate_proto("google/protobuf/internal/descriptor_pool_test2.proto", False) 96 generate_proto("google/protobuf/internal/factory_test1.proto", False) 97 generate_proto("google/protobuf/internal/factory_test2.proto", False) 98 generate_proto("google/protobuf/internal/file_options_test.proto", False) 99 generate_proto("google/protobuf/internal/import_test_package/inner.proto", False) 100 generate_proto("google/protobuf/internal/import_test_package/outer.proto", False) 101 generate_proto("google/protobuf/internal/missing_enum_values.proto", False) 102 generate_proto("google/protobuf/internal/message_set_extensions.proto", False) 103 generate_proto("google/protobuf/internal/more_extensions.proto", False) 104 generate_proto("google/protobuf/internal/more_extensions_dynamic.proto", False) 105 generate_proto("google/protobuf/internal/more_messages.proto", False) 106 generate_proto("google/protobuf/internal/packed_field_test.proto", False) 107 generate_proto("google/protobuf/internal/test_bad_identifiers.proto", False) 108 generate_proto("google/protobuf/pyext/python.proto", False) 109 110 111class clean(_clean): 112 def run(self): 113 # Delete generated files in the code tree. 114 for (dirpath, dirnames, filenames) in os.walk("."): 115 for filename in filenames: 116 filepath = os.path.join(dirpath, filename) 117 if filepath.endswith("_pb2.py") or filepath.endswith(".pyc") or \ 118 filepath.endswith(".so") or filepath.endswith(".o") or \ 119 filepath.endswith('google/protobuf/compiler/__init__.py') or \ 120 filepath.endswith('google/protobuf/util/__init__.py'): 121 os.remove(filepath) 122 # _clean is an old-style class, so super() doesn't work. 123 _clean.run(self) 124 125class build_py(_build_py): 126 def run(self): 127 # Generate necessary .proto file if it doesn't exist. 128 generate_proto("../src/google/protobuf/descriptor.proto") 129 generate_proto("../src/google/protobuf/compiler/plugin.proto") 130 generate_proto("../src/google/protobuf/any.proto") 131 generate_proto("../src/google/protobuf/api.proto") 132 generate_proto("../src/google/protobuf/duration.proto") 133 generate_proto("../src/google/protobuf/empty.proto") 134 generate_proto("../src/google/protobuf/field_mask.proto") 135 generate_proto("../src/google/protobuf/source_context.proto") 136 generate_proto("../src/google/protobuf/struct.proto") 137 generate_proto("../src/google/protobuf/timestamp.proto") 138 generate_proto("../src/google/protobuf/type.proto") 139 generate_proto("../src/google/protobuf/wrappers.proto") 140 GenerateUnittestProtos() 141 142 # Make sure google.protobuf/** are valid packages. 143 for path in ['', 'internal/', 'compiler/', 'pyext/', 'util/']: 144 try: 145 open('google/protobuf/%s__init__.py' % path, 'a').close() 146 except EnvironmentError: 147 pass 148 # _build_py is an old-style class, so super() doesn't work. 149 _build_py.run(self) 150 151class test_conformance(_build_py): 152 target = 'test_python' 153 def run(self): 154 if sys.version_info >= (2, 7): 155 # Python 2.6 dodges these extra failures. 156 os.environ["CONFORMANCE_PYTHON_EXTRA_FAILURES"] = ( 157 "--failure_list failure_list_python-post26.txt") 158 cmd = 'cd ../conformance && make %s' % (test_conformance.target) 159 status = subprocess.check_call(cmd, shell=True) 160 161 162def get_option_from_sys_argv(option_str): 163 if option_str in sys.argv: 164 sys.argv.remove(option_str) 165 return True 166 return False 167 168 169if __name__ == '__main__': 170 ext_module_list = [] 171 warnings_as_errors = '--warnings_as_errors' 172 if get_option_from_sys_argv('--cpp_implementation'): 173 # Link libprotobuf.a and libprotobuf-lite.a statically with the 174 # extension. Note that those libraries have to be compiled with 175 # -fPIC for this to work. 176 compile_static_ext = get_option_from_sys_argv('--compile_static_extension') 177 extra_compile_args = ['-Wno-write-strings', 178 '-Wno-invalid-offsetof', 179 '-Wno-sign-compare'] 180 libraries = ['protobuf'] 181 extra_objects = None 182 if compile_static_ext: 183 libraries = None 184 extra_objects = ['../src/.libs/libprotobuf.a', 185 '../src/.libs/libprotobuf-lite.a'] 186 test_conformance.target = 'test_python_cpp' 187 188 if "clang" in os.popen('$CC --version 2> /dev/null').read(): 189 extra_compile_args.append('-Wno-shorten-64-to-32') 190 191 if warnings_as_errors in sys.argv: 192 extra_compile_args.append('-Werror') 193 sys.argv.remove(warnings_as_errors) 194 195 # C++ implementation extension 196 ext_module_list.extend([ 197 Extension( 198 "google.protobuf.pyext._message", 199 glob.glob('google/protobuf/pyext/*.cc'), 200 include_dirs=[".", "../src"], 201 libraries=libraries, 202 extra_objects=extra_objects, 203 library_dirs=['../src/.libs'], 204 extra_compile_args=extra_compile_args, 205 ), 206 Extension( 207 "google.protobuf.internal._api_implementation", 208 glob.glob('google/protobuf/internal/api_implementation.cc'), 209 extra_compile_args=['-DPYTHON_PROTO2_CPP_IMPL_V2'], 210 ), 211 ]) 212 os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp' 213 214 # Keep this list of dependencies in sync with tox.ini. 215 install_requires = ['six>=1.9', 'setuptools'] 216 if sys.version_info <= (2,7): 217 install_requires.append('ordereddict') 218 install_requires.append('unittest2') 219 220 setup( 221 name='protobuf', 222 version=GetVersion(), 223 description='Protocol Buffers', 224 download_url='https://github.com/google/protobuf/releases', 225 long_description="Protocol Buffers are Google's data interchange format", 226 url='https://developers.google.com/protocol-buffers/', 227 maintainer='protobuf@googlegroups.com', 228 maintainer_email='protobuf@googlegroups.com', 229 license='New BSD License', 230 classifiers=[ 231 "Programming Language :: Python", 232 "Programming Language :: Python :: 2", 233 "Programming Language :: Python :: 2.6", 234 "Programming Language :: Python :: 2.7", 235 "Programming Language :: Python :: 3", 236 "Programming Language :: Python :: 3.3", 237 "Programming Language :: Python :: 3.4", 238 ], 239 namespace_packages=['google'], 240 packages=find_packages( 241 exclude=[ 242 'import_test_package', 243 ], 244 ), 245 test_suite='google.protobuf.internal', 246 cmdclass={ 247 'clean': clean, 248 'build_py': build_py, 249 'test_conformance': test_conformance, 250 }, 251 install_requires=install_requires, 252 ext_modules=ext_module_list, 253 ) 254