-
-
Notifications
You must be signed in to change notification settings - Fork 652
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
Print Target Definition Using Buildozer #5142
Conversation
4fb4415
to
11da0ca
Compare
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 for putting this together! :)
|
||
@classmethod | ||
def _execute_buildozer_command(cls, buildozer_command): | ||
def _execute_buildozer_command(cls, buildozer_command, supress_warnings): |
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.
nit: s/supress/suppress/
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.
Updated to suppress_warnings
in peek.py and buildozer.py.
# Copyright 2017 Pants project contributors (see CONTRIBUTORS.md). | ||
# Licensed under the Apache License, Version 2.0 (see LICENSE). | ||
|
||
#./pants peek --path=src/scala/org/pantsbuild/zinc/analysis --target-name=zinc-analysis |
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.
Remove these comments, or replace them with the valid syntax (./pants peek --line_number=true src/scala/org/pantsbuild/zinc/analysis:zinc-analysis
)
(Probably easiest to just remove them; I think CI is failing because they're here too: https://travis-ci.org/pantsbuild/pants/jobs/308864341 )
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.
Removed the comments for CI. Is it relevant to include an example in the description? I noticed some Pants tasks have them but most do not.
|
||
|
||
class Peek(Task): | ||
"""Peek a build file for a specified target |
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 write down here whether the functionality here tells you the literal value in the BUILD file, or tells you the value that pants will actually use, or something else? Each of these options are potentially useful, but noting which one we expect is handy.
For instance, in the following:
dir$ cat BUILD
java_library(
dependencies = [
"//foo:bar",
"//baz:bash",
],
)
dir$ ls -1
BUILD
Foo.java
there are a bunch of things which Pants will internally do which aren't seen in the BUILD file. Some examples:
- The
name
attribute will be populated with the name of the directory containing the BUILD file. Say the directory is named "dir"; should peek return "dir", "", some special value which denote "missing", some special value which denotes "computed", or an error? - The
srcs
attribute will automatically be expanded toglobs("*.java")
. Should peek error / return "" (because it's absent), returnglobs("*.java")
because that's what's in the BUILD file, or call the functionglobs
and return the list of java files which it actually matches (i.e.["Foo.java"]
)? - Ordering isn't significant in the dependencies attribute, and Pants internally will sort the
dependencies
attribute. Should we return the unsorted list (because that's what in the BUILD file), or a sorted version (because that's what Pants will actually use, and it makes comparing two targets easier)?
@wisechengyi I don't know what you're expecting the answers to these questions to be either, or whether you've had this discussion already :)
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.
The current behavior is to print the literal content in BUILD file and not what Pants sees, so just
java_library(
dependencies = [
"//foo:bar",
"//baz:bash",
],
)
which is fine I think.
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.
Totally fine, but worth writing down in the help text :)
11da0ca
to
4d83501
Compare
def register_options(cls, register): | ||
super(Peek, cls).register_options(register) | ||
|
||
register('--line_number', help='Prints the starting line number of the named target.', type=bool, default=False) |
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.
nit: specify this as --line-number
Also, you can pass a bool flag as just the flag name, --line-number
. You don't need the =true
, so it'd be good to update the examples using that syntax.
binary = binary if binary else BinaryUtil.Factory.create().select_binary('scripts/buildozer', version, 'buildozer') | ||
|
||
Buildozer._execute_buildozer_command([binary, command, spec]) | ||
Buildozer._execute_buildozer_command([binary, command, spec], supress_warnings) |
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.
s/supress/suppress/
|
||
if self.options.line_number: | ||
print('\n\'{}\' starts on line number:'.format(root.name)) | ||
Buildozer.execute_binary('print startline', address_spec, suppress_warnings=True) |
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.
If the line number were moved above the print name
call, would that cause problems? I think that moving it would improve the output.
'foo:target' starts on line number:
foo/BUILD:12
my_target(name='target',
kwarg=1,
kwarg2=1
)
seems better to me than
my_target(name='target',
kwarg=1,
kwarg2=1
)
'foo:target' starts on line number:
foo/BUILD:12
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.
Updated to incorporate the basics of this proposal - although just the target's name and associated line number is still currently being printed, not the entire rule definition. Depending on the level of complexity we're looking for with the peek functionality, printing the entire rule definition may be possible using the Buildozer command 'print rule'
described here: https://github.com/bazelbuild/buildtools/tree/master/buildozer
Pretty printing is made difficult by the Buildozer executable which operates as a black hole, with command 'print name'
always printing '\ntarget_name\n'
and commands 'print startline'
and 'print endline'
always printing '\ninteger_value\n'
.
try: | ||
subprocess.check_call(buildozer_command, cwd=get_buildroot()) | ||
except subprocess.CalledProcessError as err: | ||
if err.returncode == 3: | ||
logger.warn('{} ... no changes were made'.format(buildozer_command)) | ||
if not supress_warnings: |
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.
s/supress/suppress/
from pants.contrib.buildrefactor.buildozer import Buildozer | ||
|
||
|
||
class Peek(Task): |
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.
Could you make this a subclass of ConsoleTask
? I think the UX would be better.
A good example of ConsoleTask usage is ListRoots
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.
Yes, I thought the same and tried to implement it as a ConsoleTask
, but I have a bug. Here's the current working branch with changes to peek.py
and test_peek_integration.py
: https://github.com/denalimarsh/pants/tree/peek-console-task
The ConsoleTask
version of peek seems to work initially, successfully printing the target's name and line number - but directly afterwards it fails with error message:
for value in self.console_output(targets):
Exception message: 'NoneType' object is not iterable
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.
@denalimarsh consoletask's output should be in the return (or yield in some cases).
yield '{}: {}'.format(src_root.path, all_langs or '*') |
def console_output
, rather, make it a return value.
Exception message: 'NoneType' object is not iterable
is because it is expecting a 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.
Thanks for the fix! Implemented on branch peek-console-task.
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.
Hm. In the branch, it now returns an empty string. I think if you were to change it so that it doesn't return, but instead yield
s where it prints, it'll work.
ie
print('\'{}\' found in BUILD file.\n'.format(root_name))
becomes
yield '\'{}\' found in BUILD file.\n'.format(root_name)
If you add the yields, the return will be unnecessary because the method will act like a generator. Does that make sense?
4d83501
to
293c5cc
Compare
print('\n\'{}\' ends on line number:'.format(root.name)) | ||
Buildozer.execute_binary('print endline', address_spec, suppress_warnings=True) | ||
else: | ||
Buildozer.execute_binary('print name', address_spec, suppress_warnings=True) |
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.
The buildozer arg here should be print rule
$ buildozer 'print rule' examples/tests/java/org/pantsbuild/example/hello/greet:greet
junit_tests(
dependencies = [
"examples/src/java/org/pantsbuild/example/hello/greet",
"examples/src/resources/org/pantsbuild/example/hello",
],
)
so the method should be renamed to print_target
as well
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.
Implemented as ConsoleTask
, updated to 'print rule'
, and renamed to 'print_target'
on branch peek-console-task. If the changes look good I'll either update this PR or open a new 'Print Target' 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.
Updating this one would be good. Thanks.
Also make sure there is no print
function left in the code, because all the console output should be the 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.
Updated to use yield
instead of print
293c5cc
to
4ffe0bc
Compare
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 @denalimarsh please see comments below
raise TaskError('{} ... exited non-zero ({}).'.format(buildozer_command, err.returncode)) | ||
|
||
@classmethod | ||
def return_buildozer_output(cls, command, spec, binary=None, version='0.6.0.dce8b3c287652cbcaf43c8dd076b3f48c92ab44c', suppress_warnings=False): |
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.
Ah I made the same comments with @itsedvard's patch
#5175 (comment)
#5175 (comment)
|
||
$./pants test contrib/buildrefactor/tests/python/pants_test/contrib/buildrefactor:print_target_integration | ||
""" | ||
|
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.
could you also add a negative case here with an invalid target to show what the behavior should be?
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.
Updated to include additional test test_print_invalid_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.
Thanks. Also I think it's probably better to address
#5175 (comment)
#5175 (comment)
here since @itsedvard 's patch probably depends on this, and there are a lot more comments to address on that patch.
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.
Responded to your comments on the Meta Relocate PR...
TaskError:
#5175 (comment)
buildozer.py
refactoring:
#5175 (comment)
I also updated test_print_target_integration.py
with a test_multiple_targets()
test for the raised TaskError.
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.
Had the CI fail with:
ERROR: /home/travis/build/pantsbuild/pants/contrib/buildrefactor/src/python/pants/contrib/buildrefactor/print_target.py Imports are incorrectly sorted.
So I changed the import order in print_target.py
so TaskError comes before ConsoleTask, as in buildozer.py
and in list_owners.py
, an example I referenced: https://github.com/pantsbuild/pants/blob/d30cca1e0ecb9cc0e1b7e2cd0ff6e7e077e62a52/src/python/pants/backend/graph_info/tasks/list_owners.py
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.
./pants fmt contrib/buildrefactor/src/python/pants/contrib/buildrefactor::
should fix it for you
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 for the fix!
e88bce7
to
1d25d15
Compare
Buildozer._execute_buildozer_command([binary, command, spec]) | ||
@classmethod | ||
def return_buildozer_output(cls, command, spec, binary=None, version='0.6.0.dce8b3c287652cbcaf43c8dd076b3f48c92ab44c', suppress_warnings=False): | ||
binary = binary if binary else BinaryUtil.Factory.create().select_binary('scripts/buildozer', version, 'buildozer') |
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.
Ah I see you probably cannot use self._executable
because it is an instance variable and does not apply to a classmethod.
The correct way is to make Buildozer a subsystem and --version
being an option in that subsystem, so various tasks with buildozer subsystem can use the same version of buildozer. E.g.
self._ivy_subsystem = ivy_subsystem or IvySubsystem.global_instance() |
This as it stands still needs some improvement. I understand as far as the class goes it ends tomorrow evening, but we will appreciate that you can follow up the effort if you cannot finish refactoring the subsystem into it by then.
Function wise, I can consider this PR gets the point, but for production code, we have to gate keep a bit more :)
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.
Thank you for the advice and approach recommendation, I will try to implement it this way as soon as possible - and am looking forward to continuing development on pants after the class is over.
raise TaskError('{} ... exited non-zero ({}).'.format(buildozer_command, err.returncode)) | ||
else: | ||
try: | ||
subprocess.check_output(buildozer_command, cwd=get_buildroot(), stderr=subprocess.STDOUT) |
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.
I did not get the chance to run the code step by step yet, so cannot tell the reason for stderr=subprocess.STDOUT
, but I am guessing this method can be further simplified.
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.
@itsedvard lets coordinate on this as both the print-target
and meta-relocate
tasks are dependent on this refactoring.
1d25d15
to
6d50ec6
Compare
This adds the ability to peek a BUILD file for a named target, printing the target name if it is found.Additionally, peek allows a line_number flag which will print the starting line of the named target if it is found in the BUILD file. Also, this adds a suppress warnings feature to Buildozer. Example: $ ./pants peek --line_number=true path/to/directory:target_name To Verify: $ ./pants test contrib/buildrefactor/tests/python/pants_test/contrib/buildrefactor:peek_integration This addresses: pantsbuild#4861 Please enter the commit message for your changes. Lines starting
6d50ec6
to
b33d0fd
Compare
Closing due to being stale. |
@wisechengyi
@15Dkatz
Problem
What if a developer wanted to check a specified directory's BUILD file for a named target? They would have to navigate to the directory's BUILD file and then manually search the file for the target name.
Solution
The solution adds a pants goal called 'print-target' to the
buildrefactor
module. This allows us to peek a BUILD file for a named target, printing the target's rule if the target's name is found. Additionally, print-target allows aline_number
flag which will print the starting line of the named target if it is found in the BUILD file.In order to accomplish this, a suppress warnings feature was also added to Buildozer.
Print Target is a console task, an upgrade which utilizes method
return_buildozer_output()
in updatedbuildozer.py
from related thePants Meta Relocate Using Buildozer
Pull Request (#5175).To Verify:
Example:
$ ./pants print-target
--line-number path/to/directory:target_name
Test:
$ ./pants test
contrib/buildrefactor/tests/python/pants_test/contrib/buildrefactor:print_target_integration
This addresses:
#4861