[project]
name = "mdb-python-deps"
version = "1.0.0"
requires-python = ">=3.13,<4.0"
description = "MongoDB python dependencies"
authors = [ { name = "MongoDB" } ]
readme = "README.md"
# These packages are included as a TODO if we want to run resmoke with pex
# Currently this does nothing
packages = [
    { include = "buildscripts/resmoke.py" },
    { include = "buildscripts/mongosymb.py" },
    { include = "buildscripts/build_system_options.py" },
    { include = "buildscripts/resmokelib" },
    { include = "buildscripts/idl" },
    { include = "buildscripts/util" },
]
dependencies = [
    "networkx",                               # This is also used as a part of build_metrics so it is sort of required
    "pyright==1.1.393",
    "faker==37.1.0",
    "pymongo==4.12.0",
]

# Optional extras. These mirror the prior Poetry `optional = true` entries
# under [tool.poetry.dependencies] — opt-in for libdeps-graph analysis, not
# installed by `uv sync --all-groups`. Install with `uv sync --extra libdeps`
# or `pip install '.[libdeps]'`. Keeping them out of [project.dependencies]
# avoids forcing an `lxml` sdist build on s390x / ppc64le where the
# manylinux wheel set doesn't cover cp313.
[project.optional-dependencies]
libdeps = [
    "flask",
    "flask-cors>=4.0.2",
    "lxml",
    "eventlet",
    "gevent",
    "progressbar2",
    "cxxfilt",
    "pympler",
]

# This entrypoint is included as a TODO if we want to run resmoke with pex
# Currently this does nothing
[project.scripts]
resmoke = "buildscripts.resmoke:entrypoint"

# PEP 735 dependency groups. Mirrors the prior [tool.poetry.group.*] layout.
# Install all groups: `uv sync --all-groups`.
# Install a single group: `uv sync --only-group lint`.
# Exclude a group:        `uv sync --all-groups --no-group powercycle-incompatible`.
[dependency-groups]
aws = [
    "boto3>=1.34.156,<2",
    "botocore>=1.34.156,<2",
]

# Deps the bazel wrapper hook needs at import time, before any other
# tooling has run (see bazel/wrapper_hook/install_modules.py). This group
# is the single source of truth for that list: the wrapper bootstraps
# itself with `uv sync --only-group wrapper-hook --locked --inexact`.
# Constraints deliberately mirror the pins these packages carry in their
# other groups so resolution stays unified.
wrapper-hook = [
    "retry>=0.9.2,<1",
    "GitPython>=3.1.43,<4",
    "requests>=2.32.3,<3",
    "timeout-decorator==0.5.0",
    "boto3>=1.34.156,<2",
    "PyYAML>=6.0.2,<7",
    "pymongo==4.12.0",
    "opentelemetry-api",
    "opentelemetry-sdk",
    "opentelemetry-exporter-otlp-proto-grpc ; platform_machine != 's390x' and platform_machine != 'ppc64le'",
]

build-metrics = [
    "jsonschema>=4.23.0,<5",
    "psutil>=6.0.0,<7",
    "memory-profiler>=0.61.0,<0.62",
    "puremagic>=1.26,<1.27",
    "tabulate>=0.9.0,<0.10",
]

compile = [
    "ct3==3.4.0.post5",                       # Renamed from cheetah3
    "packaging>=25.0,<26",
    "regex>=2024.11.6,<2025",
    "setuptools>=80.9.0,<81",
    "wheel==0.45.0",
]

core = [
    "psutil>=6.0.0,<7",
    "pymongo==4.12.0",
    "PyYAML>=6.0.2,<7",
    "types-PyYAML>=6.0.12.20240808,<7",
    "requests>=2.32.3,<3",
    "typing-extensions>=4.12.2,<5",
    "typer>=0.12.3,<0.13",
    "tenacity>=9.0.0,<10",
]

