-
Notifications
You must be signed in to change notification settings - Fork 571
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
This adds support for "extras". #18
Conversation
Looks like my test is affected by this issue. :-/ |
Ok, I commented out the test until the other issue is resolved, since AIUI (from @damienmg) there isn't currently a way to disable a test on particular platforms. This should be RFAL. |
rules_python/piptool.py
Outdated
# dependencies to make sure they are fully satisfied. | ||
for extra_dep in whl.dependencies(extra=extra): | ||
dep_distro, dep_extra = parse_requirement(extra_dep) | ||
if not is_possible(dep_distro, dep_extra): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't work for me for with google-cloud-datastore 1.4.0.
The keys of whl_map
have underscores (eg "googleapis_common_protos"
), as does distro
. dep_distro
has dashes, eg "googleapi-common-protos"
. So if an extra depends on something with dashes, then it fails to find it in whl_map
, even though the version with underscores is there. For google-cloud-datastore, this occurs because eg proto-google-cloud-datastore-v1[grpc] depends on googleapis-common-protos[grpc].
See workaround: drigz/rules_python@2d6ce0bf
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks
@@ -0,0 +1 @@ | |||
google-cloud-language==0.27.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI the 0.27.0, 0.28.x, and 0.29 releases all had wide-ranging changes to deps, and various problems with deps, unrelated to the issue at hand.
@@ -93,6 +48,47 @@ def repository_name(self): | |||
parser.add_argument('--directory', action='store', | |||
help=('The directory into which to put .whl files.')) | |||
|
|||
def determine_possible_extras(whls): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you document the argument and return value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this definitely needed a docstring.
rules_python/piptool.py
Outdated
for whl in whls | ||
} | ||
def parse_requirement(name): | ||
if '[' not in name: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you use pkg_resources.Requirement.parse(name)
instead? This might be a little brittle.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, thanks for the pointer.
@@ -63,13 +63,12 @@ def metadata(self): | |||
def name(self): | |||
return self.metadata().get('name') | |||
|
|||
def dependencies(self): | |||
def dependencies(self, extra=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you document that passing extra=None means the dependencies of the base wheel?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should all be done. thanks, and sorry for the delayed response.
rules_python/piptool.py
Outdated
# dependencies to make sure they are fully satisfied. | ||
for extra_dep in whl.dependencies(extra=extra): | ||
dep_distro, dep_extra = parse_requirement(extra_dep) | ||
if not is_possible(dep_distro, dep_extra): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks
@@ -93,6 +48,47 @@ def repository_name(self): | |||
parser.add_argument('--directory', action='store', | |||
help=('The directory into which to put .whl files.')) | |||
|
|||
def determine_possible_extras(whls): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this definitely needed a docstring.
rules_python/piptool.py
Outdated
for whl in whls | ||
} | ||
def parse_requirement(name): | ||
if '[' not in name: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, thanks for the pointer.
@@ -63,13 +63,12 @@ def metadata(self): | |||
def name(self): | |||
return self.metadata().get('name') | |||
|
|||
def dependencies(self): | |||
def dependencies(self, extra=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
6b26ef9
to
b519c4d
Compare
@duggelz This should be RFAL. I just rebased it on the other merged PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved with some comments/questions.
'requirement("%s")' % d | ||
for d in whl.dependencies() | ||
]))) | ||
name = "pkg", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this an intentional change from 2 to 4 space indent, because it goes into a BUILD file?
Side note: I indent everything open-source with 4 spaces, instead of the Google 2, except when I forget.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's been a while, so let's say yes :)
Yeah, the external emacs mode screws with me. I didn't realize the world didn't do 2 space.
'requirement("%s")' % d | ||
for d in whl.dependencies() | ||
]), | ||
extras='\n\n'.join([ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a pretty long list comprehension, but I'll let it slide.
examples/extras/BUILD
Outdated
|
||
licenses(["notice"]) # Apache 2.0 | ||
|
||
# TODO(mattmoor): Enable testing once we resolve: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this test work yet or no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOL, it should, the hard part was already uncommented. Thanks for catching this.
"Extras" are additional dependencies of a given library, which are consumed by passing the "extra" name in brackets after the distribution name, for example: ``` mock[docs]==1.0.1 ``` We see this in the dependencies of several Google Cloud libraries, which depend on: `googleapis_common_protos[grpc]` I've added a simple test that the dependency structure we synthesize for this kind of thing is correct via an "extras" test that has a `requirements.txt` of: ``` google-cloud-language==0.27.0 ``` Fixes: bazelbuild#12
Thanks @duggelz |
I just commented out both "requirement" deps from the BUILD file and the test still passes... Is that expected?
|
@hutchk See this comment in extras_test.py:
|
@drigz So I commented out the extras in the BUILD file. Shouldn't the build fail? |
@hutchk As I understand it, the test is that if you have a requirement with an extra (in this case "googleapis-common-protos[grpc]"), that the build succeeds. In Python, if a dependency is not in the BUILD file, you will only notice at runtime, but this test doesn't care about what is available at runtime (as stated in the comment). Therefore, deleting the requirement from the BUILD file is a bit like deleting the assert from a normal test - you turn it into a no-op. |
@drigz Thanks. At least to me it wasn't immediately obvious what is being done under the hood, which may be a combination of my: a) lack of proficiency in Python b) lack of understanding of Bazel and c) how the pip_import works with transitive dependencies. I've been trying to wrap my head around and would appreciate some confirmation if possible... Questions:
But I'm worried that it won't be maintainable and I don't know all the caveats. Perhaps I should just have a unique requirements.txt file for each target or package?
This way, the user of //third_party/python:google_cloud_language would not need to determine what other requirements they need to pull in. Thanks in advance and sorry for the long post. |
This is all off-topic for comments on a pull request, but I'll try to respond anyway. In future, the other Bazel support forums (SO, IRC, bazel-discuss@) would be more appropriate. I'm hoping @mattmoor will correct me if I'm wrong on any of this:
Correct. Before this pull request (#18), others would have been downloaded but googleapis-common-protos[grpc] would have been ignored.
As I read it, #35 is about allowing the user to specify transitive dependencies in the WORKSPACE rather than having them "magically" downloaded, so that the WORKSPACE can specify a single version to resolve conflicts. For example, you depend on google-cloud-language==0.27.0 which depends on google-cloud-core==0.27.0, but you also depend on google-cloud-datastore==0.26.0 which depends on google-cloud-core==0.26.0. If google-cloud-core==0.27.0 were actually compatible with both, you'd want to be able to choose that yourself, rather than downloading both versions.
Correct. Based on the comment in extras_test.py, I assume it was intentional.
I don't know if there's a best practice here. I've been using multiple requirements.txt files so that it's clear why each requirement is in the file. However, I'm worried about what happens when I start to get version conflicts...
I don't see a need to do it. You shouldn't need to manually list googleapis-common-protos[grpc] - I think that's just done for the test - so |
@dgriz thanks for chiming in while I've been out. I think you have been right on about almost everything, but a few clarifications below.
Specifically,
It should not still pass if it doesn't import it at all because the It wasn't my intent to cover sufficient functionality coverage to exercise that we include the
You should use a single We debated making this a requirement (no pun intended) by taking away the ability to name the rule, but erred on the side of flexibility (for better or for worse).
That's exactly what |
"Extras" are additional dependencies of a given library, which are consumed by passing the "extra" name in brackets after the distribution name, for example:
We see this in the dependencies of several Google Cloud libraries, which depend on:
googleapis_common_protos[grpc]
I've added a simple test that the dependency structure we synthesize for this kind of thing is correct via an "extras" test that has a
requirements.txt
of:Fixes: #12