module(
    name = "rules_python",
    version = "1.7.0",
    compatibility_level = 1,
)

bazel_dep(name = "bazel_features", version = "1.21.0")
bazel_dep(name = "bazel_skylib", version = "1.8.2")
bazel_dep(name = "rules_cc", version = "0.1.5")
bazel_dep(name = "platforms", version = "0.0.11")

# Those are loaded only when using py_proto_library
# Use py_proto_library directly from protobuf repository
bazel_dep(name = "protobuf", version = "29.0-rc2", repo_name = "com_google_protobuf")

rules_python_config = use_extension("//python/extensions:config.bzl", "config")
use_repo(
    rules_python_config,
    "pypi__build",
    "pypi__click",
    "pypi__colorama",
    "pypi__importlib_metadata",
    "pypi__installer",
    "pypi__more_itertools",
    "pypi__packaging",
    "pypi__pep517",
    "pypi__pip",
    "pypi__pip_tools",
    "pypi__pyproject_hooks",
    "pypi__setuptools",
    "pypi__tomli",
    "pypi__wheel",
    "pypi__zipp",
    "rules_python_internal",
)

# We need to do another use_extension call to expose the "pythons_hub"
# repo.
python = use_extension("//python/extensions:python.bzl", "python")

# The default toolchain to use if nobody configures a toolchain.
# NOTE: This is not a stable version. It is provided for convenience, but will
# change frequently to track the most recent Python version.
# NOTE: The root module can override this.
# NOTE: There must be a corresponding `python.toolchain()` call for the version
# specified here.
python.defaults(
    python_version = "3.11",
)
python.toolchain(
    python_version = "3.11",
)
use_repo(
    python,
    "python_3_11",
    "pythons_hub",
    python = "python_versions",
)

# This call registers the Python toolchains.
register_toolchains("@pythons_hub//:all")

#####################
# Install twine for our own runfiles wheel publishing and allow bzlmod users to use it.

pip = use_extension("//python/extensions:pip.bzl", "pip")

# NOTE @aignas 2025-07-06: we define these platforms to keep backwards compatibility with the
# current `experimental_index_url` implementation. Whilst we stabilize the API this list may be
# updated with a mention in the CHANGELOG.
[
    pip.default(
        arch_name = cpu,
        config_settings = [
            "@platforms//cpu:{}".format(cpu),
            "@platforms//os:linux",
            "//python/config_settings:_is_py_freethreaded_{}".format(
                "yes" if freethreaded else "no",
            ),
        ],
        env = {"platform_version": "0"},
        marker = "python_version >= '3.13'" if freethreaded else "",
        os_name = "linux",
        platform = "linux_{}{}".format(cpu, freethreaded),
        whl_abi_tags = ["cp{major}{minor}t"] if freethreaded else [
            "abi3",
            "cp{major}{minor}",
        ],
        whl_platform_tags = [
            "linux_{}".format(cpu),
            "manylinux_*_{}".format(cpu),
        ],
    )
    for cpu in [
        "x86_64",
        "aarch64",
    ]
    for freethreaded in [
        "",
        "_freethreaded",
    ]
]

[
    pip.default(
        arch_name = cpu,
        config_settings = [
            "@platforms//cpu:{}".format(cpu),
            "@platforms//os:osx",
            "//python/config_settings:_is_py_freethreaded_{}".format(
                "yes" if freethreaded else "no",
            ),
        ],
        # We choose the oldest non-EOL version at the time when we release `rules_python`.
        # See https://endoflife.date/macos
        env = {"platform_version": "14.0"},
        marker = "python_version >= '3.13'" if freethreaded else "",
        os_name = "osx",
        platform = "osx_{}{}".format(cpu, freethreaded),
        whl_abi_tags = ["cp{major}{minor}t"] if freethreaded else [
            "abi3",
            "cp{major}{minor}",
        ],
        whl_platform_tags = [
            "macosx_*_{}".format(suffix)
            for suffix in platform_tag_cpus
        ],
    )
    for cpu, platform_tag_cpus in {
        "aarch64": [
            "universal2",
            "arm64",
        ],
        "x86_64": [
            "universal2",
            "x86_64",
        ],
    }.items()
    for freethreaded in [
        "",
        "_freethreaded",
    ]
]

[
    pip.default(
        arch_name = cpu,
        config_settings = [
            "@platforms//cpu:{}".format(cpu),
            "@platforms//os:windows",
            "//python/config_settings:_is_py_freethreaded_{}".format(
                "yes" if freethreaded else "no",
            ),
        ],
        env = {"platform_version": "0"},
        marker = "python_version >= '3.13'" if freethreaded else "",
        os_name = "windows",
        platform = "windows_{}{}".format(cpu, freethreaded),
        whl_abi_tags = ["cp{major}{minor}t"] if freethreaded else [
            "abi3",
            "cp{major}{minor}",
        ],
        whl_platform_tags = whl_platform_tags,
    )
    for cpu, whl_platform_tags in {
        "x86_64": ["win_amd64"],
    }.items()
    for freethreaded in [
        "",
        "_freethreaded",
    ]
]

