rules_python icon indicating copy to clipboard operation
rules_python copied to clipboard

Problem parsing requirements.txt with mixed requirement specifiers

Open DasSkelett opened this issue 2 years ago • 0 comments

🐞 bug report

Affected Rule

pip_parse

Is this a regression?

Yes, the previous version in which this bug was not present was: 0.10.2 / pip_install

Description

After installing bazel(isk) fresh in a new VM, and upgrading rules_python to 0.27.1 for compatibility with newer pip and Python releases, and thus also switching from pip_install to pip_parse , building our project (https://github.com/freifunkMUC/wgkex) failed with below mentioned exception. I believe I traced it down to us using a mix of version specifiers and no version specifiers in the requirements.txt, see below pasted example; which the tool seems to parse incorrectly, see below excerpt from ~/.cache/bazel/_bazel_fedora/.../external/pip_deps/requirements.bzl. Notice that it doesn't properly separate requirements with no version specifiers, and merges them with the line below with an escaped feed in between: ("pip_deps_coverage", "coverage\npaho-mqtt~=1.6.1")

As a result, rules_python / pip_deps later has problems resolving the dependencies.

WORKSPACE and BUILD files

WORKSPACE:

# Load python specific bazel rules.
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "rules_python",
    sha256 = "e85ae30de33625a63eca7fc40a94fea845e641888e52f32b6beea91e8b1b2793",
    strip_prefix = "rules_python-0.27.1",
    url = "https://github.com/bazelbuild/rules_python/releases/download/0.27.1/rules_python-0.27.1.tar.gz",
)
load("@rules_python//python:repositories.bzl", "py_repositories")
py_repositories()

# PIP support
load("@rules_python//python:pip.bzl", "pip_parse")
pip_parse(
    name = "pip_deps",
    requirements_lock = ":requirements.txt",
)
load("@pip_deps//:requirements.bzl", "install_deps")
install_deps()

BUILD:

load("@rules_python//python:defs.bzl", "py_binary", "py_test")
load("@pip_deps//:requirements.bzl", "requirement")


py_library(
    name = "netlink",
    srcs = ["netlink.py"],
    visibility = ["//visibility:public"],
    deps = [
       requirement("NetLink"),
       requirement("paho-mqtt"),
       requirement("pyroute2"),
       "//wgkex/common:utils",
       "//wgkex/common:logger",
       "//wgkex/config:config",
    ],
)


py_test(
    name = "netlink_test",
    srcs = ["netlink_test.py"],
    deps = [
       "//wgkex/worker:netlink",
       requirement("mock"),
       requirement("pyroute2"),
    ],
)

py_library(
    name = "mqtt",
    srcs = ["mqtt.py"],
    visibility = ["//visibility:public"],
    deps = [
       requirement("NetLink"),
       requirement("paho-mqtt"),
       requirement("pyroute2"),
       "//wgkex/common:logger",
       "//wgkex/common:mqtt",
       "//wgkex/common:utils",
       "//wgkex/config:config",
       ":msg_queue",
       ":netlink",
    ],
)

py_test(
    name = "mqtt_test",
    srcs = ["mqtt_test.py"],
    deps = [
       "//wgkex/worker:mqtt",
       "//wgkex/worker:msg_queue",
       requirement("mock"),
    ],
)

py_binary(
    name = "app",
    srcs = ["app.py"],
    deps = [
       ":mqtt",
       ":msg_queue",
       "//wgkex/config:config",
       "//wgkex/common:logger",
    ],
)

py_test(
    name = "app_test",
    srcs = ["app_test.py"],
    deps = [
       "//wgkex/worker:app",
       "//wgkex/worker:msg_queue",
       requirement("mock"),
    ],
)

py_library(
    name = "msg_queue",
    srcs = ["msg_queue.py"],
    visibility = ["//visibility:public"],
    deps = [
       "//wgkex/common:logger",
    ],
)

requirements.txt:

NetLink~=0.1
flask-mqtt
pyroute2~=0.7.10
PyYAML~=6.0.1
Flask~=3.0.0
waitress~=2.1.2

# Common
ipaddress~=1.0.23
mock~=5.1.0
coverage
paho-mqtt~=1.6.1

Excerpt from requirements.bzl:

_packages = [("pip_deps_netlink", "NetLink~=0.1"), ("pip_deps_flask_mqtt", "flask-mqtt\npyroute2~=0.7.10"), ("pip_deps_pyyaml", "PyYAML~=6.0.1"), ("pip_deps_flask", "Flask~=3.0.0"), ("pip_
deps_waitress", "waitress~=2.1.2"), ("pip_deps_ipaddress", "ipaddress~=1.0.23"), ("pip_deps_mock", "mock~=5.1.0"), ("pip_deps_coverage", "coverage\npaho-mqtt~=1.6.1")]
_config = {"download_only": False, "enable_implicit_namespace_pkgs": False, "environment": {}, "extra_pip_args": [], "isolated": True, "pip_data_exclude": [], "python_interpreter": "python
3", "quiet": True, "repo": "pip_deps", "repo_prefix": "pip_deps_", "timeout": 600}
_annotations = {}

🔬 Minimal Reproduction

Not yet

🔥 Exception or Error


ERROR: no such package '@@pip_deps//paho_mqtt': BUILD file not found in directory 'paho_mqtt' of external repository @@pip_deps. Add a BUILD file to a directory to mark it as a package.
ERROR: /home/fedora/git/wgkex/wgkex/worker/BUILD:30:11: no such package '@@pip_deps//paho_mqtt': BUILD file not found in directory 'paho_mqtt' of external repository @@pip_deps. Add a BUILD file to a directory to mark it as a package. and referenced by '//wgkex/worker:mqtt'
ERROR: Analysis of target '//wgkex/worker:app' failed; build aborted: Analysis failed
INFO: Elapsed time: 4.039s, Critical Path: 0.04s
INFO: 1 process: 1 internal.
ERROR: Build did NOT complete successfully
FAILED: 
    Fetching repository @@bazel_tools~cc_configure_extension~local_config_cc; starting
    Fetching repository @@pip_deps_pyyaml; Restarting.

🌍 Your Environment

Operating System:

Fedora 39 Cloud Edition

Output of bazel version:

v1.19.0

Rules_python version:

0.27.1

Anything else relevant?

I'll gladly provide more information and snippets if needed, please just dumb your questions down enough for someone who doesn't really know Bazel at all

DasSkelett avatar Dec 20 '23 21:12 DasSkelett