Skip to content
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

Gazelle extension for Python #514

Merged
merged 17 commits into from
Nov 17, 2021
Merged

Gazelle extension for Python #514

merged 17 commits into from
Nov 17, 2021

Conversation

f0rmiga
Copy link
Collaborator

@f0rmiga f0rmiga commented Aug 20, 2021

Hi there! 👋

This is the initial Gazelle extension for Python.

A good starting point for reviewing is the added README file under gazelle/, the example workspace and the testdata directory.

More discussion on where Gazelle extensions should live here: bazel-contrib/bazel-gazelle#1030.

@google-cla
Copy link

google-cla bot commented Aug 20, 2021

All (the pull request submitter and all commit authors) CLAs are signed, but one or more commits were authored or co-authored by someone other than the pull request submitter.

We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that by leaving a comment that contains only @googlebot I consent. in this pull request.

Note to project maintainer: There may be cases where the author cannot leave a comment, or the comment is not properly detected as consent. In those cases, you can manually confirm consent of the commit author(s), and set the cla label to yes (if enabled on your project).

ℹ️ Googlers: Go here for more info.

@google-cla google-cla bot added the cla: no label Aug 20, 2021
@alexeagle
Copy link
Collaborator

@googlebot I consent.

I'm co-authoring this with Thulio.

@thundergolfer
Copy link
Collaborator

Thanks @f0rmiga can you add bazel-contrib/bazel-gazelle#1030 to the PR description?

Looks like something reviewers should read through given discussion in the bazelbuild Slack (note that Slack link will eventually die as the workspace has free-tier limited history).

Copy link
Collaborator

@thundergolfer thundergolfer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the "starting point for reviewing" stuff so far. Good stuff. Will continue on tomorrow or day after.

Edit: Alright I'm back... 6 days later.