# rapidyaml is broken on atlas distros with powercycle. The powercycle remote
# bootstrap excludes this group via `uv sync --no-group powercycle-incompatible`.
# The S3 wheel index is configured under [[tool.uv.index]] below; regenerate
# it via `buildscripts/mongo_rapidyaml_builds/regenerate_simple_index.py`
# after publishing new wheels so uv can persist `#sha256=<hex>` hashes into
# uv.lock (rules_pycross requires them).
powercycle-incompatible = [
    "rapidyaml==0.9.0.post0 ; python_version == '3.13'",
]

export = [
    "pipx==1.6.0",
    # TODO: Add in pex as we move forward with this
    # "pex>=2.1.137,<3",
    # uv is referenced by buildscripts/uv_lock_check.py via `python -m uv`.
    # The canonical pin lives at buildscripts/uv_version.txt — all shell
    # / Docker / Python installers read it directly. TOML can't do
    # command-substitution, so this string is checked for parity with
    # uv_version.txt by buildscripts/uv_lock_check.py.
    "uv==0.11.13",
]

# bazel_rules_mongo (previously had its own poetry.lock/pyproject.toml). Its
# BUILD.bazel files reference `@poetry//:<pkg>` which is repo-mapped to the
# outer workspace's `@pypi` — see the `local_repository(..., repo_mapping=...)`
# call in //WORKSPACE.bazel. Every dep in this group must therefore also be
# reachable from the pycross hub, which is automatic since it comes from the
# same uv.lock.
bazel_rules_mongo = [
    "pyyaml>=6.0.2,<7",
    "retry>=0.9.2,<1",
    "gitpython>=3.1.44,<4",
    "requests>=2.32.5,<3",
    "structlog>=25.5.0,<26",
]

evergreen = [
    # click 8.2 changed Parameter.make_metavar()'s signature in a way that
    # broke typer 0.12.x (the version pinned in the `core` group below).
    # Cap at <8.2 until typer is bumped to a click-8.2+ compatible release
    # (typer >= 0.15).
    "click>=8.1.7,<8.2",
    "inject>=5.2.1,<6",
    "GitPython>=3.1.43,<4",
    "pydantic>=2,<3",
    # pydantic 2 moved `BaseSettings` into the separate pydantic-settings
    # package; only buildscripts/client/jiraclient.py imports it.
    "pydantic-settings>=2,<3",
    "structlog>=24.4.0,<26",
    # pathspec is imported directly by buildscripts/validate_commit_message.py
    # for gitignore-style pattern matching. Previously arrived transitively
    # via `poetry` (which uses it internally); making it a direct dep here
    # so the Bazel graph stays honest under pycross now that Poetry itself
    # has been removed.
    "pathspec>=0.12,<1",
]

external-auth = [
    # Dependencies of ldaptor
    "passlib>=1.7.4,<2",
    "pyOpenSSL>=25.0.0,<26",
    "pyparsing>=2.4.7,<3",
    "service_identity>=18.1.0,<19",
    "twisted>=26.4.0,<27",
    "twisted-iocpsupport>=1.0.4,<2 ; sys_platform == 'win32'",
    "zope.interface>=8.1.1,<9",
    "ldaptor==19.0.0",
]

idl = [
    # `unittest-xml-reporting` pulls in lxml transitively; lxml ships no
    # s390x cp313 wheel and its sdist fails to build against RHEL9 s390x's
    # libxml2 (xmlHashScanner typedef mismatch). XML-format test reports
    # aren't needed on s390x archive_dist_test; mark it platform-conditional.
    "unittest-xml-reporting==3.2.0 ; platform_machine != 's390x'",
    "packaging>=25.0,<26",
]

jira-client = [
    "jira>=3.10.5,<4",
    "requests-oauth<=0.4.1",
    "PyJWT>=2.12.0,<3",
    # python-dateutil is imported directly by
    # buildscripts/monitor_build_status/jira_service.py to parse ISO-8601
    # datetimes returned by the Jira REST API. Previously arrived
    # transitively via `jira` under Poetry; making it a direct dep here so
    # the Bazel graph stays honest under pycross.
    "python-dateutil>=2.9,<3",
    # We are omitting pycrypto based on https://github.com/pycontribs/jira/pull/629
]

