-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
py_library enforces Python 2 for some reason #1446
Comments
Workaround seems to be |
Need more helpful error message here |
I don't think py_library enforces anything. :-) The srcs_version attribute is mainly intended to support migration from python 2 to python 3. The error message is confusing because Bazel thinks you want it to auto-convert the code from python 3 down to python 2, which is the default output. I think you could just remove all the srcs_version, and it should work just fine. |
@ulfjack Removing the
with it calling |
I'm not sure I follow - can you give me more details on how to reproduce the issue? |
@ulfjack I would really love to have a complete description how the different python conversion/flags/attributes are used and in which combination they should produce which output. |
We've done some work to support a migration from Python 2 to Python 3, and as part of that, the rules can convert both 2to3 and 3to2 (IIRC) if you have appropriate tools. However, I'm not sure why Blaze thinks that those conversions should be triggered. Unfortunately, that code is ~3-4 years old, and nobody working on Bazel right now has the necessary context. |
If by flawed you mean "it doesn't work for all use cases", then I agree. Where should we start fixing the python rules? What's the biggest pain point? |
|
I have also run into this problem. The documentation gives the expectation that if you write python 3 code and set srcs_version='PY3' in your BUILD, everything should "just work". This is not the case. I think I'm up-to-date. bazel info gives:
When I try to build this target:
bazel tells me:
which is, shall we say, counterintuitive. |
I've been looking at Python 2 vs 3 versioning issues lately and expect to have a simple fix shortly for this kind of spurious and annoying error. Let me recap what's happening here. The purpose of The Python mode is controlled by If you have a The solution is to also set the python mode, if not set already, based on The original variant of the error message in this thread is obsolete. I believe it was indicating that since the Python mode was 2 but |
This is a precursor to fixing #1446. RELNOTES: None PiperOrigin-RevId: 212267168
This is needed to open source unit tests for Python rules. Work towards #1446 and other Python-related items. RELNOTES: None PiperOrigin-RevId: 212474035
The moved tests used to cover binary/test and now also cover library. Also added some test cases for srcs_version. Work toward #1446. RELNOTES: None PiperOrigin-RevId: 212999264
Update: This work was delayed by a little yak shaving to open source some unit tests for our Python rules. It's now blocked on the fact that my fix breaks some users of bazel cquery/aquery, which is experimental. We're looking at whether the underlying issue with cquery/aquery can be fixed so it's not a breakage, and if not, whether it's ok to just continue anyway. I won't be able to work on this until mid next week anyway, hopefully the blocker will be resolved by then. |
@brandjon any update on this? We are kind of holding off with some of our development just until having the py2/py3 support fixed as it sounded it would not be far away. But if it is still a few weeks/months away we might have to start finding/using a different solution. |
When you say you're blocked on having py2/3 support fixed, which particular issues do you mean? I'm using this thread to track only the specific issue that you can't directly (i.e. on the command line) build a I just made an index of PY2/3-related issues at #6444, most of which are targeted for this quarter. For the bug described by this thread, here's an update. The blocker with cquery/aquery was fixed. The new blocker we're facing is that we're worried that fixing this bug will break py3 targets that have py2 data dependencies. This in turn requires fixing #6441. We may also need an incompatible change flag, but that's debatable because Python 3 support is marked "experimental". I'm anticipating resuming work on the blocker and this issue next week. |
Another blocker, this time more serious: We're finding that there are action conflicts between targets built in the PY2 mode, and targets built in the "I haven't decided what python version I'm using yet" mode. That is, if you declare --force_python=PY2 or default_python_version="PY2", that's different from not declaring anything at all, even though the global default is Python 2. One example where the difference matters is if you have some transitive dependency that does a select() on "force_python", say to control what sources you're building with. Then the two modes give different results, hence the conflict when we try to write the results to the same path. One solution is to make a separate output root to distinguish the "I haven't decided" mode from PY2 mode, the way we already have the "-py3" output root for PY3 mode. But another solution I'm investigating is doing away with the "I haven't decided" mode altogether. The more I think about it, the more I think this model may be simpler and avoid redundant build computations. |
Doing away with "I haven't decided" mode sounds like the right thing. |
In that case there would be three modes: PY2, PY3, and PY2AND3, but no "unset", correct? Then what mode would It seems to me that this is one big constraint solving problem. The only twist here is that some build rules change at "runtime" via |
We have no plans to make the Python major version mode handle anything besides PY 2 vs PY 3. I believe the Python community has decided that (a hypothetical) PY 4 will be significant for its name rather than for its breaking changes, so it's unlikely we'll see the need to manage compatibility to the same extent as for 2 vs 3. The more general problem you describe is tackled to some extent by the platforms/toolchains framework. We don't use it for Python 2 vs 3 because at the moment the framework is for platform-based constraints rather than version-based constraints, though that may change in the future. If you want to generalize, the next issue may be minor version numbers, where you might want to say some At the moment we are designing for the common use case of dealing with a dual PY2 / PY3 code base including an active migration from 2 to 3. By the time we address the other cases the platform/toolchain framework may be more of an obvious answer. |
The py provider is currently just a struct manipulated by native code. Eventually it should be a full-fledged Provider, but in the meantime this moves its accessors to a separate utility class. This is preparation for adding new provider fields to address #6583 and #1446. The cleanup is also a small step toward #7010. RELNOTES: None PiperOrigin-RevId: 227771462
PyProvider manages how Java code creates and accesses the fields of the legacy "py" struct provider (which we'll migrate away from soonish). This CL refactors default value logic into PyProvider, and adds a builder so it's easier to construct. It also slightly refactors some shared-library logic in PyCommon. More cleanup (hopefully) to come. Work toward #7010, yak shaving for #6583 and #1446. RELNOTES: None PiperOrigin-RevId: 229401739
PyCommon's initialization and validation helpers are renamed and moved to near the top of the class, followed by simple accessors. Initialization methods are made static so there are no longer any implicit dependencies on which fields get initialized first. Python import paths are now computed in the PyCommon constructor in order to follow the pattern of other provider fields. This requires passing the PythonSemantics to the constructor, so while I was at it I made PyCommon keep a reference to the semantics. I was a little concerned about this promoting increased coupling between PyCommon and PythonSemantics, but given that both classes serve essentially the same purpose I'm not too worried. Work toward #7010, yak shaving for #6583 and #1446. RELNOTES: None PiperOrigin-RevId: 229425980
When --experimental_allow_python_version_transitions is enabled, srcs_version will now be checked by py_binary/py_test instead of at every py_library. This allows building multiple py_library targets in the same invocation (e.g. via bazel build //pkg/...) regardless of their srcs_versions constraints. The check occurs at analysis time, but any failure is reported at execution time. This allows a configured target to be created for diagnostic purposes (i.e. finding the bad transitive dependency). I've updated our analysis-time tests to account for this possibility by asserting that this deferred failure does not occur. The "py" provider now has fields `has_py2_only_sources` and `has_py3_only_sources`. Will add a couple tests for accessing these from Starlark code in a follow-up CL. Work towards #6583 and #1446. RELNOTES: None PiperOrigin-RevId: 229986854
We need this aspect because under the new Python version semantics, incompatibilities in srcs_version are caught by py_binary rather than at the py_library where the mismatch occurred. The workflow is for users to see the validation error and follow a URL to documentation (to come in a later CL) instructing them to run this aspect to locate the bad dependencies. The aspect propagates to deps and uses both srcs_version and the py provider fields to try to determine the top-most targets that require Python 2 or Python 3. It's possible this idiom of "find the topmost dependencies satisfying property X" is reusable and could be factored into Skylib (perhaps once this code is moved out of core Bazel and into rules_python). Incidentally removed python_version_srcs filegroup in favor of just using srcs. Work towards #6583 and #1446. RELNOTES: None PiperOrigin-RevId: 230813240
PyProvider manages how Java code creates and accesses the fields of the legacy "py" struct provider (which we'll migrate away from soonish). This CL refactors default value logic into PyProvider, and adds a builder so it's easier to construct. It also slightly refactors some shared-library logic in PyCommon. More cleanup (hopefully) to come. Work toward bazelbuild#7010, yak shaving for bazelbuild#6583 and bazelbuild#1446. RELNOTES: None PiperOrigin-RevId: 229401739
Simplify computing the transitive sources and transitive-without-local sources by factoring a method or two and separating out the computation of `convertedFiles`. Work toward bazelbuild#7010, yak shaving for bazelbuild#6583 and bazelbuild#1446. RELNOTES: None PiperOrigin-RevId: 229410930
PyCommon's initialization and validation helpers are renamed and moved to near the top of the class, followed by simple accessors. Initialization methods are made static so there are no longer any implicit dependencies on which fields get initialized first. Python import paths are now computed in the PyCommon constructor in order to follow the pattern of other provider fields. This requires passing the PythonSemantics to the constructor, so while I was at it I made PyCommon keep a reference to the semantics. I was a little concerned about this promoting increased coupling between PyCommon and PythonSemantics, but given that both classes serve essentially the same purpose I'm not too worried. Work toward bazelbuild#7010, yak shaving for bazelbuild#6583 and bazelbuild#1446. RELNOTES: None PiperOrigin-RevId: 229425980
When --experimental_allow_python_version_transitions is enabled, srcs_version will now be checked by py_binary/py_test instead of at every py_library. This allows building multiple py_library targets in the same invocation (e.g. via bazel build //pkg/...) regardless of their srcs_versions constraints. The check occurs at analysis time, but any failure is reported at execution time. This allows a configured target to be created for diagnostic purposes (i.e. finding the bad transitive dependency). I've updated our analysis-time tests to account for this possibility by asserting that this deferred failure does not occur. The "py" provider now has fields `has_py2_only_sources` and `has_py3_only_sources`. Will add a couple tests for accessing these from Starlark code in a follow-up CL. Work towards bazelbuild#6583 and bazelbuild#1446. RELNOTES: None PiperOrigin-RevId: 229986854
The rewritten test is non-Bazel specific and directly checks the sandwich use case. There's a slight loss in coverage that will be addressed with bazelbuild#7054. Work towards bazelbuild#1446. RELNOTES: None PiperOrigin-RevId: 230002328
We need this aspect because under the new Python version semantics, incompatibilities in srcs_version are caught by py_binary rather than at the py_library where the mismatch occurred. The workflow is for users to see the validation error and follow a URL to documentation (to come in a later CL) instructing them to run this aspect to locate the bad dependencies. The aspect propagates to deps and uses both srcs_version and the py provider fields to try to determine the top-most targets that require Python 2 or Python 3. It's possible this idiom of "find the topmost dependencies satisfying property X" is reusable and could be factored into Skylib (perhaps once this code is moved out of core Bazel and into rules_python). Incidentally removed python_version_srcs filegroup in favor of just using srcs. Work towards bazelbuild#6583 and bazelbuild#1446. RELNOTES: None PiperOrigin-RevId: 230813240
|
We are not interested in anything lower than Python 3 so we set all our
srcs_version
toPY3
fprpy_
* rules. Still when Analyzing, Bazel complains:The error message is quite unhelpful because it does not explain why it "needs" to be converted nor which thing is
not yet implemented
.The text was updated successfully, but these errors were encountered: