mysqlx-connector-python/setup.py (172 lines of code) (raw):

#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (c) 2009, 2025, Oracle and/or its affiliates. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2.0, as # published by the Free Software Foundation. # # This program is designed to work with certain software (including # but not limited to OpenSSL) that is licensed under separate terms, # as designated in a particular file or component or in included license # documentation. The authors of MySQL hereby grant you an # additional permission to link the program and your derivative works # with the separately licensed software that they have either included with # the program or referenced in the documentation. # # Without limiting anything contained in the foregoing, this file, # which is part of MySQL Connector/Python, is also subject to the # Universal FOSS Exception, version 1.0, a copy of which can be found at # http://oss.oracle.com/licenses/universal-foss-exception. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the GNU General Public License, version 2.0, for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import os import pathlib import re import shutil import sys sys.path.insert(0, ".") from cpydist import BuildExt, Install, InstallLib from cpydist.bdist import DistBinary from cpydist.bdist_solaris import DistSolaris from cpydist.sdist import DistSource from setuptools import Extension, find_packages, setup try: from cpydist.bdist_wheel import DistWheel except ImportError: DistWheel = None GITHUB_URL = "https://github.com/mysql/mysql-connector-python" METADATA_FILES = ( "README.txt", "README.rst", "LICENSE.txt", "CHANGES.txt", "CONTRIBUTING.md", "SECURITY.md", ) VERSION_TEXT = "999.0.0" version_py = os.path.join("lib", "mysqlx", "version.py") with open(version_py, "rb") as fp: exec(compile(fp.read(), version_py, "exec")) COMMAND_CLASSES = { "bdist": DistBinary, "bdist_solaris": DistSolaris, "build_ext": BuildExt, "install": Install, "install_lib": InstallLib, "sdist": DistSource, } if DistWheel is not None: COMMAND_CLASSES["bdist_wheel"] = DistWheel # C extensions EXTENSIONS = [ Extension( name="_mysqlxpb", define_macros=[("PY3", 1)] if sys.version_info[0] == 3 else [], sources=[ "src/mysqlxpb/mysqlx/mysqlx.pb.cc", "src/mysqlxpb/mysqlx/mysqlx_connection.pb.cc", "src/mysqlxpb/mysqlx/mysqlx_crud.pb.cc", "src/mysqlxpb/mysqlx/mysqlx_cursor.pb.cc", "src/mysqlxpb/mysqlx/mysqlx_datatypes.pb.cc", "src/mysqlxpb/mysqlx/mysqlx_expect.pb.cc", "src/mysqlxpb/mysqlx/mysqlx_expr.pb.cc", "src/mysqlxpb/mysqlx/mysqlx_notice.pb.cc", "src/mysqlxpb/mysqlx/mysqlx_prepare.pb.cc", "src/mysqlxpb/mysqlx/mysqlx_resultset.pb.cc", "src/mysqlxpb/mysqlx/mysqlx_session.pb.cc", "src/mysqlxpb/mysqlx/mysqlx_sql.pb.cc", "src/mysqlxpb/mysqlxpb.cc", ], ), ] def main() -> None: setup( name="mysqlx-connector-python", version=VERSION_TEXT, description=( "A Python driver which implements the X DevAPI, an Application " "Programming Interface for working with the MySQL Document Store." ), long_description=get_long_description(), long_description_content_type="text/x-rst", author="Oracle and/or its affiliates", author_email="", license="GNU GPLv2 (with FOSS License Exception)", keywords=[ "mysql", "database", "db", "connector", "driver", "xdevapi", "nosql", "docstore", ], project_urls={ "Homepage": "https://dev.mysql.com/doc/connector-python/en/", "Documentation": "https://dev.mysql.com/doc/connector-python/en/", "Downloads": "https://dev.mysql.com/downloads/connector/python/", "Release Notes": "https://dev.mysql.com/doc/relnotes/connector-python/en/", "Source Code": GITHUB_URL, "Bug System": "https://bugs.mysql.com/", "Slack": "https://mysqlcommunity.slack.com/messages/connectors", "Forums": "https://forums.mysql.com/list.php?50", "Blog": "https://blogs.oracle.com/mysql/", }, package_dir={"": "lib"}, packages=find_packages(where="lib"), classifiers=[ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "Intended Audience :: Education", "License :: OSI Approved :: GNU General Public License (GPL)", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX :: Linux", "Operating System :: Unix", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Topic :: Database", "Topic :: Software Development", "Topic :: Software Development :: Libraries :: Python Modules", "Typing :: Typed", ], ext_modules=EXTENSIONS, cmdclass=COMMAND_CLASSES, python_requires=">=3.9", install_requires=["protobuf==4.25.3"], extras_require={ "dns-srv": ["dnspython==2.6.1"], "compression": ["lz4>=2.1.6,<=4.3.2", "zstandard==0.23.0"], }, ) def copy_metadata_files() -> None: """Copy metadata files (required by MANIFEST.in) from the parent directory to the current directory. """ for filename in METADATA_FILES: shutil.copy(pathlib.Path(os.getcwd(), f"../{filename}"), pathlib.Path(f"./")) def get_long_description() -> str: """Extracts a long description from the README.rst file that is suited for this specific package. """ with open(pathlib.Path(os.getcwd(), "../README.rst")) as file_handle: # The README.rst text is meant to be shared by both mysql and mysqlx packages, so after getting it we need to # parse it in order to remove the bits of text that are not meaningful for this package (mysqlx) long_description = file_handle.read() block_matches = re.finditer( pattern=( r'(?P<module_start>\.{2}\s+={2,}\s+(?P<module_tag>\<(?P<module_name>mysql|mysqlx|both)\>)(?P<repls>\s+' r'\[(?:(?:,\s*)?(?:repl(?:-mysql(?:x)?)?)\("(?:[^"]+)",\s*"(?:[^"]*)"\))+\])?\s+={2,})' r'(?P<block_text>.+?(?=\.{2}\s+={2,}))(?P<module_end>\.{2}\s+={2,}\s+\</(?P=module_name)\>\s+={2,})' ), string=long_description, flags=re.DOTALL) for block_match in block_matches: if block_match.group("module_name") == 'mysql': long_description = long_description.replace(block_match.group(), "") else: block_text = block_match.group("block_text") if block_match.group("repls"): repl_matches = re.finditer(pattern=r'(?P<repl_name>repl(?:-mysql(?:x)?)?)\("' r'(?P<repl_source>[^"]+)",\s*"(?P<repl_target>[^"]*)"\)+', string=block_match.group("repls")) for repl_match in repl_matches: repl_name = repl_match.group("repl_name") repl_source = repl_match.group("repl_source") repl_target = repl_match.group("repl_target") if repl_target is None: repl_target = "" if repl_name == "repl" or repl_name.endswith("mysqlx"): block_text = block_text.replace(repl_source, repl_target) long_description = long_description.replace(block_match.group(), block_text) # Make replacements for files that are directly accessible within GitHub but not within PyPI files_regex_fragment = "|".join(mf.replace(".", r"\.") for mf in METADATA_FILES) long_description = re.sub(pattern=rf"\<(?P<file_name>{files_regex_fragment})\>", repl=f"<{GITHUB_URL}/blob/trunk/\g<file_name>>", string=long_description) return long_description def remove_metadata_files() -> None: """Remove files copied by `copy_metadata_files()`""" for filename in METADATA_FILES: os.remove(pathlib.Path(f"./{filename}")) if __name__ == "__main__": copy_metadata_files() try: main() except Exception as err: raise err finally: remove_metadata_files()