lint = [
    # Note: These versions are checked by python modules in buildscripts/linter/
    "GitPython>=3.1.7,<4",
    "mypy>=1.11.1,<2",
    "structlog>=24.4.0,<26",
    "yamllint>=1.35.1,<2",
    "types-setuptools>=80.9.0,<81",
    "types-requests>=2.32.0.20240712,<3",
    "tqdm",
    "colorama>=0.4.6,<0.5",
    "evergreen-lint>=0.1.10,<0.2",
    "ruff>=0.6.7,<0.7",
    "license-expression>=30.4.4,<31",
]

modules_poc = [
    "codeowners>=0.8.0,<0.9 ; platform_machine != 's390x' and platform_machine != 'ppc64le'",
    "progressbar2>=4.4.2,<5 ; platform_machine != 's390x' and platform_machine != 'ppc64le'",
    "textual[syntax]>=3.0.0,<4 ; platform_machine != 's390x' and platform_machine != 'ppc64le'",
    "tree-sitter>=0.24.0,<0.25 ; platform_machine != 's390x' and platform_machine != 'ppc64le'",
    "tree-sitter-cpp>=0.23.4,<0.24 ; platform_machine != 's390x' and platform_machine != 'ppc64le'",
    "pyzstd>=0.16.2,<0.17 ; platform_machine != 's390x' and platform_machine != 'ppc64le'",
    "cffi>=2.0.0,<3",
]

platform = [
    "pypiwin32>=223 ; sys_platform == 'win32'",
    "pywin32>=225 ; sys_platform == 'win32'",
    "python-msilib>=0.5.0,<0.6 ; sys_platform == 'win32' and python_version >= '3.13'",
    # cryptography 41+ ships a Rust extension and PyPI carries no
    # s390x / ppc64le wheels for it (only manylinux/musllinux x86_64 +
    # aarch64 + armv7l). For those archs we host pre-built manylinux_2_28
    # wheels in mdb-build-public — see [tool.uv.sources] at the bottom of
    # this file and buildscripts/mongo_cryptography_builds/README.md.
    # Pinned to ==44.0.2 (rather than >=44.0.2,<45) so the version
    # uv picks on every platform matches the version of the wheels we've
    # uploaded; bumping requires rebuilding both s390x and ppc64le wheels
    # first (see the README).
    "cryptography==44.0.2",
]

