-
-
Notifications
You must be signed in to change notification settings - Fork 646
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
python_source_root not added to syspath #11666
Comments
Interesting, this does make sense! This is the relevant code: pants/src/python/pants/backend/python/goals/pytest_runner.py Lines 238 to 241 in 0e1f1f9
Which maps back to: pants/src/python/pants/backend/python/util_rules/python_sources.py Lines 101 to 110 in 0e1f1f9
Based on this code, we would no matter what be using That is, our code is not safe for codegen, which is allowed to place the generated files in any arbitrary location, unlike a normal -- The fix is that rather than using pants/src/python/pants/source/source_root.py Lines 176 to 190 in 0e1f1f9
However, we do still need to only be getting source roots for Right now, this is a convenience that merges all the sources into a single digest. (Refer to https://www.pantsbuild.org/docs/rules-api-and-target-api#the-sources-field and https://www.pantsbuild.org/docs/rules-api-file-system#core-abstractions-digest-and-snapshot): pants/src/python/pants/backend/python/util_rules/python_sources.py Lines 82 to 90 in 0e1f1f9
We don't want that convenience, we need to associate/zip each target with its specific sources. So, we'd replace that above with Then, replace the below with more complex logic: Finally, updating the test. Add on to this test with a pants/src/python/pants/backend/python/util_rules/python_sources_test.py Lines 207 to 231 in 0e1f1f9
Would you be interested in fixing this @jyggen? |
Sure, I can give it a try! |
I gave it a shot in this commit, but something isn't quite right because Pants fills the screen with "No source of dependency..." and refuses to start. Any pointers in the right direction would be appreciated! |
Huh, I reproduce that extremely confusing rule graph error and I'm not sure why it's happening..sorry for the confusion! Rule graph error messages are a high priority for us to fix. In the process, though, I realized my suggested approach wasn't fully worked through - I didn't realize that diff --git a/src/python/pants/backend/python/util_rules/python_sources.py b/src/python/pants/backend/python/util_rules/python_sources.py
index 1d668d7d6..cd891527a 100644
--- a/src/python/pants/backend/python/util_rules/python_sources.py
+++ b/src/python/pants/backend/python/util_rules/python_sources.py
@@ -13,7 +13,7 @@ from pants.core.util_rules.source_files import SourceFiles, SourceFilesRequest
from pants.core.util_rules.stripped_source_files import StrippedSourceFiles
from pants.engine.fs import MergeDigests, Snapshot
from pants.engine.rules import Get, MultiGet, collect_rules, rule
-from pants.engine.target import Sources, Target
+from pants.engine.target import HydratedSources, HydrateSourcesRequest, Sources, Target
from pants.engine.unions import UnionMembership
from pants.source.source_root import SourceRoot, SourceRootRequest
from pants.util.logging import LogLevel
@@ -98,15 +98,39 @@ async def prepare_python_sources(
MergeDigests((sources.snapshot.digest, missing_init_files.snapshot.digest)),
)
- source_root_objs = await MultiGet(
- Get(SourceRoot, SourceRootRequest, SourceRootRequest.for_target(tgt))
- for tgt in request.targets
- if (
- tgt.has_field(PythonSources)
- or tgt.has_field(ResourcesSources)
- or tgt.get(Sources).can_generate(PythonSources, union_membership)
- or tgt.get(Sources).can_generate(ResourcesSources, union_membership)
+ # Codegen is able to generate code in any arbitrary location, unlike sources normally being
+ # rooted under the target definition. To determine source roots for these generated files, we
+ # cannot use the normal `SourceRootRequest.for_target()` and we instead must determine the
+ # source file for every individual generated file. So, we re-resolve the codegen sources here.
+ python_and_resources_targets = []
+ codegen_targets = []
+ for tgt in request.targets:
+ if tgt.has_field(PythonSources) or tgt.has_field(ResourcesSources):
+ python_and_resources_targets.append(tgt)
+ elif tgt.get(Sources).can_generate(PythonSources, union_membership) or tgt.get(
+ Sources
+ ).can_generate(ResourcesSources, union_membership):
+ codegen_targets.append(tgt)
+ codegen_sources = await MultiGet(
+ Get(
+ HydratedSources,
+ HydrateSourcesRequest(
+ tgt.get(Sources), for_sources_types=request.valid_sources_types, enable_codegen=True
+ ),
+ )
+ for tgt in codegen_targets
+ )
+ source_root_requests = [
+ *(SourceRootRequest.for_target(tgt) for tgt in python_and_resources_targets),
+ *(
+ SourceRootRequest.for_file(f)
+ for sources in codegen_sources
+ for f in sources.snapshot.files
)
+ ]
+
+ source_root_objs = await MultiGet(
+ Get(SourceRoot, SourceRootRequest, req) for req in source_root_requests
)
source_root_paths = {source_root_obj.path for source_root_obj in source_root_objs}
return PythonSourceFiles( The only thing missing now is expanding the tests in |
…ot` (pantsbuild#11673) Fixes pantsbuild#11666. # Rust tests and lints will be skipped. Delete if not intended. [ci skip-rust] # Building wheels and fs_util will be skipped. Delete if not intended. [ci skip-build-wheels]
…ot` (pantsbuild#11673) Fixes pantsbuild#11666. # Rust tests and lints will be skipped. Delete if not intended. [ci skip-rust]
I have a project structure along the lines of this:
/packages
,/protos
and/services
are all configured as source roots. In each BUILD files residing inprotos/*
I have either the lineprotobuf_library(python_source_root='services')
orprotobuf_library(python_source_root='packages')
, which means that the generated code ends up inpackages/*
orservices/*
instead.This is working just fine as long as the running code is in the same source root as the generated protobuf code, but when code in
services/
is dependent on protos that haspython_source_root
set topackages
, Python can't find the module unless an actual module from the same source root is also a dependency. I did some digging around, and it seems like the issue is that the source root specified inpython_source_root
is never explicitly added to Python's syspath, which is why imports fail if no "real" packages from the same source roots are used. So using the same example as earlier I seeservices
andprotos
, butpackages
, where the generated code is placed, is missing.I created a proof-of-concept repository in case my rambling makes little sense. The issue can be seen by running
./pants test services/::
.The text was updated successfully, but these errors were encountered: