rules_python icon indicating copy to clipboard operation
rules_python copied to clipboard

Error trying to use a py_library with requirements from another module

Open calliecameron opened this issue 1 year ago • 8 comments

🐞 bug report

Affected Rule

py_library

Description

With a py_library defined in one module using requirement, depending on the library from another module causes a build error.

🔬 Minimal Reproduction

Note that module2 doesn't use rules_python itself; it's depending on a library from module1 that uses rules_python.

$ cat ./module1/.bazelversion
7.0.2

$ cat ./module1/BUILD
load("@rules_python//python:pip.bzl", "compile_pip_requirements")
load("@pip//:requirements.bzl", "requirement")
load("@rules_python//python:defs.bzl", "py_library")

compile_pip_requirements(
    name = "requirements",
    requirements_in = "requirements.txt",
    requirements_txt = "requirements_lock.txt",
    tags = ["requires-network"],
)

py_library(
    name = "foo",
    srcs = ["foo.py"],
    visibility = ["//visibility:public"],
    deps = [requirement("pyyaml")],
)

$ cat ./module1/MODULE.bazel
module(
    name = "module1",
    version = "0.0.0",
)

bazel_dep(
    name = "rules_python",
    version = "0.31.0",
)

python = use_extension("@rules_python//python/extensions:python.bzl", "python")
python.toolchain(
    python_version = "3.10",
)
use_repo(python, "python_versions")

pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
pip.parse(
    hub_name = "pip",
    python_version = "3.10",
    requirements_lock = "//:requirements_lock.txt",
)
use_repo(pip, "pip")

$ cat ./module1/WORKSPACE

$ cat ./module1/foo.py
print("foo")

$ cat ./module1/requirements.txt
PyYAML == 6.0.1

$ cat ./module2/.bazelversion
7.0.2

$ cat ./module2/BUILD
sh_binary(
    name = "bar",
    srcs = ["bar.sh"],
    data = ["@module1//:foo"],
)

$ cat ./module2/MODULE.bazel
module(
    name = "module2",
    version = "0.0.0",
)

bazel_dep(
    name = "module1",
    version = "0.0.0",
)
local_path_override(
    module_name = "module1",
    path = "../module1",
)

$ cat ./module2/WORKSPACE

$ cat ./module2/bar.sh
#!/bin/bash

echo bar

🔥 Exception or Error

Preparation:

cd module1
touch requirements_lock.txt
bazel run :requirements.update
cd ../module2

The error:

$ bazel build :bar
Starting local Bazel server and connecting to it...
bazel: Entering directory `/home/callie/.cache/bazel/_bazel_callie/452a97bf58a333a814222c54dff465cc/execroot/_main/'
ERROR: /home/callie/.cache/bazel/_bazel_callie/452a97bf58a333a814222c54dff465cc/external/rules_python~0.31.0~pip~pip/pyyaml/BUILD.bazel:27:6: configurable attribute "actual" in @@rules_python~0.31.0~pip~pip//pyyaml:pkg doesn't match this configuration: No matching wheel for current configuration's Python version.

The current build configuration's Python version doesn't match any of the Python
versions available for this wheel. This wheel supports the following Python versions:
    3.10

As matched by the `@rules_python~0.31.0//python/config_settings:is_python_<version>`
configuration settings.

To determine the current configuration's Python version, run:
    `bazel config <config id>` (shown further below)
and look for
    rules_python~0.31.0//python/config_settings:python_version

If the value is missing, then the "default" Python version is being used,
which has a "null" version value and will not match version constraints.


This instance of @@rules_python~0.31.0~pip~pip//pyyaml:pkg has configuration identifier 312a038. To inspect its configuration, run: bazel config 312a038.

For more help, see https://bazel.build/docs/configurable-attributes#faq-select-choose-condition.

