blob: cbb9a5906ba357ad704e8e7f121708272c3a7998 [file] [log] [blame]
Tamir Duberstein9d9d0b72015-04-11 20:23:45 -07001#! /usr/bin/env python
temporal40ee5512008-07-10 02:12:20 +00002#
3# See README for usage instructions.
David L. Jones1ba1d732022-02-17 09:53:51 -08004
5# pylint:disable=missing-module-docstring
6# pylint:disable=g-bad-import-order
Paul Yang704037f2018-11-28 16:45:16 -08007from distutils import util
Misha Seltzer223e8912020-05-14 21:09:09 -04008import fnmatch
Tamir Duberstein5018c432015-05-08 08:48:40 -04009import glob
temporal40ee5512008-07-10 02:12:20 +000010import os
Paul Yang704037f2018-11-28 16:45:16 -080011import pkg_resources
12import re
kenton@google.coma6de64a2009-04-18 02:28:15 +000013import subprocess
Tamir Duberstein5018c432015-05-08 08:48:40 -040014import sys
Paul Yang704037f2018-11-28 16:45:16 -080015import sysconfig
David L. Jones1ba1d732022-02-17 09:53:51 -080016
17# pylint:disable=g-importing-member
18# pylint:disable=g-multiple-import
temporal40ee5512008-07-10 02:12:20 +000019
liujisi@google.com9ced30c2012-08-01 06:22:19 +000020# We must use setuptools, not distutils, because we need to use the
21# namespace_packages option for the "google" package.
Dan O'Reilly3bdfb4b2015-08-20 13:51:26 -040022from setuptools import setup, Extension, find_packages
liujisi@google.com9ced30c2012-08-01 06:22:19 +000023
Sandy Zhang215dd132021-09-10 20:04:52 +000024from distutils.command.build_ext import build_ext as _build_ext
Benjamin Peterson188c44b2018-09-10 13:35:38 -070025from distutils.command.build_py import build_py as _build_py
Tamir Duberstein21a7cf92015-04-11 18:24:24 -070026from distutils.command.clean import clean as _clean
Tamir Duberstein21a7cf92015-04-11 18:24:24 -070027from distutils.spawn import find_executable
temporal40ee5512008-07-10 02:12:20 +000028
29# Find the Protocol Compiler.
liujisi@google.come34f1f62012-12-05 01:25:12 +000030if 'PROTOC' in os.environ and os.path.exists(os.environ['PROTOC']):
31 protoc = os.environ['PROTOC']
David L. Jones1ba1d732022-02-17 09:53:51 -080032elif os.path.exists('../src/protoc'):
33 protoc = '../src/protoc'
34elif os.path.exists('../src/protoc.exe'):
35 protoc = '../src/protoc.exe'
36elif os.path.exists('../vsprojects/Debug/protoc.exe'):
37 protoc = '../vsprojects/Debug/protoc.exe'
38elif os.path.exists('../vsprojects/Release/protoc.exe'):
39 protoc = '../vsprojects/Release/protoc.exe'
temporal40ee5512008-07-10 02:12:20 +000040else:
David L. Jones1ba1d732022-02-17 09:53:51 -080041 protoc = find_executable('protoc')
temporal40ee5512008-07-10 02:12:20 +000042
Tamir Duberstein21a7cf92015-04-11 18:24:24 -070043
Jisi Liu4573e112015-03-04 16:45:13 -080044def GetVersion():
David L. Jones1ba1d732022-02-17 09:53:51 -080045 """Reads and returns the version from google/protobuf/__init__.py.
Jisi Liu4573e112015-03-04 16:45:13 -080046
Tamir Duberstein21a7cf92015-04-11 18:24:24 -070047 Do not import google.protobuf.__init__ directly, because an installed
David L. Jones1ba1d732022-02-17 09:53:51 -080048 protobuf library may be loaded instead.
49
50 Returns:
51 The version.
52 """
Jisi Liu4573e112015-03-04 16:45:13 -080053
Joshua Habermanb99994d2020-03-31 16:25:37 -070054 with open(os.path.join('google', 'protobuf', '__init__.py')) as version_file:
David L. Jones1ba1d732022-02-17 09:53:51 -080055 exec(version_file.read(), globals()) # pylint:disable=exec-used
56 return __version__ # pylint:disable=undefined-variable
Jisi Liu4573e112015-03-04 16:45:13 -080057
58
David L. Jones1ba1d732022-02-17 09:53:51 -080059def GenProto(source, require=True):
60 """Generates a _pb2.py from the given .proto file.
61
62 Does nothing if the output already exists and is newer than the input.
63
64 Args:
65 source: the .proto file path.
66 require: if True, exit immediately when a path is not found.
67 """
temporal40ee5512008-07-10 02:12:20 +000068
Feng Xiao8e142682015-05-26 00:11:09 -070069 if not require and not os.path.exists(source):
70 return
71
David L. Jones1ba1d732022-02-17 09:53:51 -080072 output = source.replace('.proto', '_pb2.py').replace('../src/', '')
temporal40ee5512008-07-10 02:12:20 +000073
temporal40ee5512008-07-10 02:12:20 +000074 if (not os.path.exists(output) or
75 (os.path.exists(source) and
76 os.path.getmtime(source) > os.path.getmtime(output))):
David L. Jones1ba1d732022-02-17 09:53:51 -080077 print('Generating %s...' % output)
temporal40ee5512008-07-10 02:12:20 +000078
liujisi@google.com9ced30c2012-08-01 06:22:19 +000079 if not os.path.exists(source):
80 sys.stderr.write("Can't find required file: %s\n" % source)
81 sys.exit(-1)
82
Tamir Duberstein21a7cf92015-04-11 18:24:24 -070083 if protoc is None:
temporal40ee5512008-07-10 02:12:20 +000084 sys.stderr.write(
David L. Jones1ba1d732022-02-17 09:53:51 -080085 'protoc is not installed nor found in ../src. Please compile it '
86 'or install the binary package.\n')
temporal40ee5512008-07-10 02:12:20 +000087 sys.exit(-1)
88
David L. Jones1ba1d732022-02-17 09:53:51 -080089 protoc_command = [protoc, '-I../src', '-I.', '--python_out=.', source]
kenton@google.coma6de64a2009-04-18 02:28:15 +000090 if subprocess.call(protoc_command) != 0:
temporal40ee5512008-07-10 02:12:20 +000091 sys.exit(-1)
92
David L. Jones1ba1d732022-02-17 09:53:51 -080093
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000094def GenerateUnittestProtos():
David L. Jones1ba1d732022-02-17 09:53:51 -080095 """Generates protobuf code for unittests."""
96 GenProto('../src/google/protobuf/any_test.proto', False)
97 GenProto('../src/google/protobuf/map_proto2_unittest.proto', False)
98 GenProto('../src/google/protobuf/map_unittest.proto', False)
99 GenProto('../src/google/protobuf/test_messages_proto3.proto', False)
100 GenProto('../src/google/protobuf/test_messages_proto2.proto', False)
101 GenProto('../src/google/protobuf/unittest_arena.proto', False)
102 GenProto('../src/google/protobuf/unittest.proto', False)
103 GenProto('../src/google/protobuf/unittest_custom_options.proto', False)
104 GenProto('../src/google/protobuf/unittest_import.proto', False)
105 GenProto('../src/google/protobuf/unittest_import_public.proto', False)
106 GenProto('../src/google/protobuf/unittest_mset.proto', False)
107 GenProto('../src/google/protobuf/unittest_mset_wire_format.proto', False)
108 GenProto('../src/google/protobuf/unittest_no_generic_services.proto', False)
109 GenProto('../src/google/protobuf/unittest_proto3_arena.proto', False)
110 GenProto('../src/google/protobuf/util/json_format.proto', False)
111 GenProto('../src/google/protobuf/util/json_format_proto3.proto', False)
112 GenProto('google/protobuf/internal/any_test.proto', False)
113 GenProto('google/protobuf/internal/descriptor_pool_test1.proto', False)
114 GenProto('google/protobuf/internal/descriptor_pool_test2.proto', False)
115 GenProto('google/protobuf/internal/factory_test1.proto', False)
116 GenProto('google/protobuf/internal/factory_test2.proto', False)
117 GenProto('google/protobuf/internal/file_options_test.proto', False)
Adam Cozzettea336ba02022-03-18 21:25:56 +0000118 GenProto('google/protobuf/internal/import_test_package/import_public.proto',
119 False)
120 GenProto(
121 'google/protobuf/internal/import_test_package/import_public_nested.proto',
122 False)
David L. Jones1ba1d732022-02-17 09:53:51 -0800123 GenProto('google/protobuf/internal/import_test_package/inner.proto', False)
124 GenProto('google/protobuf/internal/import_test_package/outer.proto', False)
125 GenProto('google/protobuf/internal/missing_enum_values.proto', False)
126 GenProto('google/protobuf/internal/message_set_extensions.proto', False)
127 GenProto('google/protobuf/internal/more_extensions.proto', False)
128 GenProto('google/protobuf/internal/more_extensions_dynamic.proto', False)
129 GenProto('google/protobuf/internal/more_messages.proto', False)
130 GenProto('google/protobuf/internal/no_package.proto', False)
131 GenProto('google/protobuf/internal/packed_field_test.proto', False)
132 GenProto('google/protobuf/internal/test_bad_identifiers.proto', False)
133 GenProto('google/protobuf/internal/test_proto3_optional.proto', False)
134 GenProto('google/protobuf/pyext/python.proto', False)
liujisi@google.com9ced30c2012-08-01 06:22:19 +0000135
Tamir Duberstein21a7cf92015-04-11 18:24:24 -0700136
David L. Jones1ba1d732022-02-17 09:53:51 -0800137class CleanCmd(_clean):
138 """Custom clean command for building the protobuf extension."""
139
liujisi@google.com9ced30c2012-08-01 06:22:19 +0000140 def run(self):
141 # Delete generated files in the code tree.
David L. Jones1ba1d732022-02-17 09:53:51 -0800142 for (dirpath, unused_dirnames, filenames) in os.walk('.'):
temporal40ee5512008-07-10 02:12:20 +0000143 for filename in filenames:
144 filepath = os.path.join(dirpath, filename)
David L. Jones1ba1d732022-02-17 09:53:51 -0800145 if (filepath.endswith('_pb2.py') or filepath.endswith('.pyc') or
146 filepath.endswith('.so') or filepath.endswith('.o')):
temporal40ee5512008-07-10 02:12:20 +0000147 os.remove(filepath)
liujisi@google.com9ced30c2012-08-01 06:22:19 +0000148 # _clean is an old-style class, so super() doesn't work.
149 _clean.run(self)
150
David L. Jones1ba1d732022-02-17 09:53:51 -0800151
152class BuildPyCmd(_build_py):
153 """Custom build_py command for building the protobuf runtime."""
154
liujisi@google.com9ced30c2012-08-01 06:22:19 +0000155 def run(self):
temporal40ee5512008-07-10 02:12:20 +0000156 # Generate necessary .proto file if it doesn't exist.
David L. Jones1ba1d732022-02-17 09:53:51 -0800157 GenProto('../src/google/protobuf/descriptor.proto')
158 GenProto('../src/google/protobuf/compiler/plugin.proto')
159 GenProto('../src/google/protobuf/any.proto')
160 GenProto('../src/google/protobuf/api.proto')
161 GenProto('../src/google/protobuf/duration.proto')
162 GenProto('../src/google/protobuf/empty.proto')
163 GenProto('../src/google/protobuf/field_mask.proto')
164 GenProto('../src/google/protobuf/source_context.proto')
165 GenProto('../src/google/protobuf/struct.proto')
166 GenProto('../src/google/protobuf/timestamp.proto')
167 GenProto('../src/google/protobuf/type.proto')
168 GenProto('../src/google/protobuf/wrappers.proto')
jieluo@google.combde4a322014-08-12 21:10:30 +0000169 GenerateUnittestProtos()
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000170
liujisi@google.com9ced30c2012-08-01 06:22:19 +0000171 # _build_py is an old-style class, so super() doesn't work.
172 _build_py.run(self)
jieluo@google.combde4a322014-08-12 21:10:30 +0000173
Misha Seltzer223e8912020-05-14 21:09:09 -0400174 def find_package_modules(self, package, package_dir):
175 exclude = (
David L. Jones1ba1d732022-02-17 09:53:51 -0800176 '*test*',
177 'google/protobuf/internal/*_pb2.py',
178 'google/protobuf/internal/_parameterized.py',
179 'google/protobuf/pyext/python_pb2.py',
Misha Seltzer223e8912020-05-14 21:09:09 -0400180 )
181 modules = _build_py.find_package_modules(self, package, package_dir)
182 return [(pkg, mod, fil) for (pkg, mod, fil) in modules
183 if not any(fnmatch.fnmatchcase(fil, pat=pat) for pat in exclude)]
184
185
David L. Jones1ba1d732022-02-17 09:53:51 -0800186class BuildExtCmd(_build_ext):
187 """Command class for building the protobuf Python extension."""
Sandy Zhang215dd132021-09-10 20:04:52 +0000188
189 def get_ext_filename(self, ext_name):
190 # since python3.5, python extensions' shared libraries use a suffix that
191 # corresponds to the value of sysconfig.get_config_var('EXT_SUFFIX') and
192 # contains info about the architecture the library targets. E.g. on x64
193 # linux the suffix is ".cpython-XYZ-x86_64-linux-gnu.so" When
194 # crosscompiling python wheels, we need to be able to override this
195 # suffix so that the resulting file name matches the target architecture
196 # and we end up with a well-formed wheel.
197 filename = _build_ext.get_ext_filename(self, ext_name)
David L. Jones1ba1d732022-02-17 09:53:51 -0800198 orig_ext_suffix = sysconfig.get_config_var('EXT_SUFFIX')
199 new_ext_suffix = os.getenv('PROTOCOL_BUFFERS_OVERRIDE_EXT_SUFFIX')
Sandy Zhang215dd132021-09-10 20:04:52 +0000200 if new_ext_suffix and filename.endswith(orig_ext_suffix):
201 filename = filename[:-len(orig_ext_suffix)] + new_ext_suffix
202 return filename
203
David L. Jones1ba1d732022-02-17 09:53:51 -0800204
205class TestConformanceCmd(_build_py):
Josh Haberman325392d2015-08-17 12:30:49 -0700206 target = 'test_python'
David L. Jones1ba1d732022-02-17 09:53:51 -0800207
Josh Haberman325392d2015-08-17 12:30:49 -0700208 def run(self):
Yuchen Xie595231d2018-06-26 06:20:53 +0800209 # Python 2.6 dodges these extra failures.
David L. Jones1ba1d732022-02-17 09:53:51 -0800210 os.environ['CONFORMANCE_PYTHON_EXTRA_FAILURES'] = (
211 '--failure_list failure_list_python-post26.txt')
212 cmd = 'cd ../conformance && make %s' % (TestConformanceCmd.target)
213 subprocess.check_call(cmd, shell=True)
Josh Haberman325392d2015-08-17 12:30:49 -0700214
liujisi@google.com9b7f6c52010-12-08 03:45:27 +0000215
David L. Jones1ba1d732022-02-17 09:53:51 -0800216def GetOptionFromArgv(option_str):
Manjunath Kudlurcf828de2016-03-25 10:58:46 -0700217 if option_str in sys.argv:
218 sys.argv.remove(option_str)
219 return True
220 return False
221
222
liujisi@google.com9ced30c2012-08-01 06:22:19 +0000223if __name__ == '__main__':
jieluo@google.com1eba9d92014-08-25 20:17:53 +0000224 ext_module_list = []
Josh Haberman00700b72015-10-06 14:13:09 -0700225 warnings_as_errors = '--warnings_as_errors'
David L. Jones1ba1d732022-02-17 09:53:51 -0800226 if GetOptionFromArgv('--cpp_implementation'):
Manjunath Kudlurcf828de2016-03-25 10:58:46 -0700227 # Link libprotobuf.a and libprotobuf-lite.a statically with the
228 # extension. Note that those libraries have to be compiled with
229 # -fPIC for this to work.
David L. Jones1ba1d732022-02-17 09:53:51 -0800230 compile_static_ext = GetOptionFromArgv('--compile_static_extension')
Manjunath Kudlurcf828de2016-03-25 10:58:46 -0700231 libraries = ['protobuf']
232 extra_objects = None
233 if compile_static_ext:
234 libraries = None
235 extra_objects = ['../src/.libs/libprotobuf.a',
236 '../src/.libs/libprotobuf-lite.a']
David L. Jones1ba1d732022-02-17 09:53:51 -0800237 TestConformanceCmd.target = 'test_python_cpp'
Josh Habermand8814ed2015-10-07 11:46:23 -0700238
Paul Yangc9317432018-04-02 15:55:28 -0700239 extra_compile_args = []
240
Adam Cozzettea035bd02022-01-25 08:24:12 -0800241 message_extra_link_args = None
242 api_implementation_link_args = None
David L. Jones1ba1d732022-02-17 09:53:51 -0800243 if 'darwin' in sys.platform:
Adam Cozzettea035bd02022-01-25 08:24:12 -0800244 if sys.version_info[0] == 2:
David L. Jones1ba1d732022-02-17 09:53:51 -0800245 message_init_symbol = 'init_message'
246 api_implementation_init_symbol = 'init_api_implementation'
Adam Cozzettea035bd02022-01-25 08:24:12 -0800247 else:
David L. Jones1ba1d732022-02-17 09:53:51 -0800248 message_init_symbol = 'PyInit__message'
249 api_implementation_init_symbol = 'PyInit__api_implementation'
250 message_extra_link_args = [
251 '-Wl,-exported_symbol,_%s' % message_init_symbol
252 ]
253 api_implementation_link_args = [
254 '-Wl,-exported_symbol,_%s' % api_implementation_init_symbol
255 ]
Adam Cozzettea035bd02022-01-25 08:24:12 -0800256
Paul Yangc9317432018-04-02 15:55:28 -0700257 if sys.platform != 'win32':
Adam Cozzette3afc8282021-10-08 16:45:26 -0700258 extra_compile_args.append('-Wno-write-strings')
259 extra_compile_args.append('-Wno-invalid-offsetof')
260 extra_compile_args.append('-Wno-sign-compare')
261 extra_compile_args.append('-Wno-unused-variable')
262 extra_compile_args.append('-std=c++11')
Paul Yangc9317432018-04-02 15:55:28 -0700263
Feng Xiaoacd5b052018-08-09 21:21:01 -0700264 if sys.platform == 'darwin':
David L. Jones1ba1d732022-02-17 09:53:51 -0800265 extra_compile_args.append('-Wno-shorten-64-to-32')
266 extra_compile_args.append('-Wno-deprecated-register')
Feng Xiaoacd5b052018-08-09 21:21:01 -0700267
Paul Yang704037f2018-11-28 16:45:16 -0800268 # https://developer.apple.com/documentation/xcode_release_notes/xcode_10_release_notes
269 # C++ projects must now migrate to libc++ and are recommended to set a
270 # deployment target of macOS 10.9 or later, or iOS 7 or later.
271 if sys.platform == 'darwin':
Thomas BACCELLI26c0fbc2020-12-06 15:40:04 +0100272 mac_target = str(sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET'))
Paul Yang704037f2018-11-28 16:45:16 -0800273 if mac_target and (pkg_resources.parse_version(mac_target) <
David L. Jones1ba1d732022-02-17 09:53:51 -0800274 pkg_resources.parse_version('10.9.0')):
Paul Yang704037f2018-11-28 16:45:16 -0800275 os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.9'
276 os.environ['_PYTHON_HOST_PLATFORM'] = re.sub(
277 r'macosx-[0-9]+\.[0-9]+-(.+)', r'macosx-10.9-\1',
278 util.get_platform())
279
Paul Yangc9317432018-04-02 15:55:28 -0700280 # https://github.com/Theano/Theano/issues/4926
281 if sys.platform == 'win32':
282 extra_compile_args.append('-D_hypot=hypot')
283
284 # https://github.com/tpaviot/pythonocc-core/issues/48
285 if sys.platform == 'win32' and '64 bit' in sys.version:
286 extra_compile_args.append('-DMS_WIN64')
287
288 # MSVS default is dymanic
David L. Jones1ba1d732022-02-17 09:53:51 -0800289 if sys.platform == 'win32':
Paul Yangc9317432018-04-02 15:55:28 -0700290 extra_compile_args.append('/MT')
291
David L. Jones1ba1d732022-02-17 09:53:51 -0800292 if 'clang' in os.popen('$CC --version 2> /dev/null').read():
Josh Habermand8814ed2015-10-07 11:46:23 -0700293 extra_compile_args.append('-Wno-shorten-64-to-32')
Josh Haberman00700b72015-10-06 14:13:09 -0700294
295 if warnings_as_errors in sys.argv:
296 extra_compile_args.append('-Werror')
297 sys.argv.remove(warnings_as_errors)
298
jieluo@google.com1eba9d92014-08-25 20:17:53 +0000299 # C++ implementation extension
Manjunath Kudlurcf828de2016-03-25 10:58:46 -0700300 ext_module_list.extend([
Tamir Duberstein21a7cf92015-04-11 18:24:24 -0700301 Extension(
David L. Jones1ba1d732022-02-17 09:53:51 -0800302 'google.protobuf.pyext._message',
Tamir Duberstein5018c432015-05-08 08:48:40 -0400303 glob.glob('google/protobuf/pyext/*.cc'),
David L. Jones1ba1d732022-02-17 09:53:51 -0800304 include_dirs=['.', '../src'],
Manjunath Kudlurcf828de2016-03-25 10:58:46 -0700305 libraries=libraries,
306 extra_objects=extra_objects,
Adam Cozzettea035bd02022-01-25 08:24:12 -0800307 extra_link_args=message_extra_link_args,
Tamir Duberstein21a7cf92015-04-11 18:24:24 -0700308 library_dirs=['../src/.libs'],
Josh Haberman00700b72015-10-06 14:13:09 -0700309 extra_compile_args=extra_compile_args,
Manjunath Kudlurcf828de2016-03-25 10:58:46 -0700310 ),
311 Extension(
David L. Jones1ba1d732022-02-17 09:53:51 -0800312 'google.protobuf.internal._api_implementation',
Manjunath Kudlurcf828de2016-03-25 10:58:46 -0700313 glob.glob('google/protobuf/internal/api_implementation.cc'),
David L. Jones1ba1d732022-02-17 09:53:51 -0800314 extra_compile_args=(extra_compile_args +
315 ['-DPYTHON_PROTO2_CPP_IMPL_V2']),
Adam Cozzettea035bd02022-01-25 08:24:12 -0800316 extra_link_args=api_implementation_link_args,
Manjunath Kudlurcf828de2016-03-25 10:58:46 -0700317 ),
318 ])
Jisi Liuada65562015-02-25 16:39:11 -0800319 os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp'
liujisi@google.com33165fe2010-11-02 13:14:58 +0000320
Dan O'Reilly3791c802015-08-20 20:49:45 -0400321 # Keep this list of dependencies in sync with tox.ini.
Joshua Habermana33aa732021-09-09 13:20:34 -0700322 install_requires = []
Dan O'Reilly2621c8a2015-08-14 22:54:53 -0400323
Tamir Duberstein21a7cf92015-04-11 18:24:24 -0700324 setup(
325 name='protobuf',
326 version=GetVersion(),
327 description='Protocol Buffers',
Feng Xiaoafe98de2018-08-22 11:55:30 -0700328 download_url='https://github.com/protocolbuffers/protobuf/releases',
Tamir Duberstein21a7cf92015-04-11 18:24:24 -0700329 long_description="Protocol Buffers are Google's data interchange format",
330 url='https://developers.google.com/protocol-buffers/',
331 maintainer='protobuf@googlegroups.com',
332 maintainer_email='protobuf@googlegroups.com',
Maximilian82372d82022-01-27 01:23:14 +0100333 license='BSD-3-Clause',
Tamir Duberstein21a7cf92015-04-11 18:24:24 -0700334 classifiers=[
David L. Jones1ba1d732022-02-17 09:53:51 -0800335 'Programming Language :: Python',
336 'Programming Language :: Python :: 3',
337 'Programming Language :: Python :: 3.7',
338 'Programming Language :: Python :: 3.8',
339 'Programming Language :: Python :: 3.9',
340 'Programming Language :: Python :: 3.10',
Adam Cozzette3afc8282021-10-08 16:45:26 -0700341 ],
Craig Citro0e7c0c22016-03-04 20:40:24 -0800342 namespace_packages=['google'],
Tamir Duberstein21a7cf92015-04-11 18:24:24 -0700343 packages=find_packages(
344 exclude=[
345 'import_test_package',
David L. Jonesff06e232020-08-31 10:40:57 -0700346 'protobuf_distutils',
Adam Cozzette3afc8282021-10-08 16:45:26 -0700347 ],),
Tamir Duberstein21a7cf92015-04-11 18:24:24 -0700348 test_suite='google.protobuf.internal',
349 cmdclass={
David L. Jones1ba1d732022-02-17 09:53:51 -0800350 'clean': CleanCmd,
351 'build_py': BuildPyCmd,
352 'build_ext': BuildExtCmd,
353 'test_conformance': TestConformanceCmd,
Tamir Duberstein21a7cf92015-04-11 18:24:24 -0700354 },
Dan O'Reilly2621c8a2015-08-14 22:54:53 -0400355 install_requires=install_requires,
Tamir Duberstein21a7cf92015-04-11 18:24:24 -0700356 ext_modules=ext_module_list,
David L. Jones1ba1d732022-02-17 09:53:51 -0800357 python_requires='>=3.7',
Tamir Duberstein21a7cf92015-04-11 18:24:24 -0700358 )