testing = [
    "bazel-runfiles>=1.8.3,<2",
    "curatorbin>=1.2.4,<2",
    # Pinned to exactly 5.29.3 because `buildscripts/bazel_spawn_pb2.py`
    # (protoc-generated) hardcodes `_runtime_version.ValidateProtobufRuntimeVersion(5, 29, 3, ...)`
    # — it validates at import time that the installed protobuf runtime
    # matches the version protoc used to generate the file. Any other
    # major version raises. Matches master's pin. Regenerate the _pb2.py
    # via buildscripts/generate_bazel_spawn_pb2.py if bumping.
    "protobuf==5.29.3",
    # Matches master's mongodb-forks/PyKMIP pin. See [tool.uv.sources]
    # further down for the URL source configuration; rules_pycross's URL
    # source handling is enabled by the uv_translator_url_source patch
    # applied in MODULE.bazel.
    "pykmip",
    "pyOpenSSL>=25.0.0,<26",
    "kafka-python>=2.0.2,<3",
    "avro-python3>=1.10.2,<2",
    # evergreen-py upstream caps at python<3.14; project is constrained to
    # python 3.13 so we only need the marker for forward-compatibility.
    "evergreen-py>=3.19.2,<4 ; python_version < '3.14'",
    "mock>=5.1.0,<6",
    "shrub-py>=3.1.4,<4",
    "ocspresponder>=0.5.0,<0.6",
    "flask>=2.3.3,<3",
    "ocspbuilder>=0.10.2,<0.11",
    "ecdsa>=0.19.0,<0.20",
    "asn1crypto>=1.5.1,<2",
    "toml>=0.10.2,<0.11",
    "filelock>=3.18.0,<4",
    "numpy==2.2.6 ; platform_machine != 's390x' and platform_machine != 'ppc64le'",
    "oscrypto>=1.3.0,<2 ; platform_machine != 's390x' and platform_machine != 'ppc64le'",
    # Werkzeug is needed for ocsp tests in ocsp_mock.py.
    "Werkzeug<=3.1.6",
    "PyGithub>=1.58,<2",
    "urllib3>=2.7.0,<3",
    "distro>=1.9.0,<2",
    "dnspython>=2.6.1,<3",
    "proxy-protocol>=0.11.3,<0.12",
    "pkce>=1.0.3,<2",
    "pexpect>=4.9.0,<5",
    "oauthlib>=3.1.1,<4",
    "requests-oauthlib>=2.0.0,<3",
    "packaging>=25.0,<26",
    "docker>=7.1.0,<8",
    "mongomock>=4.1.2,<5",
    "pyjwt>=2.12.0,<3",
    "selenium>=4.23.1,<5",
    "geckodriver-autoinstaller>=0.1.0,<0.2",
    "retry>=0.9.2,<1",
    "gdbmongo>=0.16.0,<0.17",
    "googleapis-common-protos>=1.63.2,<2",
    "google-api-python-client>=2.19.0,<3",
    "google-auth-oauthlib>=1.2.1,<2",
    # `gcovr` pulls in lxml transitively; lxml ships no s390x cp313 wheel
    # (see the unittest-xml-reporting comment in the idl group). Code-
    # coverage builds aren't run on s390x, so excluding it there is safe.
    "gcovr==7.2 ; platform_machine != 's390x'",
    "opentelemetry-api",
    "opentelemetry-sdk",
    "opentelemetry-exporter-otlp-proto-common",
    "opentelemetry-exporter-otlp-proto-grpc ; platform_machine != 's390x' and platform_machine != 'ppc64le'",
    "opentelemetry-exporter-otlp-proto-http ; platform_machine != 's390x' and platform_machine != 'ppc64le'",
    "timeout-decorator==0.5.0",
]

# ---------------------------------------------------------------------------
# uv-specific config
# ---------------------------------------------------------------------------

# This project is the dev/build toolbelt, not a published package. Tell uv not
# to try to build it (mirrors the prior Poetry `package-mode = false`).
[tool.uv]
package = false

# Custom wheel index for rapidyaml. Mirrors the prior
# [[tool.poetry.source]] entry; `explicit = true` matches `priority = "explicit"`
# in Poetry — uv will only consult this index for packages that opt in via
# [tool.uv.sources].
[[tool.uv.index]]
name = "mdb-build-public"
url = "https://mdb-build-public.s3.amazonaws.com/rapidyaml_wheels/simple/"
explicit = true

[tool.uv.sources]
rapidyaml = { index = "mdb-build-public" }
# Match master's Poetry pin (mongodb-forks/PyKMIP @ c48cb016). Declared as a
# direct URL to the GitHub archive tarball for that rev — rather than a git
# source — so uv records the tarball's sha256 in uv.lock and rules_pycross
# (via the uv_translator_url_source patch) can generate a hash-verified
# http_file for it without any translation-time network fetch. If GitHub
# ever re-rolls its archive tarballs (changing the bytes), `uv lock` must be
# re-run to refresh the committed hash; alternatively mirror the sdist to
# mdb-build-public like the cryptography wheels.
pykmip = { url = "https://github.com/mongodb-forks/PyKMIP/archive/c48cb01635819e478b573e3245ef840a11d78865.tar.gz" }
# Pre-built cryptography wheels for s390x / ppc64le. PyPI carries no
# wheels for those archs and the sdist needs a Rust toolchain that
# pip.parse's hermetic sandbox can't see — see
# buildscripts/mongo_cryptography_builds/README.md for the build /
# upload procedure. uv picks the URL whose marker matches the current
# platform; on every other arch it falls back to PyPI (where 44.0.2 is
# available as the standard cp37-abi3 wheel).
cryptography = [
    { url = "https://mdb-build-public.s3.amazonaws.com/cryptography_wheels/cryptography-44.0.2-cp37-abi3-manylinux_2_28_s390x.whl", marker = "platform_machine == 's390x'" },
    { url = "https://mdb-build-public.s3.amazonaws.com/cryptography_wheels/cryptography-44.0.2-cp37-abi3-manylinux_2_28_ppc64le.whl", marker = "platform_machine == 'ppc64le'" },
]