[
    pip.default(
        arch_name = cpu,
        config_settings = [
            "@platforms//cpu:{}".format(cpu),
            "@platforms//os:windows",
            "//python/config_settings:_is_py_freethreaded_{}".format(
                "yes" if freethreaded else "no",
            ),
        ],
        env = {"platform_version": "0"},
        marker = "python_version >= '3.13'" if freethreaded else "python_version >= '3.11'",
        os_name = "windows",
        platform = "windows_{}{}".format(cpu, freethreaded),
        whl_abi_tags = ["cp{major}{minor}t"] if freethreaded else [
            "abi3",
            "cp{major}{minor}",
        ],
        whl_platform_tags = whl_platform_tags,
    )
    for cpu, whl_platform_tags in {
        "aarch64": ["win_arm64"],
    }.items()
    for freethreaded in [
        "",
        "_freethreaded",
    ]
]

pip.parse(
    hub_name = "rules_python_publish_deps",
    python_version = "3.11",
    requirements_by_platform = {
        "//tools/publish:requirements_darwin.txt": "osx_*",
        "//tools/publish:requirements_linux.txt": "linux_*",
        "//tools/publish:requirements_windows.txt": "windows_*",
    },
)
use_repo(pip, "rules_python_publish_deps")

# Not a dev dependency to allow usage of //sphinxdocs code, which refers to stardoc repos.
bazel_dep(name = "stardoc", version = "0.7.2", repo_name = "io_bazel_stardoc")

# ===== DEV ONLY DEPS AND SETUP BELOW HERE =====
bazel_dep(name = "rules_bazel_integration_test", version = "0.27.0", dev_dependency = True)
bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)
bazel_dep(name = "rules_shell", version = "0.3.0", dev_dependency = True)
bazel_dep(name = "rules_multirun", version = "0.9.0", dev_dependency = True)
bazel_dep(name = "bazel_ci_rules", version = "1.0.0", dev_dependency = True)
bazel_dep(name = "rules_pkg", version = "1.0.1", dev_dependency = True)
bazel_dep(name = "other", version = "0", dev_dependency = True)
bazel_dep(name = "another_module", version = "0", dev_dependency = True)

# Extra gazelle plugin deps so that WORKSPACE.bzlmod can continue including it for e2e tests.
# We use `WORKSPACE.bzlmod` because it is impossible to have dev-only local overrides.
bazel_dep(name = "rules_go", version = "0.41.0", dev_dependency = True, repo_name = "io_bazel_rules_go")
bazel_dep(name = "rules_python_gazelle_plugin", version = "0", dev_dependency = True)
bazel_dep(name = "gazelle", version = "0.40.0", dev_dependency = True, repo_name = "bazel_gazelle")

internal_dev_deps = use_extension(
    "//python/private:internal_dev_deps.bzl",
    "internal_dev_deps",
    dev_dependency = True,
)
use_repo(
    internal_dev_deps,
    "buildkite_config",
    "implicit_namespace_ns_sub1",
    "implicit_namespace_ns_sub2",
    "rules_python_runtime_env_tc_info",
    "somepkg_with_build_files",
    "whl_with_build_files",
)

dev_rules_python_config = use_extension(
    "//python/extensions:config.bzl",
    "config",
    dev_dependency = True,
)
dev_rules_python_config.add_transition_setting(
    # Intentionally add a setting already present for testing
    setting = "//python/config_settings:python_version",
)
dev_rules_python_config.add_transition_setting(
    setting = "//tests/multi_pypi:external_deps_name",
)

# Add gazelle plugin so that we can run the gazelle example as an e2e integration
# test and include the distribution files.
local_path_override(
    module_name = "rules_python_gazelle_plugin",
    path = "gazelle",
)

local_path_override(
    module_name = "other",
    path = "tests/modules/other",
)

local_path_override(
    module_name = "another_module",
    path = "tests/modules/another_module",
)

dev_python = use_extension(
    "//python/extensions:python.bzl",
    "python",
    dev_dependency = True,
)
dev_python.override(
    register_all_versions = True,
)

# For testing an arbitrary runtime triggered by a custom flag.
# See //tests/toolchains:custom_platform_toolchain_test
dev_python.single_version_platform_override(
    platform = "linux-x86-install-only-stripped",
    python_version = "3.13.1",
    sha256 = "56817aa976e4886bec1677699c136cb01c1cdfe0495104c0d8ef546541864bbb",
    target_compatible_with = [
        "@platforms//os:linux",
        "@platforms//cpu:x86_64",
    ],
    target_settings = [
        "@@//tests/support:is_custom_runtime_linux-x86-install-only-stripped",
    ],
    urls = ["https://github.com/astral-sh/python-build-standalone/releases/download/20250115/cpython-3.13.1+20250115-x86_64-unknown-linux-gnu-install_only_stripped.tar.gz"],
)