bazel: Leaving directory `/home/callie/.cache/bazel/_bazel_callie/452a97bf58a333a814222c54dff465cc/execroot/_main/'
ERROR: Analysis of target '//:bar' failed; build aborted: Analysis failed
INFO: Elapsed time: 5.179s, Critical Path: 0.04s
INFO: 1 process: 1 internal.
ERROR: Build did NOT complete successfully

🌍 Your Environment

Operating System:

Ubuntu 22.04

Output of bazel version:

7.0.2

Rules_python version:

0.31.0

Anything else relevant?

The example is a bit contrived (having an sh_binary with a data dep on a py_library) but is the simplest case that causes the error. In practice, I've got a py_library, used by a py_binary, used in an action in a rule, all defined in one module - and the rule being instantiated in another module. Since the py_binary is defined using the versioned rule from the python extension, I'd expect the library it calls to use that version even when used in another module.

calliecameron avatar Mar 24 '24 16:03 calliecameron

This is working as designed, kind of...

Right now you define in your module1 python 3.10 dependencies but you do not set the default toolchain there. What is more setting the default would not do much because only the root module can configure the default toolchains. Anyway, what you have in module 3.10 is a target that will correctly resolve the dependencies when the toolchain is 3.10 and when your build configuration is defining 3.10 as the default.

Your module2 sh_binary does not set this python configuration value, so python library does not know what do, because the dependencies are only registered for python 3.10. If you were using the python version aware py_binary in module2 I suspect that this error would go away. Another way would be to specify the default python version via the .bazelrc.

What is your usecase far sharing the modules?

aignas avatar Mar 25 '24 02:03 aignas

I'm writing a ruleset for markdown. Internally, parts of the ruleset are implemented in python. But that's an implementation detail - the public API of the module is a bzl file that doesn't mention python at all. Users of the module won't be writing python code, and shouldn't have to know that python is being used internally.

The actual WIP code is on the 'bazel-test' branch at https://github.com/calliecameron/markdown-makefile. Specifically:

  • there's a py_library 'metadata' here
  • which is used by the py_binary 'version' here
  • which is an implicit dependency of the rule 'md_file' here
  • which is used in an action in 'md_file' here
  • 'md_file' is exposed in the module's public API through a macro here
  • and also through a higher-level macro 'md_document' here

Users of the module depend on the module as here and call md_document as here.

When I add pydantic as a dependency to 'metadata' using 'requirement', the md_document in the user module fails to build.


Another way would be to specify the default python version via the .bazelrc

How do I do this? - what do I need to set?

This is fine as a workaround, but it would be nice if it wasn't needed, e.g. by having a versioned version of py_library, like we have for py_binary and py_test.

calliecameron avatar Mar 25 '24 08:03 calliecameron

Is there a reason why the py_binary version is not versioned? That is the place where you could enforce the 3.10 python version and the users then don't need to do anything.

See the multi-version or bzlmod examples of how one can do this. I actually needed to do exactly the same in #1572 just today. :)

aignas avatar Mar 25 '24 08:03 aignas

The py_binary is versioned, or at least it's supposed to be:

  • usage here using the wrapper loaded here
  • wrapper definition calls the real py_binary here, which is the versioned version loaded here

Or am I doing something wrong here?

calliecameron avatar Mar 25 '24 10:03 calliecameron

I think what you are doing in py_binary is correct, but it seems that the configuration might be getting dropped. Maybe you should add cfg = exec where you use the version target as the default of the attribute.

On 25 March 2024 19:04:12 GMT+09:00, Callie Cameron @.***> wrote:

The py_binary is versioned, or at least it's supposed to be:

  • usage here using the wrapper loaded here
  • wrapper definition calls the real py_binary here, which is the versioned version loaded here

Or am I doing something wrong here?

-- Reply to this email directly or view it on GitHub: https://github.com/bazelbuild/rules_python/issues/1824#issuecomment-2017633488 You are receiving this because you commented.

Message ID: @.***>

aignas avatar Mar 25 '24 11:03 aignas

I tried that (and also added executable = True) but still get the same error.

calliecameron avatar Mar 25 '24 16:03 calliecameron

FWIW, I asked about this on bazel Slack and the transitions should work correctly in this case. i am not sure why they are not working.

aignas avatar Apr 10 '24 00:04 aignas

Could you please see if this is still not working as expected with 0.32.1?

aignas avatar May 13 '24 08:05 aignas

It works now.

calliecameron avatar May 20 '24 14:05 calliecameron