# ---------------------------------------------------------------------------
# Tool-specific config (unchanged from Poetry era)
# ---------------------------------------------------------------------------

[tool.ruff]
force-exclude = true
extend-exclude = [
    "src/third_party",
    # protoc-generated files. Their `from google.protobuf import X_pb2` lines
    # look "unused" to static analyzers but are load-order-critical (they
    # register descriptor types with the global protobuf pool via import-time
    # side effects), and their formatting is dictated by the protobuf
    # compiler — not something we should reflow with `ruff format`. Applies
    # to master's `buildscripts/bazel_spawn_pb2.py` and any future generated
    # protobuf files anywhere in the tree.
    "**/*_pb2.py",
]

line-length = 100
target-version = "py313"

[tool.ruff.lint]
extend-select = [
    "I",        # isort
    "UP006",    # non-pep585-annotation
    "W605",     # invalid-escape-sequence
]
ignore = [
    "E402", # module-import-not-at-top-of-file
    "E721", # type-comparison
    "E722", # bare-except
    "E741", # ambiguous-variable-name
    "F402", # import-shadowed-by-loop-var
    "F403", # undefined-local-with-import-star
    "F405", # undefined-local-with-import-star-usage
    "F811", # redefined-while-unused
    "F821", # undefined-name
    "F822", # undefined-export
    ]

[tool.ruff.lint.per-file-ignores]
# This file needs to support Python 3.5+ for old OS package testing
"buildscripts/package_test/package_test_internal.py" = ["UP"]

# This file needs to support old Python versions, and so it cannot use newer type annotations.
"buildscripts/evergreen_activate_gen_tasks.py" = ["UP006", "UP035"]

[tool.ruff.lint.isort]
known-first-party = ["buildscripts", "buildscripts/idl", "evergreen", "tools"]

[tool.pyright]
include = [
    "buildscripts",
    "src"
]
exclude = [
    "**/third_party/**",
    "**/external/**"
]
pythonVersion  = "3.13"

# These should be set to "error" for basic functionality
reportInvalidTypeForm = "none"
reportMissingImports = "none"
reportUndefinedVariable = "none"
reportAbstractUsage = "error"
reportAssertTypeFailure = "error"
reportInconsistentOverload = "error"
reportInvalidTypeArguments = "none"
reportNoOverloadImplementation = "error"
reportOptionalCall = "none"
reportOptionalContextManager = "error"
reportRedeclaration = "none"
reportUnboundVariable = "none"
reportUnhashable = "none"
reportUnusedCoroutine = "error"
reportUnusedExcept = "error"

# These should be set to "warning" or "error" for standard checks
reportArgumentType = "none"
reportAssignmentType = "none"
reportAttributeAccessIssue = "none"
reportCallIssue = "none"
reportGeneralTypeIssues = "none"
reportIndexIssue = "none"
reportOperatorIssue = "none"
reportOptionalSubscript = "none"
reportOptionalMemberAccess = "none"
reportOptionalIterable = "none"
reportOptionalOperand = "none"
reportReturnType = "none"
reportTypedDictNotRequiredAccess = "none"
reportPrivateImportUsage = "none"
reportFunctionMemberAccess = "none"
reportIncompatibleMethodOverride = "none"
reportIncompatibleVariableOverride = "none"
reportOverlappingOverload = "error"
reportPossiblyUnboundVariable = "none"

# These are additional checks for strict mode
reportMissingTypeStubs = "none"
reportAssertAlwaysTrue = "error"
reportInvalidStringEscapeSequence = "error"
reportInvalidTypeVarUse = "error"
reportSelfClsParameterName = "none"
reportUnsupportedDunderAll = "error"
reportUnusedExpression = "error"
reportWildcardImportFromLibrary = "error"
reportConstantRedefinition = "none"