temporary rollback PiperOrigin-RevId: 803075347
diff --git a/python/_brotli.c b/python/_brotli.c index bdc24a1..9f6c017 100644 --- a/python/_brotli.c +++ b/python/_brotli.c
@@ -18,53 +18,7 @@ #define Py_ARRAY_LENGTH(array) (sizeof(array) / sizeof((array)[0])) #endif -/* Forward declaration for module definition */ -#if PY_MAJOR_VERSION >= 3 -static struct PyModuleDef brotli_module; -#endif - -/* Module state for multi-phase initialization */ -typedef struct { - PyObject *BrotliError; -} brotli_module_state; - -#if PY_MAJOR_VERSION >= 3 -static brotli_module_state * -get_brotli_state(PyObject *module) -{ - void *state = PyModule_GetState(module); - assert(state != NULL); - return (brotli_module_state *)state; -} -#endif - -static void set_brotli_exception(const char *message) { -#if PY_MAJOR_VERSION >= 3 - PyObject *module = PyImport_ImportModule("_brotli"); - if (module == NULL) { - PyErr_SetString(PyExc_RuntimeError, "Module not found"); - return; - } - brotli_module_state *state = get_brotli_state(module); - PyErr_SetString(state->BrotliError, message); -#else - /* For Python 2, use static global */ - static PyObject *brotli_error = NULL; - if (brotli_error == NULL) { - PyObject *module_dict = PyImport_GetModuleDict(); - PyObject *module = PyDict_GetItemString(module_dict, "_brotli"); - if (module != NULL) { - brotli_error = PyObject_GetAttrString(module, "error"); - } - } - if (brotli_error != NULL) { - PyErr_SetString(brotli_error, message); - } else { - PyErr_SetString(PyExc_RuntimeError, message); - } -#endif -} - +static PyObject *BrotliError; /* ----------------------------------- BlocksOutputBuffer code @@ -282,20 +236,20 @@ static int mode_convertor(PyObject *o, BrotliEncoderMode *mode) { if (!PyInt_Check(o)) { - set_brotli_exception("Invalid mode"); + PyErr_SetString(BrotliError, "Invalid mode"); return 0; } int mode_value = -1; if (!as_bounded_int(o, &mode_value, 0, 255)) { - set_brotli_exception("Invalid mode"); + PyErr_SetString(BrotliError, "Invalid mode"); return 0; } *mode = (BrotliEncoderMode) mode_value; if (*mode != BROTLI_MODE_GENERIC && *mode != BROTLI_MODE_TEXT && *mode != BROTLI_MODE_FONT) { - set_brotli_exception("Invalid mode"); + PyErr_SetString(BrotliError, "Invalid mode"); return 0; } @@ -304,12 +258,12 @@ static int quality_convertor(PyObject *o, int *quality) { if (!PyInt_Check(o)) { - set_brotli_exception("Invalid quality"); + PyErr_SetString(BrotliError, "Invalid quality"); return 0; } if (!as_bounded_int(o, quality, 0, 11)) { - set_brotli_exception("Invalid quality. Range is 0 to 11."); + PyErr_SetString(BrotliError, "Invalid quality. Range is 0 to 11."); return 0; } @@ -318,12 +272,12 @@ static int lgwin_convertor(PyObject *o, int *lgwin) { if (!PyInt_Check(o)) { - set_brotli_exception("Invalid lgwin"); + PyErr_SetString(BrotliError, "Invalid lgwin"); return 0; } if (!as_bounded_int(o, lgwin, 10, 24)) { - set_brotli_exception("Invalid lgwin. Range is 10 to 24."); + PyErr_SetString(BrotliError, "Invalid lgwin. Range is 10 to 24."); return 0; } @@ -332,12 +286,12 @@ static int lgblock_convertor(PyObject *o, int *lgblock) { if (!PyInt_Check(o)) { - set_brotli_exception("Invalid lgblock"); + PyErr_SetString(BrotliError, "Invalid lgblock"); return 0; } if (!as_bounded_int(o, lgblock, 0, 24) || (*lgblock != 0 && *lgblock < 16)) { - set_brotli_exception("Invalid lgblock. Can be 0 or in range 16 to 24."); + PyErr_SetString(BrotliError, "Invalid lgblock. Can be 0 or in range 16 to 24."); return 0; } @@ -516,7 +470,8 @@ } error: - set_brotli_exception("BrotliEncoderCompressStream failed while processing the stream"); + PyErr_SetString(BrotliError, + "BrotliEncoderCompressStream failed while processing the stream"); ret = NULL; finally: @@ -552,7 +507,8 @@ } error: - set_brotli_exception("BrotliEncoderCompressStream failed while flushing the stream"); + PyErr_SetString(BrotliError, + "BrotliEncoderCompressStream failed while flushing the stream"); ret = NULL; finally: return ret; @@ -591,7 +547,8 @@ goto finally; error: - set_brotli_exception("BrotliEncoderCompressStream failed while finishing the stream"); + PyErr_SetString(BrotliError, + "BrotliEncoderCompressStream failed while finishing the stream"); ret = NULL; finally: return ret; @@ -834,7 +791,7 @@ if (self->unconsumed_data_length > 0) { if (input.len > 0) { - set_brotli_exception("process called with data when accept_more_data is False"); + PyErr_SetString(BrotliError, "process called with data when accept_more_data is False"); ret = NULL; goto finally; } @@ -851,7 +808,8 @@ } error: - set_brotli_exception("BrotliDecoderDecompressStream failed while processing the stream"); + PyErr_SetString(BrotliError, + "BrotliDecoderDecompressStream failed while processing the stream"); ret = NULL; finally: @@ -875,7 +833,7 @@ static PyObject* brotli_Decompressor_is_finished(brotli_Decompressor *self) { if (!self->dec) { - set_brotli_exception("BrotliDecoderState is NULL while checking is_finished"); + PyErr_SetString(BrotliError, "BrotliDecoderState is NULL while checking is_finished"); return NULL; } @@ -1045,7 +1003,7 @@ error: BlocksOutputBuffer_OnError(&buffer); - set_brotli_exception("BrotliDecompress failed"); + PyErr_SetString(BrotliError, "BrotliDecompress failed"); ret = NULL; finally: @@ -1061,34 +1019,47 @@ PyDoc_STRVAR(brotli_doc, "Implementation module for the Brotli library."); -static int init_brotli_mod(PyObject *m) { #if PY_MAJOR_VERSION >= 3 - brotli_module_state *state = get_brotli_state(m); - state->BrotliError = PyErr_NewException("brotli.error", NULL, NULL); - if (state->BrotliError == NULL) { - return -1; - } - Py_INCREF(state->BrotliError); - if (PyModule_AddObject(m, "error", state->BrotliError) < 0) { - Py_DECREF(state->BrotliError); - return -1; - } +#define INIT_BROTLI PyInit__brotli +#define CREATE_BROTLI PyModule_Create(&brotli_module) +#define RETURN_BROTLI return m +#define RETURN_NULL return NULL + +static struct PyModuleDef brotli_module = { + PyModuleDef_HEAD_INIT, + "_brotli", /* m_name */ + brotli_doc, /* m_doc */ + 0, /* m_size */ + brotli_methods, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL /* m_free */ +}; #else - PyObject* err = PyErr_NewException("brotli.error", NULL, NULL); - if (err != NULL) { - Py_INCREF(err); - PyModule_AddObject(m, "error", err); - } +#define INIT_BROTLI init_brotli +#define CREATE_BROTLI Py_InitModule3("_brotli", brotli_methods, brotli_doc) +#define RETURN_BROTLI return +#define RETURN_NULL return #endif +PyMODINIT_FUNC INIT_BROTLI(void) { + PyObject *m = CREATE_BROTLI; + + BrotliError = PyErr_NewException((char*) "brotli.error", NULL, NULL); + if (BrotliError != NULL) { + Py_INCREF(BrotliError); + PyModule_AddObject(m, "error", BrotliError); + } + if (PyType_Ready(&brotli_CompressorType) < 0) { - return -1; + RETURN_NULL; } Py_INCREF(&brotli_CompressorType); PyModule_AddObject(m, "Compressor", (PyObject *)&brotli_CompressorType); if (PyType_Ready(&brotli_DecompressorType) < 0) { - return -1; + RETURN_NULL; } Py_INCREF(&brotli_DecompressorType); PyModule_AddObject(m, "Decompressor", (PyObject *)&brotli_DecompressorType); @@ -1103,56 +1074,5 @@ decoderVersion >> 24, (decoderVersion >> 12) & 0xFFF, decoderVersion & 0xFFF); PyModule_AddStringConstant(m, "__version__", version); - return 0; + RETURN_BROTLI; } - -#if PY_MAJOR_VERSION >= 3 - -static PyModuleDef_Slot brotli_mod_slots[] = { - {Py_mod_exec, init_brotli_mod}, - #if PY_MINOR_VERSION >= 12 - {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, - #endif - {0, NULL} -}; - -static int -brotli_traverse(PyObject *m, visitproc visit, void *arg) -{ - brotli_module_state *state = get_brotli_state(m); - Py_VISIT(state->BrotliError); - return 0; -} - -static int -brotli_clear(PyObject *m) -{ - brotli_module_state *state = get_brotli_state(m); - Py_CLEAR(state->BrotliError); - return 0; -} - -static struct PyModuleDef brotli_module = { - PyModuleDef_HEAD_INIT, - "_brotli", /* m_name */ - brotli_doc, /* m_doc */ - sizeof(brotli_module_state), /* m_size */ - brotli_methods, /* m_methods */ - brotli_mod_slots, /* m_slots */ - brotli_traverse, /* m_traverse */ - brotli_clear, /* m_clear */ - NULL /* m_free */ -}; - -PyMODINIT_FUNC PyInit__brotli(void){ - return PyModuleDef_Init(&brotli_module); -} - -#else - -PyMODINIT_FUNC init_brotli(void) { - PyObject *m = Py_InitModule3("_brotli", brotli_methods, brotli_doc); - init_brotli_mod(m); -} - -#endif
diff --git a/setup.py b/setup.py index c44d8c5..d73d6dd 100644 --- a/setup.py +++ b/setup.py
@@ -36,33 +36,35 @@ def read_define(path, macro): - """Return macro value from the given file.""" - with open(path, "r") as f: + """ Return macro value from the given file. """ + with open(path, 'r') as f: for line in f: - m = re.match(r"#define\s{}\s+(.+)".format(macro), line) + m = re.match(rf'#define\s{macro}\s+(.+)', line) if m: return m.group(1) - return "" + + return '' def get_version(): - """Return library version string from 'common/version.h' file.""" - version_file_path = os.path.join(CURR_DIR, "c", "common", "version.h") - major = read_define(version_file_path, "BROTLI_VERSION_MAJOR") - minor = read_define(version_file_path, "BROTLI_VERSION_MINOR") - patch = read_define(version_file_path, "BROTLI_VERSION_PATCH") + """ Return library version string from 'common/version.h' file. """ + version_file_path = os.path.join(CURR_DIR, 'c', 'common', 'version.h') + major = read_define(version_file_path, 'BROTLI_VERSION_MAJOR') + minor = read_define(version_file_path, 'BROTLI_VERSION_MINOR') + patch = read_define(version_file_path, 'BROTLI_VERSION_PATCH') if not major or not minor or not patch: - return "" - return "{}.{}.{}".format(major, minor, patch) + return '' + return f'{major}.{minor}.{patch}' def get_test_suite(): test_loader = unittest.TestLoader() - test_suite = test_loader.discover("python", pattern="*_test.py") + test_suite = test_loader.discover('python', pattern='*_test.py') return test_suite class BuildExt(build_ext): + def get_source_files(self): filenames = build_ext.get_source_files(self) for ext in self.extensions: @@ -72,14 +74,13 @@ def build_extension(self, ext): if ext.sources is None or not isinstance(ext.sources, (list, tuple)): raise errors.DistutilsSetupError( - "in 'ext_modules' option (extension '%s'), " - "'sources' must be present and must be " - "a list of source filenames" % ext.name - ) + "in 'ext_modules' option (extension '%s'), " + "'sources' must be present and must be " + "a list of source filenames" % ext.name) ext_path = self.get_ext_fullpath(ext.name) depends = ext.sources + ext.depends - if not (self.force or dep_util.newer_group(depends, ext_path, "newer")): + if not (self.force or dep_util.newer_group(depends, ext_path, 'newer')): log.debug("skipping '%s' extension (up-to-date)", ext.name) return else: @@ -87,20 +88,20 @@ c_sources = [] for source in ext.sources: - if source.endswith(".c"): - c_sources.append(source) + if source.endswith('.c'): + c_sources.append(source) extra_args = ext.extra_compile_args or [] objects = [] macros = ext.define_macros[:] - if platform.system() == "Darwin": - macros.append(("OS_MACOSX", "1")) - elif self.compiler.compiler_type == "mingw32": + if platform.system() == 'Darwin': + macros.append(('OS_MACOSX', '1')) + elif self.compiler.compiler_type == 'mingw32': # On Windows Python 2.7, pyconfig.h defines "hypot" as "_hypot", # This clashes with GCC's cmath, and causes compilation errors when # building under MinGW: http://bugs.python.org/issue11566 - macros.append(("_hypot", "hypot")) + macros.append(('_hypot', 'hypot')) for undef in ext.undef_macros: macros.append((undef,)) @@ -111,8 +112,7 @@ include_dirs=ext.include_dirs, debug=self.debug, extra_postargs=extra_args, - depends=ext.depends, - ) + depends=ext.depends) objects.extend(objs) self._built_objects = objects[:] @@ -121,8 +121,8 @@ extra_args = ext.extra_link_args or [] # when using GCC on Windows, we statically link libgcc and libstdc++, # so that we don't need to package extra DLLs - if self.compiler.compiler_type == "mingw32": - extra_args.extend(["-static-libgcc", "-static-libstdc++"]) + if self.compiler.compiler_type == 'mingw32': + extra_args.extend(['-static-libgcc', '-static-libstdc++']) ext_path = self.get_ext_fullpath(ext.name) # Detect target language, if not provided @@ -138,55 +138,54 @@ export_symbols=self.get_export_symbols(ext), debug=self.debug, build_temp=self.build_temp, - target_lang=language, - ) + target_lang=language) -NAME = "Brotli" +NAME = 'Brotli' VERSION = get_version() -URL = "https://github.com/google/brotli" +URL = 'https://github.com/google/brotli' -DESCRIPTION = "Python bindings for the Brotli compression library" +DESCRIPTION = 'Python bindings for the Brotli compression library' -AUTHOR = "The Brotli Authors" +AUTHOR = 'The Brotli Authors' -LICENSE = "MIT" +LICENSE = 'MIT' -PLATFORMS = ["Posix", "MacOS X", "Windows"] +PLATFORMS = ['Posix', 'MacOS X', 'Windows'] CLASSIFIERS = [ - "Development Status :: 4 - Beta", - "Environment :: Console", - "Intended Audience :: Developers", - "License :: OSI Approved :: MIT License", - "Operating System :: MacOS :: MacOS X", - "Operating System :: Microsoft :: Windows", - "Operating System :: POSIX :: Linux", - "Programming Language :: C", - "Programming Language :: C++", - "Programming Language :: Python", - "Programming Language :: Python :: 2", - "Programming Language :: Python :: 2.7", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.3", - "Programming Language :: Python :: 3.4", - "Programming Language :: Python :: 3.5", - "Programming Language :: Unix Shell", - "Topic :: Software Development :: Libraries", - "Topic :: Software Development :: Libraries :: Python Modules", - "Topic :: System :: Archiving", - "Topic :: System :: Archiving :: Compression", - "Topic :: Text Processing :: Fonts", - "Topic :: Utilities", + 'Development Status :: 4 - Beta', + 'Environment :: Console', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: MIT License', + 'Operating System :: MacOS :: MacOS X', + 'Operating System :: Microsoft :: Windows', + 'Operating System :: POSIX :: Linux', + 'Programming Language :: C', + 'Programming Language :: C++', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Unix Shell', + 'Topic :: Software Development :: Libraries', + 'Topic :: Software Development :: Libraries :: Python Modules', + 'Topic :: System :: Archiving', + 'Topic :: System :: Archiving :: Compression', + 'Topic :: Text Processing :: Fonts', + 'Topic :: Utilities', ] -PACKAGE_DIR = {"": "python"} +PACKAGE_DIR = {'': 'python'} -PY_MODULES = ["brotli"] +PY_MODULES = ['brotli'] -USE_SYSTEM_BROTLI = bool_from_environ("USE_SYSTEM_BROTLI") +USE_SYSTEM_BROTLI = bool_from_environ('USE_SYSTEM_BROTLI') if USE_SYSTEM_BROTLI: import pkgconfig @@ -222,115 +221,115 @@ else: EXT_MODULES = [ Extension( - "_brotli", + '_brotli', sources=[ - "python/_brotli.c", - "c/common/constants.c", - "c/common/context.c", - "c/common/dictionary.c", - "c/common/platform.c", - "c/common/shared_dictionary.c", - "c/common/transform.c", - "c/dec/bit_reader.c", - "c/dec/decode.c", - "c/dec/huffman.c", - "c/dec/prefix.c", - "c/dec/state.c", - "c/dec/static_init.c", - "c/enc/backward_references.c", - "c/enc/backward_references_hq.c", - "c/enc/bit_cost.c", - "c/enc/block_splitter.c", - "c/enc/brotli_bit_stream.c", - "c/enc/cluster.c", - "c/enc/command.c", - "c/enc/compound_dictionary.c", - "c/enc/compress_fragment.c", - "c/enc/compress_fragment_two_pass.c", - "c/enc/dictionary_hash.c", - "c/enc/encode.c", - "c/enc/encoder_dict.c", - "c/enc/entropy_encode.c", - "c/enc/fast_log.c", - "c/enc/histogram.c", - "c/enc/literal_cost.c", - "c/enc/memory.c", - "c/enc/metablock.c", - "c/enc/static_dict.c", - "c/enc/static_dict_lut.c", - "c/enc/static_init.c", - "c/enc/utf8_util.c", + 'python/_brotli.c', + 'c/common/constants.c', + 'c/common/context.c', + 'c/common/dictionary.c', + 'c/common/platform.c', + 'c/common/shared_dictionary.c', + 'c/common/transform.c', + 'c/dec/bit_reader.c', + 'c/dec/decode.c', + 'c/dec/huffman.c', + 'c/dec/prefix.c', + 'c/dec/state.c', + 'c/dec/static_init.c', + 'c/enc/backward_references.c', + 'c/enc/backward_references_hq.c', + 'c/enc/bit_cost.c', + 'c/enc/block_splitter.c', + 'c/enc/brotli_bit_stream.c', + 'c/enc/cluster.c', + 'c/enc/command.c', + 'c/enc/compound_dictionary.c', + 'c/enc/compress_fragment.c', + 'c/enc/compress_fragment_two_pass.c', + 'c/enc/dictionary_hash.c', + 'c/enc/encode.c', + 'c/enc/encoder_dict.c', + 'c/enc/entropy_encode.c', + 'c/enc/fast_log.c', + 'c/enc/histogram.c', + 'c/enc/literal_cost.c', + 'c/enc/memory.c', + 'c/enc/metablock.c', + 'c/enc/static_dict.c', + 'c/enc/static_dict_lut.c', + 'c/enc/static_init.c', + 'c/enc/utf8_util.c', ], depends=[ - "c/common/constants.h", - "c/common/context.h", - "c/common/dictionary.h", - "c/common/platform.h", - "c/common/shared_dictionary_internal.h", - "c/common/static_init.h", - "c/common/transform.h", - "c/common/version.h", - "c/dec/bit_reader.h", - "c/dec/huffman.h", - "c/dec/prefix.h", - "c/dec/prefix_inc.h", - "c/dec/state.h", - "c/dec/static_init.h", - "c/enc/backward_references.h", - "c/enc/backward_references_hq.h", - "c/enc/backward_references_inc.h", - "c/enc/bit_cost.h", - "c/enc/bit_cost_inc.h", - "c/enc/block_encoder_inc.h", - "c/enc/block_splitter.h", - "c/enc/block_splitter_inc.h", - "c/enc/brotli_bit_stream.h", - "c/enc/cluster.h", - "c/enc/cluster_inc.h", - "c/enc/command.h", - "c/enc/compound_dictionary.h", - "c/enc/compress_fragment.h", - "c/enc/compress_fragment_two_pass.h", - "c/enc/dictionary_hash.h", - "c/enc/dictionary_hash_inc.h", - "c/enc/encoder_dict.h", - "c/enc/entropy_encode.h", - "c/enc/entropy_encode_static.h", - "c/enc/fast_log.h", - "c/enc/find_match_length.h", - "c/enc/hash.h", - "c/enc/hash_composite_inc.h", - "c/enc/hash_forgetful_chain_inc.h", - "c/enc/hash_longest_match64_inc.h", - "c/enc/hash_longest_match_inc.h", - "c/enc/hash_longest_match_quickly_inc.h", - "c/enc/hash_rolling_inc.h", - "c/enc/hash_to_binary_tree_inc.h", - "c/enc/histogram.h", - "c/enc/histogram_inc.h", - "c/enc/literal_cost.h", - "c/enc/memory.h", - "c/enc/metablock.h", - "c/enc/metablock_inc.h", - "c/enc/params.h", - "c/enc/prefix.h", - "c/enc/quality.h", - "c/enc/ringbuffer.h", - "c/enc/static_dict.h", - "c/enc/static_dict_lut.h", - "c/enc/static_init.h", - "c/enc/utf8_util.h", - "c/enc/write_bits.h", + 'c/common/constants.h', + 'c/common/context.h', + 'c/common/dictionary.h', + 'c/common/platform.h', + 'c/common/shared_dictionary_internal.h', + 'c/common/static_init.h', + 'c/common/transform.h', + 'c/common/version.h', + 'c/dec/bit_reader.h', + 'c/dec/huffman.h', + 'c/dec/prefix.h', + 'c/dec/prefix_inc.h', + 'c/dec/state.h', + 'c/dec/static_init.h', + 'c/enc/backward_references.h', + 'c/enc/backward_references_hq.h', + 'c/enc/backward_references_inc.h', + 'c/enc/bit_cost.h', + 'c/enc/bit_cost_inc.h', + 'c/enc/block_encoder_inc.h', + 'c/enc/block_splitter.h', + 'c/enc/block_splitter_inc.h', + 'c/enc/brotli_bit_stream.h', + 'c/enc/cluster.h', + 'c/enc/cluster_inc.h', + 'c/enc/command.h', + 'c/enc/compound_dictionary.h', + 'c/enc/compress_fragment.h', + 'c/enc/compress_fragment_two_pass.h', + 'c/enc/dictionary_hash.h', + 'c/enc/dictionary_hash_inc.h', + 'c/enc/encoder_dict.h', + 'c/enc/entropy_encode.h', + 'c/enc/entropy_encode_static.h', + 'c/enc/fast_log.h', + 'c/enc/find_match_length.h', + 'c/enc/hash.h', + 'c/enc/hash_composite_inc.h', + 'c/enc/hash_forgetful_chain_inc.h', + 'c/enc/hash_longest_match64_inc.h', + 'c/enc/hash_longest_match_inc.h', + 'c/enc/hash_longest_match_quickly_inc.h', + 'c/enc/hash_rolling_inc.h', + 'c/enc/hash_to_binary_tree_inc.h', + 'c/enc/histogram.h', + 'c/enc/histogram_inc.h', + 'c/enc/literal_cost.h', + 'c/enc/memory.h', + 'c/enc/metablock.h', + 'c/enc/metablock_inc.h', + 'c/enc/params.h', + 'c/enc/prefix.h', + 'c/enc/quality.h', + 'c/enc/ringbuffer.h', + 'c/enc/static_dict.h', + 'c/enc/static_dict_lut.h', + 'c/enc/static_init.h', + 'c/enc/utf8_util.h', + 'c/enc/write_bits.h', ], include_dirs=[ - "c/include", + 'c/include', ]), ] -TEST_SUITE = "setup.get_test_suite" +TEST_SUITE = 'setup.get_test_suite' CMD_CLASS = { - "build_ext": BuildExt, + 'build_ext': BuildExt, } with open("README.md", "r") as f: @@ -351,5 +350,4 @@ py_modules=PY_MODULES, ext_modules=EXT_MODULES, test_suite=TEST_SUITE, - cmdclass=CMD_CLASS, -) + cmdclass=CMD_CLASS)