Skip to content

Commit

Permalink
PYTHON-4451 Use Hatch as Build Backend (mongodb#1644)
Browse files Browse the repository at this point in the history
(cherry picked from commit 2b03001)
  • Loading branch information
blink1073 committed Jun 7, 2024
1 parent c36bfbc commit d693ccf
Show file tree
Hide file tree
Showing 12 changed files with 100 additions and 99 deletions.
1 change: 1 addition & 0 deletions .evergreen/run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ if [ -n "$TEST_ENCRYPTION" ] || [ -n "$TEST_FLE_AZURE_AUTO" ] || [ -n "$TEST_FLE
if [ ! -d "libmongocrypt_git" ]; then
git clone https://github.com/mongodb/libmongocrypt.git libmongocrypt_git
fi
python -m pip install -U setuptools
python -m pip install ./libmongocrypt_git/bindings/python
python -c "import pymongocrypt; print('pymongocrypt version: '+pymongocrypt.__version__)"
python -c "import pymongocrypt; print('libmongocrypt version: '+pymongocrypt.libmongocrypt_version())"
Expand Down
2 changes: 1 addition & 1 deletion .evergreen/utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ createvirtualenv () {

export PIP_QUIET=1
python -m pip install --upgrade pip
python -m pip install --upgrade setuptools tox
python -m pip install --upgrade tox
}

# Usage:
Expand Down
6 changes: 2 additions & 4 deletions .github/workflows/test-python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,10 @@ jobs:
- name: Run linters
run: |
tox -m lint-manual
- name: Check Manifest
run: |
tox -m manifest
- name: Run compilation
run: |
pip install -e .
export PYMONGO_C_EXT_MUST_BUILD=1
pip install -v -e .
python tools/fail_if_no_c.py
- name: Run typecheck
run: |
Expand Down
33 changes: 0 additions & 33 deletions MANIFEST.in

This file was deleted.

6 changes: 0 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,6 @@ PyMongo can be installed with [pip](http://pypi.python.org/pypi/pip):
python -m pip install pymongo
```

Or `easy_install` from [setuptools](http://pypi.python.org/pypi/setuptools):

```bash
python -m easy_install pymongo
```

You can also download the project source and do:

```bash
Expand Down
36 changes: 36 additions & 0 deletions hatch_build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""A custom hatch build hook for pymongo."""
from __future__ import annotations

import os
import subprocess
import sys
from pathlib import Path

from hatchling.builders.hooks.plugin.interface import BuildHookInterface


class CustomHook(BuildHookInterface):
"""The pymongo build hook."""

def initialize(self, version, build_data):
"""Initialize the hook."""
if self.target_name == "sdist":
return
here = Path(__file__).parent.resolve()
sys.path.insert(0, str(here))

subprocess.check_call([sys.executable, "setup.py", "build_ext", "-i"])

# Ensure wheel is marked as binary and contains the binary files.
build_data["infer_tag"] = True
build_data["pure_python"] = False
if os.name == "nt":
patt = ".pyd"
else:
patt = ".so"
for pkg in ["bson", "pymongo"]:
dpath = here / pkg
for fpath in dpath.glob(f"*{patt}"):
relpath = os.path.relpath(fpath, here)
build_data["artifacts"].append(relpath)
build_data["force_include"][relpath] = relpath
27 changes: 20 additions & 7 deletions pymongo/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,29 @@
"""Current version of PyMongo."""
from __future__ import annotations

from typing import Tuple, Union
import re
from typing import List, Tuple, Union

version_tuple: Tuple[Union[int, str], ...] = (4, 7, 4, ".dev0")
__version__ = "4.7.4.dev1"


def get_version_string() -> str:
if isinstance(version_tuple[-1], str):
return ".".join(map(str, version_tuple[:-1])) + version_tuple[-1]
return ".".join(map(str, version_tuple))
def get_version_tuple(version: str) -> Tuple[Union[int, str], ...]:
pattern = r"(?P<major>\d+).(?P<minor>\d+).(?P<patch>\d+)(?P<rest>.*)"
match = re.match(pattern, version)
if match:
parts: List[Union[int, str]] = [int(match[part]) for part in ["major", "minor", "patch"]]
if match["rest"]:
parts.append(match["rest"])
elif re.match(r"\d+.\d+", version):
parts = [int(part) for part in version.split(".")]
else:
raise ValueError("Could not parse version")
return tuple(parts)


__version__: str = get_version_string()
version_tuple = get_version_tuple(__version__)
version = __version__


def get_version_string() -> str:
return __version__
32 changes: 22 additions & 10 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[build-system]
requires = ["setuptools>=63.0"]
build-backend = "setuptools.build_meta"
requires = ["hatchling>1.24","setuptools>=65.0","hatch-requirements-txt>=0.4.1"]
build-backend = "hatchling.build"

[project]
name = "pymongo"
Expand Down Expand Up @@ -46,16 +46,27 @@ Documentation = "https://pymongo.readthedocs.io"
Source = "https://github.com/mongodb/mongo-python-driver"
Tracker = "https://jira.mongodb.org/projects/PYTHON/issues"

[tool.setuptools.dynamic]
version = {attr = "pymongo._version.__version__"}
# Used to call hatch_build.py
[tool.hatch.build.hooks.custom]

[tool.setuptools.packages.find]
include = ["bson","gridfs", "pymongo"]
[tool.hatch.version]
path = "pymongo/_version.py"

[tool.setuptools.package-data]
bson=["py.typed", "*.pyi"]
pymongo=["py.typed", "*.pyi"]
gridfs=["py.typed", "*.pyi"]
[tool.hatch.build.targets.wheel]
packages = ["bson","gridfs", "pymongo"]

[tool.hatch.metadata.hooks.requirements_txt]
files = ["requirements.txt"]

[tool.hatch.metadata.hooks.requirements_txt.optional-dependencies]
aws = ["requirements/aws.txt"]
docs = ["requirements/docs.txt"]
encryption = ["requirements/encryption.txt"]
gssapi = ["requirements/gssapi.txt"]
ocsp = ["requirements/ocsp.txt"]
snappy = ["requirements/snappy.txt"]
test = ["requirements/test.txt"]
zstd = ["requirements/zstd.txt"]

[tool.pytest.ini_options]
minversion = "7"
Expand Down Expand Up @@ -169,6 +180,7 @@ dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?)|dummy.*)$"
"UP031", "F401", "B023", "F811"]
"tools/*.py" = ["T201"]
"green_framework_test.py" = ["T201"]
"hatch_build.py" = ["S"]

[tool.coverage.run]
branch = true
Expand Down
26 changes: 1 addition & 25 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,32 +136,8 @@ def build_extension(self, ext):
)
ext_modules = []


def parse_reqs_file(fname):
with open(fname) as fid:
lines = [li.strip() for li in fid.readlines()]
return [li for li in lines if li and not li.startswith("#")]


dependencies = parse_reqs_file("requirements.txt")

extras_require = dict(
aws=parse_reqs_file("requirements/aws.txt"),
encryption=parse_reqs_file("requirements/encryption.txt"),
gssapi=parse_reqs_file("requirements/gssapi.txt"),
ocsp=parse_reqs_file("requirements/ocsp.txt"),
snappy=parse_reqs_file("requirements/snappy.txt"),
# 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=parse_reqs_file("requirements/zstd.txt"),
test=parse_reqs_file("requirements/test.txt"),
)

setup(
cmdclass={"build_ext": custom_build_ext},
install_requires=dependencies,
extras_require=extras_require,
ext_modules=ext_modules,
packages=["bson", "pymongo", "gridfs"],
) # type:ignore
9 changes: 9 additions & 0 deletions test/test_pymongo.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,22 @@
from test import unittest

import pymongo
from pymongo._version import get_version_tuple


class TestPyMongo(unittest.TestCase):
def test_mongo_client_alias(self):
# Testing that pymongo module imports mongo_client.MongoClient
self.assertEqual(pymongo.MongoClient, pymongo.mongo_client.MongoClient)

def test_get_version_tuple(self):
self.assertEqual(get_version_tuple("4.8.0.dev1"), (4, 8, 0, ".dev1"))
self.assertEqual(get_version_tuple("4.8.1"), (4, 8, 1))
self.assertEqual(get_version_tuple("5.0.0rc1"), (5, 0, 0, "rc1"))
self.assertEqual(get_version_tuple("5.0"), (5, 0))
with self.assertRaises(ValueError):
get_version_tuple("5")


if __name__ == "__main__":
unittest.main()
8 changes: 8 additions & 0 deletions tools/fail_if_no_c.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@
import pymongo # noqa: E402

if not pymongo.has_c() or not bson.has_c():
try:
from pymongo import _cmessage # type:ignore[attr-defined] # noqa: F401
except Exception as e:
print(e)
try:
from bson import _cbson # type:ignore[attr-defined] # noqa: F401
except Exception as e:
print(e)
sys.exit("could not load C extensions")

if os.environ.get("ENSURE_UNIVERSAL2") == "1":
Expand Down
13 changes: 0 additions & 13 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ envlist =
doc-test,
# Linkcheck sphinx docs
linkcheck
# Check the sdist integrity.
manifest

labels = # Use labels and -m instead of -e so that tox -m <label> fails instantly if the label does not exist
test = test
Expand All @@ -51,7 +49,6 @@ labels = # Use labels and -m instead of -e so that tox -m <label> fails instantl
linkcheck = linkcheck
test-mockupdb = test-mockupdb
aws-secrets = aws-secrets
manifest = manifest

[testenv]
package = editable
Expand All @@ -71,8 +68,6 @@ commands =
description = run tests using run-tests.sh Evergreen script
passenv = *
extras = test
deps =
setuptools
allowlist_externals =
bash
commands =
Expand Down Expand Up @@ -184,14 +179,6 @@ allowlist_externals =
commands =
{[testenv:test]commands} ./test/mockupdb

[testenv:manifest]
description = ensure the sdist manifest is correct
skip_install = true
deps =
check-manifest
commands =
python -m check_manifest -v

[testenv:setup-encryption]
description = set up encryption assets and servers
skip_install = true
Expand Down

0 comments on commit d693ccf

Please sign in to comment.