diff --git a/.evergreen/build-mac.sh b/.evergreen/build-mac.sh index 60846ae92..4e8be8cf5 100755 --- a/.evergreen/build-mac.sh +++ b/.evergreen/build-mac.sh @@ -14,9 +14,8 @@ PYTHON=/Library/Frameworks/Python.framework/Versions/$VERSION/bin/python3 rm -rf build createvirtualenv $PYTHON releasevenv -python -m pip install --upgrade wheel -python -m pip install setuptools==63.2.0 -python setup.py bdist_wheel +python -m pip install build +python -m build --wheel . deactivate || true rm -rf releasevenv diff --git a/.evergreen/build-manylinux-internal.sh b/.evergreen/build-manylinux-internal.sh index 7c3747f4e..6f1c58fd8 100755 --- a/.evergreen/build-manylinux-internal.sh +++ b/.evergreen/build-manylinux-internal.sh @@ -16,7 +16,8 @@ for PYTHON in /opt/python/*/bin/python; do fi # https://github.com/pypa/manylinux/issues/49 rm -rf build - $PYTHON setup.py bdist_wheel + $PYTHON -m pip install build + $PYTHON -m build --wheel . rm -rf build # Audit wheels and write manylinux tag diff --git a/.evergreen/build-windows.sh b/.evergreen/build-windows.sh index aeb16892b..8748e5c18 100755 --- a/.evergreen/build-windows.sh +++ b/.evergreen/build-windows.sh @@ -13,7 +13,8 @@ for VERSION in 37 38 39 310 311; do "C:/Python/32/Python${VERSION}/python.exe") for PYTHON in "${_pythons[@]}"; do rm -rf build - $PYTHON setup.py bdist_wheel + $PYTHON -m pip install build + $PYTHON -m build --wheel . # Test that each wheel is installable. for release in dist/*; do diff --git a/.evergreen/config.yml b/.evergreen/config.yml index df126f57a..f3c159a1d 100644 --- a/.evergreen/config.yml +++ b/.evergreen/config.yml @@ -1121,7 +1121,8 @@ functions: done # Build source distribution. cd src/ - /opt/python/3.7/bin/python3 setup.py sdist + /opt/python/3.7/bin/python3 -m pip install build + /opt/python/3.7/bin/python3 -m build --sdist . cp dist/* ../releases - command: archive.targz_pack params: diff --git a/.evergreen/run-doctests.sh b/.evergreen/run-doctests.sh index eebb0f784..39e5102b6 100644 --- a/.evergreen/run-doctests.sh +++ b/.evergreen/run-doctests.sh @@ -3,5 +3,5 @@ set -o xtrace set -o errexit -${PYTHON_BINARY} setup.py clean -${PYTHON_BINARY} setup.py doc -t +${PYTHON_BINARY} -m pip install tox +${PYTHON_BINARY} -m tox -e doc-test diff --git a/README.rst b/README.rst index 71d47bdc0..6274e2c9d 100644 --- a/README.rst +++ b/README.rst @@ -79,7 +79,7 @@ Or ``easy_install`` from You can also download the project source and do:: - $ python setup.py install + $ pip install . Do **not** install the "bson" package from pypi. PyMongo comes with its own bson package; doing "easy_install bson" installs a third-party package that diff --git a/RELEASE.rst b/RELEASE.rst index 4150126f2..caa67d381 100644 --- a/RELEASE.rst +++ b/RELEASE.rst @@ -36,7 +36,7 @@ Doing a Release To test locally, ``python3 setup.py test`` will build the C extensions and test. ``python3 tools/clean.py`` will remove the extensions, and then ``python3 setup.py --no_ext test`` will run the tests without - them. You can also run the doctests: ``python3 setup.py doc -t``. + them. You can also run the doctests: ``tox -e doc-test``. 2. Check Jira to ensure all the tickets in this version have been completed. diff --git a/doc/index.rst b/doc/index.rst index e474d27d8..7e357c2a4 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -102,7 +102,8 @@ following command from the root directory of the **PyMongo** source: .. code-block:: bash - $ python setup.py doc + $ pip install tox + $ tox -e docs Indices and tables ------------------ diff --git a/doc/installation.rst b/doc/installation.rst index c4cbc78d9..8ba21b0f9 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -89,7 +89,7 @@ latest source from GitHub and install the driver from the resulting tree:: $ git clone https://github.com/mongodb/mongo-python-driver.git pymongo $ cd pymongo/ - $ python3 setup.py install + $ pip install . Installing from source on Unix .............................. @@ -186,7 +186,7 @@ If you wish to install PyMongo without the C extensions, even if the extensions build properly, it can be done using a command line option to *setup.py*:: - $ python3 setup.py --no_ext install + $ NO_EXT=1 python -m pip install . Installing a beta or release candidate -------------------------------------- diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..3ad35c0b4 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,93 @@ +[build-system] +requires = ["setuptools>=63.0"] +build-backend = "setuptools.build_meta" + +[project] +name = "pymongo" +dynamic = ["version"] +description = "Python driver for MongoDB " +readme = "README.rst" +license = {file="LICENSE"} +requires-python = ">=3.7" +authors = [ + { name = "The MongoDB Python Team" }, +] +keywords = [ + "bson", + "gridfs", + "mongo", + "mongodb", + "pymongo", +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "Operating System :: MacOS :: MacOS X", + "Operating System :: Microsoft :: Windows", + "Operating System :: POSIX", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Topic :: Database", + "Typing :: Typed", +] +dependencies = [ + "dnspython>=1.16.0,<3.0.0", +] + +[project.optional-dependencies] +aws = [ + "pymongo-auth-aws<2.0.0", +] +encryption = [ + "pymongo[aws]", + "pymongocrypt>=1.6.0,<2.0.0", +] +gssapi = [ + "pykerberos;os.name!='nt'", + "winkerberos>=0.5.0;os.name=='nt'" +] +# PyOpenSSL 17.0.0 introduced support for OCSP. 17.1.0 introduced +# a related feature we need. 17.2.0 fixes a bug +# in set_default_verify_paths we should really avoid. +# service_identity 18.1.0 introduced support for IP addr matching. +# Fallback to certifi on Windows if we can't load CA certs from the system +# store and just use certifi on macOS. +# https://www.pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set_default_verify_paths +ocsp = [ + "certifi;os.name=='nt' or sys_platform=='darwin'", + "pyopenssl>=17.2.0", + "requests<3.0.0", + "service_identity>=18.1.0", +] +snappy = [ + "python-snappy", +] +# PYTHON-3423 Removed in 4.3 but kept here to avoid pip warnings. +srv = [] +tls = [] +# PYTHON-2133 Removed in 4.0 but kept here to avoid pip warnings. +zstd = [ + "zstandard", +] + +[project.urls] +Homepage = "http://github.com/mongodb/mongo-python-driver" + +[tool.setuptools.dynamic] +version = {attr = "pymongo._version.__version__"} + +[tool.setuptools.packages.find] +include = ["bson","gridfs", "pymongo"] + +[tool.setuptools.package-data] +bson=["py.typed", "*.pyi"] +pymongo=["py.typed", "*.pyi"] +gridfs=["py.typed", "*.pyi"] diff --git a/setup.py b/setup.py index e570d04c5..de8f1b4c1 100755 --- a/setup.py +++ b/setup.py @@ -1,69 +1,16 @@ import os -import platform -import re import sys import warnings -if sys.version_info[:3] < (3, 7): - raise RuntimeError("Python version >= 3.7 required.") - - # Hack to silence atexit traceback in some Python versions try: import multiprocessing # noqa: F401 except ImportError: pass -from setuptools import setup - -if sys.version_info[:2] < (3, 10): - from distutils.cmd import Command - from distutils.command.build_ext import build_ext - from distutils.core import Extension -else: - from setuptools import Command - from setuptools.command.build_ext import build_ext - from setuptools.extension import Extension - -_HAVE_SPHINX = True -try: - from sphinx.cmd import build as sphinx -except ImportError: - try: - import sphinx - except ImportError: - _HAVE_SPHINX = False - -version_ns = {} -with open("pymongo/_version.py") as fp: - exec(fp.read(), version_ns) -version = version_ns["__version__"] - -f = open("README.rst") -try: - try: - readme_content = f.read() - except BaseException: - readme_content = "" -finally: - f.close() - -# PYTHON-654 - Clang doesn't support -mno-fused-madd but the pythons Apple -# ships are built with it. This is a problem starting with Xcode 5.1 -# since clang 3.4 errors out when it encounters unrecognized compiler -# flags. This hack removes -mno-fused-madd from the CFLAGS automatically -# generated by distutils for Apple provided pythons, allowing C extension -# builds to complete without error. The inspiration comes from older -# versions of distutils.sysconfig.get_config_vars. -if sys.platform == "darwin" and "clang" in platform.python_compiler().lower(): - from distutils.sysconfig import get_config_vars - - res = get_config_vars() - for key in ("CFLAGS", "PY_CFLAGS"): - if key in res: - flags = res[key] - flags = re.sub("-mno-fused-madd", "", flags) - res[key] = flags +from setuptools import Command, setup +from setuptools.command.build_ext import build_ext +from setuptools.extension import Extension class test(Command): @@ -126,55 +73,6 @@ class test(Command): sys.exit(not result.wasSuccessful()) -class doc(Command): - - description = "generate or test documentation" - - user_options = [("test", "t", "run doctests instead of generating documentation")] - - boolean_options = ["test"] - - def initialize_options(self): - self.test = False - - def finalize_options(self): - pass - - def run(self): - - if not _HAVE_SPHINX: - raise RuntimeError("You must install Sphinx to build or test the documentation.") - - if self.test: - path = os.path.join(os.path.abspath("."), "doc", "_build", "doctest") - mode = "doctest" - else: - path = os.path.join(os.path.abspath("."), "doc", "_build", version) - mode = "html" - - try: - os.makedirs(path) - except BaseException: - pass - - sphinx_args = ["-E", "-b", mode, "doc", path] - - # sphinx.main calls sys.exit when sphinx.build_main exists. - # Call build_main directly so we can check status and print - # the full path to the built docs. - if hasattr(sphinx, "build_main"): - status = sphinx.build_main(sphinx_args) - else: - status = sphinx.main(sphinx_args) - - if status: - raise RuntimeError("documentation step '%s' failed" % (mode,)) - - sys.stdout.write( - "\nDocumentation step '%s' performed, results here:\n %s/\n" % (mode, path) - ) - - class custom_build_ext(build_ext): """Allow C extension building to fail. @@ -272,39 +170,10 @@ ext_modules = [ ), ] -# PyOpenSSL 17.0.0 introduced support for OCSP. 17.1.0 introduced -# a related feature we need. 17.2.0 fixes a bug -# in set_default_verify_paths we should really avoid. -# service_identity 18.1.0 introduced support for IP addr matching. -pyopenssl_reqs = ["pyopenssl>=17.2.0", "requests<3.0.0", "service_identity>=18.1.0"] -if sys.platform in ("win32", "darwin"): - # Fallback to certifi on Windows if we can't load CA certs from the system - # store and just use certifi on macOS. - # https://www.pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set_default_verify_paths - pyopenssl_reqs.append("certifi") -aws_reqs = ["pymongo-auth-aws<2.0.0"] - -extras_require = { - "encryption": ["pymongocrypt>=1.6.0,<2.0.0"] + aws_reqs, - "ocsp": pyopenssl_reqs, - "snappy": ["python-snappy"], - "zstd": ["zstandard"], - "aws": aws_reqs, - "srv": [], # PYTHON-3423 Removed in 4.3 but kept here to avoid pip warnings. - "tls": [], # PYTHON-2133 Removed in 4.0 but kept here to avoid pip warnings. -} - -# GSSAPI extras -if sys.platform == "win32": - extras_require["gssapi"] = ["winkerberos>=0.5.0"] -else: - extras_require["gssapi"] = ["pykerberos"] - -extra_opts = {} - -if "--no_ext" in sys.argv: +if "--no_ext" in sys.argv or "NO_EXT" in os.environ: sys.argv.remove("--no_ext") + ext_modules = [] elif sys.platform.startswith("java") or sys.platform == "cli" or "PyPy" in sys.version: sys.stdout.write( """ @@ -314,46 +183,8 @@ by this python implementation.\n *****************************************************\n """ ) -else: - extra_opts["ext_modules"] = ext_modules + ext_modules = [] setup( - name="pymongo", - version=version, - description="Python driver for MongoDB ", - long_description=readme_content, - author="The MongoDB Python Team", - url="http://github.com/mongodb/mongo-python-driver", - keywords=["mongo", "mongodb", "pymongo", "gridfs", "bson"], - install_requires=["dnspython>=1.16.0,<3.0.0"], - license="Apache License, Version 2.0", - python_requires=">=3.7", - classifiers=[ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "License :: OSI Approved :: Apache Software License", - "Operating System :: MacOS :: MacOS X", - "Operating System :: Microsoft :: Windows", - "Operating System :: POSIX", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: Implementation :: CPython", - "Programming Language :: Python :: Implementation :: PyPy", - "Topic :: Database", - "Typing :: Typed", - ], - cmdclass={"build_ext": custom_build_ext, "doc": doc, "test": test}, - extras_require=extras_require, - packages=["bson", "pymongo", "gridfs"], - package_data={ - "bson": ["py.typed", "*.pyi"], - "pymongo": ["py.typed", "*.pyi"], - "gridfs": ["py.typed", "*.pyi"], - }, - **extra_opts -) + cmdclass={"build_ext": custom_build_ext, "test": test}, ext_modules=ext_modules +) # type:ignore diff --git a/tox.ini b/tox.ini index f6e2f1f75..ba53a2011 100644 --- a/tox.ini +++ b/tox.ini @@ -103,7 +103,7 @@ commands = [testenv:doc] description = build sphinx docs deps = - sphinx + -rdoc/docs-requirements.txt commands = sphinx-build -E -b html doc ./doc/_build/html @@ -111,6 +111,7 @@ commands = description = run sphinx doc tests deps = {[testenv:doc]deps} + gevent commands = sphinx-build -E -b doctest doc ./doc/_build/doctest