dev_pip = use_extension(
    "//python/extensions:pip.bzl",
    "pip",
    dev_dependency = True,
)

[
    dev_pip.parse(
        download_only = True,
        experimental_index_url = "https://pypi.org/simple",
        hub_name = "dev_pip",
        parallel_download = False,
        python_version = python_version,
        requirements_lock = "//docs:requirements.txt",
    )
    for python_version in [
        "3.9",
        "3.10",
        "3.11",
        "3.12",
        "3.13",
        "3.14",
    ]
]

dev_pip.parse(
    download_only = True,
    experimental_index_url = "https://pypi.org/simple",
    hub_name = "pypiserver",
    python_version = "3.11",
    requirements_lock = "//examples/wheel:requirements_server.txt",
)
dev_pip.parse(
    hub_name = "pypi_alpha",
    python_version = "3.11",
    requirements_lock = "//tests/multi_pypi/alpha:requirements.txt",
)
dev_pip.parse(
    hub_name = "pypi_beta",
    python_version = "3.11",
    requirements_lock = "//tests/multi_pypi/beta:requirements.txt",
)
use_repo(dev_pip, "dev_pip", "pypi_alpha", "pypi_beta", "pypiserver")

# Bazel integration test setup below

bazel_binaries = use_extension(
    "@rules_bazel_integration_test//:extensions.bzl",
    "bazel_binaries",
    dev_dependency = True,
)

# Keep in sync with //:version.bzl
bazel_binaries.local(
    name = "self",
    path = "tests/integration/bazel_from_env",
)
bazel_binaries.download(version = "7.4.1")
bazel_binaries.download(version = "8.0.0")

# For now, don't test with rolling, because that's Bazel 9, which is a ways
# away.
# bazel_binaries.download(version = "rolling")
use_repo(
    bazel_binaries,
    "bazel_binaries",
    # These don't appear necessary, but are reported as direct dependencies
    # that should be use_repo()'d, so we add them as requested
    "bazel_binaries_bazelisk",
    "build_bazel_bazel_7_4_1",
    "build_bazel_bazel_8_0_0",
    # "build_bazel_bazel_rolling",
    "build_bazel_bazel_self",
)

# TODO @aignas 2025-01-27: should this be moved to `//python/extensions:uv.bzl` or should
# it stay as it is? I think I may prefer to move it.
uv = use_extension("//python/uv:uv.bzl", "uv")

# Here is how we can define platforms for the `uv` binaries - this will affect
# all of the downstream callers because we are using the extension without
# `dev_dependency = True`.
uv.default(
    base_url = "https://github.com/astral-sh/uv/releases/download",
    manifest_filename = "dist-manifest.json",
    version = "0.6.3",
)
uv.default(
    compatible_with = [
        "@platforms//os:macos",
        "@platforms//cpu:aarch64",
    ],
    platform = "aarch64-apple-darwin",
)
uv.default(
    compatible_with = [
        "@platforms//os:linux",
        "@platforms//cpu:aarch64",
    ],
    platform = "aarch64-unknown-linux-gnu",
)
uv.default(
    compatible_with = [
        "@platforms//os:linux",
        "@platforms//cpu:ppc",
    ],
    platform = "powerpc64-unknown-linux-gnu",
)
uv.default(
    compatible_with = [
        "@platforms//os:linux",
        "@platforms//cpu:ppc64le",
    ],
    platform = "powerpc64le-unknown-linux-gnu",
)
uv.default(
    compatible_with = [
        "@platforms//os:linux",
        "@platforms//cpu:s390x",
    ],
    platform = "s390x-unknown-linux-gnu",
)
uv.default(
    compatible_with = [
        "@platforms//os:linux",
        "@platforms//cpu:riscv64",
    ],
    platform = "riscv64-unknown-linux-gnu",
)
uv.default(
    compatible_with = [
        "@platforms//os:macos",
        "@platforms//cpu:x86_64",
    ],
    platform = "x86_64-apple-darwin",
)
uv.default(
    compatible_with = [
        "@platforms//os:windows",
        "@platforms//cpu:x86_64",
    ],
    platform = "x86_64-pc-windows-msvc",
)
uv.default(
    compatible_with = [
        "@platforms//os:linux",
        "@platforms//cpu:x86_64",
    ],
    platform = "x86_64-unknown-linux-gnu",
)
use_repo(uv, "uv")

register_toolchains("@uv//:all")

uv_dev = use_extension(
    "//python/uv:uv.bzl",
    "uv",
    dev_dependency = True,
)
uv_dev.configure(
    version = "0.6.2",
)