modules_mapping(
name = "modules_map",
# This should point to wherever we declare our python dependencies
requirements = "//:requirements_lock.txt",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a 'lock' file. Does it require the requirements file to be transitively locked? If yes, it should be called out I think.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW the public doc for the repo doesn't call this out (but maybe it should?)

The public doc also use "//path/to:requirements_lock.txt" so maybe we should use that here as well for consistency? (and down below in gazelle_python_manifest)


Finally, you create a target that you'll invoke to run the Gazelle tool
with the rules_python extension included. This typically goes in your root
`/BUILD.bazel` file:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Could be clearer to just say "target typically goes in your workspace root package, //:gazelle.

gazelle/README.md Show resolved Hide resolved
Copy link
Collaborator

@thundergolfer thundergolfer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had a scan through the Golang, and the testing looks nice and thorough. As I'm not the best person to do ongoing review of Golang code, can we get an ongoing reviewer added to .github/CODEOWNERS. They'll get assigned by Github as appropriate.

gazelle/kinds.go Outdated Show resolved Hide resolved
examples/build_file_generation/BUILD Outdated Show resolved Hide resolved
@f0rmiga f0rmiga force-pushed the gazelle branch 2 times, most recently from cb39cbc to a795f91 Compare September 14, 2021 05:34
.bazelversion Outdated
@@ -1 +1 @@
3.3.1
4.1.0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this change? We have #533 bumping the version.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that just landed, so no we shouldn't need this anymore

@google-cla
Copy link

google-cla bot commented Sep 30, 2021

All (the pull request submitter and all commit authors) CLAs are signed, but one or more commits were authored or co-authored by someone other than the pull request submitter.

We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that by leaving a comment that contains only @googlebot I consent. in this pull request.

Note to project maintainer: There may be cases where the author cannot leave a comment, or the comment is not properly detected as consent. In those cases, you can manually confirm consent of the commit author(s), and set the cla label to yes (if enabled on your project).

ℹ️ Googlers: Go here for more info.

@google-cla google-cla bot added cla: no and removed cla: yes labels Sep 30, 2021
Copy link

@joshua-cannon-techlabs joshua-cannon-techlabs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👋 Howdy! Very excited to see this PR, as someone who build-engineers at a company with way too much hand-maintained Python BUILD files 😁

In fact, ignoring all the other challenges we face with Bazel+Python, this is the largest IMO.


One high-level suggestion I have (possibly out of scope, but would love to see it): super-fine grained generation. This mode would be the default and essentially boils down to roughly one rule-per-file.

This would make builds/tests as fast as possible within Bazel. It'll also make the BUILD files noisy, but it's also generated so "meh".

To demonstrate it with an example:

Take this directory structure:

cheese_shop/
├─ __init__.py  # Just imports and re-exports from the _<cheese> files
├─ _caerphilly.py
├─ _caerphilly_test.py
├─ _emmental.py
├─ _emmental_test.py
├─ _japanese_sage_darby.py
├─ _japanese_sage_darby_test.py
├─ mister_wensleydale.py  # public subpackage
├─ mister_wensleydale_test.py

Ideally, there'd be:

  • 5 py_librarys:
    • One for each _<cheese>.py (Maybe this could even has it's visibility marked, due to the leading-underscore convention?)
    • One for __init__.py. This would be the one that other libraries depend on.
    • One for mister_wensleydale.py, a public subpackage
  • 4 py_tests. One for each *_test.py

That way if I only edit _caerphilly.py, Ideally only the _caerphilly_test.py test rule will need to be run (and not the other tests).


### Tests

Python test files are those ending in `_test.py`.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd be prudent to also look for other standard patterns.

unittest's discovery's pattern is test* by default: https://docs.python.org/3/library/unittest.html#cmdoption-unittest-discover-p
pytest allows both test_ and _test: https://docs.pytest.org/en/6.2.x/goodpractices.html#test-discovery

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And/or allow me to specify the pattern (through a directive?) 😁

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already supported! https://github.com/bazelbuild/rules_python/pull/514/files#diff-56956604a1d66006e9135f231c19bf1799aa19370f382ccd94842a88856bce78R86

We only need to update the documentation to be clear. unittest should be supported if you write a template for it and use the target output as __test__.py and the generation target named __test__.

modules_mapping(
name = "modules_map",
# This should point to wherever we declare our python dependencies
requirements = "//:requirements_lock.txt",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW the public doc for the repo doesn't call this out (but maybe it should?)

The public doc also use "//path/to:requirements_lock.txt" so maybe we should use that here as well for consistency? (and down below in gazelle_python_manifest)


Python test files are those ending in `_test.py`.

A `py_test` target is added containing all test files as `srcs`.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be out of scope for this PR, but this might be a nonstarter for projects using a custom test rule (which is suuuuuuuper common, since rules_python lacks pytest support today and pytest is the ubiquitous Python test library/runner).

Is this possible to customize through directives?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll expand this section. It's more complicated than what we stated so far.

modules_mapping = "@modules_map//:modules_mapping.json",
# This is what we called our `pip_install` rule, where third-party
# python libraries are loaded in BUILD files.
pip_deps_repository_name = "pip",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The public doc for this repo uses my_deps, let's be consistent?

@f0rmiga
Copy link
Collaborator Author

f0rmiga commented Oct 27, 2021

@joshua-cannon-techlabs Thanks for your input. I considered the file-grained approach, but not as default. I shall change a bit the generation mode options before landing this. I won't add the file-grained mode before landing, but will leave space for it to be added in the near future. So the options supported now would be:

# gazelle:python_generation_mode package
# gazelle:python_generation_mode project

and then for the future:

# gazelle:python_generation_mode file

@google-cla
Copy link

google-cla bot commented Oct 27, 2021

All (the pull request submitter and all commit authors) CLAs are signed, but one or more commits were authored or co-authored by someone other than the pull request submitter.

We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that by leaving a comment that contains only @googlebot I consent. in this pull request.

Note to project maintainer: There may be cases where the author cannot leave a comment, or the comment is not properly detected as consent. In those cases, you can manually confirm consent of the commit author(s), and set the cla label to yes (if enabled on your project).

ℹ️ Googlers: Go here for more info.

1 similar comment
@google-cla
Copy link

google-cla bot commented Oct 27, 2021

All (the pull request submitter and all commit authors) CLAs are signed, but one or more commits were authored or co-authored by someone other than the pull request submitter.

We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that by leaving a comment that contains only @googlebot I consent. in this pull request.

Note to project maintainer: There may be cases where the author cannot leave a comment, or the comment is not properly detected as consent. In those cases, you can manually confirm consent of the commit author(s), and set the cla label to yes (if enabled on your project).

ℹ️ Googlers: Go here for more info.

@f0rmiga
Copy link
Collaborator Author

f0rmiga commented Oct 27, 2021

@googlebot I consent.

@google-cla
Copy link

google-cla bot commented Oct 27, 2021

All (the pull request submitter and all commit authors) CLAs are signed, but one or more commits were authored or co-authored by someone other than the pull request submitter.

We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that by leaving a comment that contains only @googlebot I consent. in this pull request.

Note to project maintainer: There may be cases where the author cannot leave a comment, or the comment is not properly detected as consent. In those cases, you can manually confirm consent of the commit author(s), and set the cla label to yes (if enabled on your project).

ℹ️ Googlers: Go here for more info.

@google-cla
Copy link

google-cla bot commented Oct 27, 2021

All (the pull request submitter and all commit authors) CLAs are signed, but one or more commits were authored or co-authored by someone other than the pull request submitter.

We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that by leaving a comment that contains only @googlebot I consent. in this pull request.

Note to project maintainer: There may be cases where the author cannot leave a comment, or the comment is not properly detected as consent. In those cases, you can manually confirm consent of the commit author(s), and set the cla label to yes (if enabled on your project).

ℹ️ Googlers: Go here for more info.

@f0rmiga
Copy link
Collaborator Author

f0rmiga commented Oct 27, 2021

@thundergolfer The MacOS Buildkite runner is missing the os module from Python. Any idea why?

@google-cla
Copy link

google-cla bot commented Nov 10, 2021

All (the pull request submitter and all commit authors) CLAs are signed, but one or more commits were authored or co-authored by someone other than the pull request submitter.

We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that by leaving a comment that contains only @googlebot I consent. in this pull request.

Note to project maintainer: There may be cases where the author cannot leave a comment, or the comment is not properly detected as consent. In those cases, you can manually confirm consent of the commit author(s), and set the cla label to yes (if enabled on your project).

ℹ️ Googlers: Go here for more info.

@google-cla google-cla bot added cla: yes and removed cla: no labels Nov 10, 2021
alexeagle and others added 13 commits November 16, 2021 13:57
Signed-off-by: Thulio Ferraz Assis <[email protected]>
Co-authored-by: Jonathon Belotti <[email protected]>
Signed-off-by: Thulio Ferraz Assis <[email protected]>
With the recent change in pypa/setuptools#2769, some wheels started to
fail build immediately with an unpinned setuptools in isolation mode.

Signed-off-by: Thulio Ferraz Assis <[email protected]>
Signed-off-by: Thulio Ferraz Assis <[email protected]>
Signed-off-by: Thulio Ferraz Assis <[email protected]>
Also add the python_generation_mode directive.

Signed-off-by: Thulio Ferraz Assis <[email protected]>
Signed-off-by: Thulio Ferraz Assis <[email protected]>
Copy link
Contributor

@hrfuller hrfuller left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. A few nits that can be addressed in a follow up.



def build(wheel):
print("{}: building {}".format(datetime.now(), wheel), file=sys.stderr)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prefer an f-string here

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

f-strings are Python 3.6 only. Don't we care about earlier Python versions?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree we should avoid depending on interpreter version where possible/convenient. I don't know what assertions we have to keep ourselves honest about it.

Comment on lines +34 to +37
print("STDOUT:", file=sys.stderr)
print(process.stdout, file=sys.stderr)
print("STDERR:", file=sys.stderr)
print(process.stderr, file=sys.stderr)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this could be turned into a more readable multi-line string

def build(wheel):
print("{}: building {}".format(datetime.now(), wheel), file=sys.stderr)
process = subprocess.run(
[sys.executable, "-m", "build", "--wheel", "--no-isolation"], cwd=wheel
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is assuming that .tar.gz packages have a build module a packaging standard? Do some need setup.py run?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand this question. The build module here is provided by https://packaging.python.org/key_projects/#build, which implements https://www.python.org/dev/peps/pep-0517/.

After it builds the wheel from the source, we dig the file with generator.py in this same Python package.
Is your question around needing to run setup.py instead of looking at the packaged wheel only?

Signed-off-by: Thulio Ferraz Assis <[email protected]>
Signed-off-by: Thulio Ferraz Assis <[email protected]>
Performing the check last is more correct and yields better performance,
noticeable on large repositories.

Signed-off-by: Thulio Ferraz Assis <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants