diff --git a/CHANGELOG.md b/CHANGELOG.md index 422e399026..08991c6107 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -101,6 +101,8 @@ END_UNRELEASED_TEMPLATE `# gazelle:python_resolve_sibling_imports true` * (pypi) Show overridden index URL of packages when downloading metadata have failed. ([#2985](https://github.com/bazel-contrib/rules_python/issues/2985)). +* (toolchains) use "command -v" to find interpreter in `$PATH` + ([#3150](https://github.com/bazel-contrib/rules_python/pull/3150)). {#v0-0-0-added} ### Added diff --git a/gazelle/README.md b/gazelle/README.md index 4de2c3c0cd..128fb1f583 100644 --- a/gazelle/README.md +++ b/gazelle/README.md @@ -1,92 +1,6 @@ # Python Gazelle plugin :::{note} -The gazelle plugin docs are being migrated to our primary documentation on +The gazelle plugin docs have been migrated to our primary documentation on ReadTheDocs. Please see https://rules-python.readthedocs.io/gazelle/docs/index.html. ::: - - -### Libraries - -Python source files are those ending in `.py` but not ending in `_test.py`. - -First, we look for the nearest ancestor BUILD file starting from the folder -containing the Python source file. - -In package generation mode, if there is no `py_library` in this BUILD file, one -is created using the package name as the target's name. This makes it the -default target in the package. Next, all source files are collected into the -`srcs` of the `py_library`. - -In project generation mode, all source files in subdirectories (that don't have -BUILD files) are also collected. - -In file generation mode, each file is given its own target. - -Finally, the `import` statements in the source files are parsed, and -dependencies are added to the `deps` attribute. - -### Unit Tests - -A `py_test` target is added to the BUILD file when gazelle encounters -a file named `__test__.py`. -Often, Python unit test files are named with the suffix `_test`. -For example, if we had a folder that is a package named "foo" we could have a Python file named `foo_test.py` -and gazelle would create a `py_test` block for the file. - -The following is an example of a `py_test` target that gazelle would add when -it encounters a file named `__test__.py`. - -```starlark -py_test( - name = "build_file_generation_test", - srcs = ["__test__.py"], - main = "__test__.py", - deps = [":build_file_generation"], -) -``` - -You can control the naming convention for test targets by adding a gazelle directive named -`# gazelle:python_test_naming_convention`. See the instructions in the section above that -covers directives. - -### Binaries - -When a `__main__.py` file is encountered, this indicates the entry point -of a Python program. A `py_binary` target will be created, named `[package]_bin`. - -When no such entry point exists, Gazelle will look for a line like this in the top level in every module: - -```python -if __name == "__main__": -``` - -Gazelle will create a `py_binary` target for every module with such a line, with -the target name the same as the module name. - -If `python_generation_mode` is set to `file`, then instead of one `py_binary` -target per module, Gazelle will create one `py_binary` target for each file with -such a line, and the name of the target will match the name of the script. - -Note that it's possible for another script to depend on a `py_binary` target and -import from the `py_binary`'s scripts. This can have possible negative effects on -Bazel analysis time and runfiles size compared to depending on a `py_library` -target. The simplest way to avoid these negative effects is to extract library -code into a separate script without a `main` line. Gazelle will then create a -`py_library` target for that library code, and other scripts can depend on that -`py_library` target. - -## Developer Notes - -Gazelle extensions are written in Go. -See the gazelle documentation https://github.com/bazelbuild/bazel-gazelle/blob/master/extend.md -for more information on extending Gazelle. - -If you add new Go dependencies to the plugin source code, you need to "tidy" the go.mod file. -After changing that file, run `go mod tidy` or `bazel run @go_sdk//:bin/go -- mod tidy` -to update the go.mod and go.sum files. Then run `bazel run //:gazelle_update_repos` to have gazelle -add the new dependenies to the deps.bzl file. The deps.bzl file is used as defined in our /WORKSPACE -to include the external repos Bazel loads Go dependencies from. - -Then after editing Go code, run `bazel run //:gazelle` to generate/update the rules in the -BUILD.bazel files in our repo. diff --git a/gazelle/docs/development.md b/gazelle/docs/development.md new file mode 100644 index 0000000000..29ac7a0605 --- /dev/null +++ b/gazelle/docs/development.md @@ -0,0 +1,57 @@ +# Development + +Gazelle extensions are written in Go. + +See the [Gazelle documentation][gazelle-extend] for more information on +extending Gazelle. + +[gazelle-extend]: https://github.com/bazel-contrib/bazel-gazelle/blob/master/extend.md + + +## Dependencies + +If you add new Go dependencies to the plugin source code, you need to "tidy" +the go.mod file. After changing that file, run `go mod tidy` or +`bazel run @go_sdk//:bin/go -- mod tidy` to update the `go.mod` and `go.sum` +files. Then run `bazel run //:gazelle_update_repos` to have gazelle add the +new dependencies to the `deps.bzl` file. The `deps.bzl` file is used as +defined in our `/WORKSPACE` to include the external repos Bazel loads Go +dependencies from. + +Then after editing Go code, run `bazel run //:gazelle` to generate/update +the rules in the `BUILD.bazel` files in our repo. + + +## Tests + +:::{seealso} +{gh-path}`gazelle/python/testdata/README.md` +::: + +To run tests, {command}`cd` into the {gh-path}`gazelle` directory and run +`bazel test //...`. + +Test cases are found at {gh-path}`gazelle/python/testdata`. To make a new +test case, create a directory in that folder with the following files: + ++ `README.md` with a short blurb describing the test case(s). ++ `test.yaml`, either empty (with just the docstart `---` line) or with + the expected `stderr` and exit codes of the test case. ++ and empty `WORKSPACE` file + +You will also need `BUILD.in` and `BUILD.out` files somewhere within the test +case directory. These can be in the test case root, in subdirectories, or +both. + ++ `BUILD.in` files are populated with the "before" information - typically + things like Gazelle directives or pre-existing targets. This is how the + `BUILD.bazel` file looks before running Gazelle. ++ `BUILD.out` files are the expected result after running Gazelle within + the test case. + +:::{tip} +The easiest way to create a new test is to look at one of the existing test +cases. +::: + +The source code for running tests is {gh-path}`gazelle/python/python_test.go`. diff --git a/gazelle/docs/index.md b/gazelle/docs/index.md index 6758e11d81..f276b0ca16 100644 --- a/gazelle/docs/index.md +++ b/gazelle/docs/index.md @@ -45,4 +45,5 @@ the `update` command (the default) does anything for Python code. installation_and_usage directives annotations +development ``` diff --git a/gazelle/docs/installation_and_usage.md b/gazelle/docs/installation_and_usage.md index e764957581..123f30a068 100644 --- a/gazelle/docs/installation_and_usage.md +++ b/gazelle/docs/installation_and_usage.md @@ -149,3 +149,86 @@ gazelle( That's it, now you can finally run `bazel run //:gazelle` anytime you edit Python code, and it should update your `BUILD` files correctly. + + +## Target Types and How They're Generated + +### Libraries + +Python source files are those ending in `.py` that are not matched as a test +file via the `# gazelle:python_test_file_pattern` directive. By default, +python source files are all `*.py` files except for `*_test.py` and +`test_*.py`. + +First, we look for the nearest ancestor `BUILD(.bazel)` file starting from +the folder containing the Python source file. + ++ In `package` generation mode, if there is no {bzl:obj}`py_library` in this + `BUILD(.bazel)` file, one is created using the package name as the target's + name. This makes it the default target in the package. Next, all source + files are collected into the `srcs` of the {bzl:obj}`py_library`. ++ In `project` generation mode, all source files in subdirectories (that don't + have `BUILD(.bazel)` files) are also collected. ++ In `file` generation mode, each python source file is given its own target. + +Finally, the `import` statements in the source files are parsed and +dependencies are added to the `deps` attribute of the target. + + +### Tests + +A {bzl:obj}`py_test` target is added to the `BUILD(.bazel)` file when gazelle +encounters a file named `__test__.py` or when files matching the +`# gazelle:python_test_file_pattern` directive are found. + +For example, if we had a folder that is a package named "foo" we could have a +Python file named `foo_test.py` and gazelle would create a {bzl:obj}`py_test` +block for the file. + +The following is an example of a {bzl:obj}`py_test` target that gazelle would +add when it encounters a file named `__test__.py`. + +```starlark +py_test( + name = "build_file_generation_test", + srcs = ["__test__.py"], + main = "__test__.py", + deps = [":build_file_generation"], +) +``` + +You can control the naming convention for test targets using the +`# gazelle:python_test_naming_convention` directive. + + +### Binaries + +When a `__main__.py` file is encountered, this indicates the entry point +of a Python program. A {bzl:obj}`py_binary` target will be created, named +`[package]_bin`. + +When no such entry point exists, Gazelle will look for a line like this in +the top level in every module: + +```python +if __name == "__main__": +``` + +Gazelle will create a {bzl:obj}`py_binary` target for every module with such +a line, with the target name the same as the module name. + +If the `# gazelle:python_generation_mode` directive is set to `file`, then +instead of one {bzl:obj}`py_binary` target per module, Gazelle will create +one {bzl:obj}`py_binary` target for each file with such a line, and the name +of the target will match the name of the script. + +:::{note} +It's possible for another script to depend on a {bzl:obj}`py_binary` target +and import from the {bzl:obj}`py_binary`'s scripts. This can have possible +negative effects on Bazel analysis time and runfiles size compared to +depending on a {bzl:obj}`py_library` target. The simplest way to avoid these +negative effects is to extract library code into a separate script without a +`main` line. Gazelle will then create a {bzl:obj}`py_library` target for +that library code, and other scripts can depend on that {bzl:obj}`py_library` +target. +::: diff --git a/python/private/runtime_env_toolchain_interpreter.sh b/python/private/runtime_env_toolchain_interpreter.sh index dd4d648d12..c78cfe1a9b 100755 --- a/python/private/runtime_env_toolchain_interpreter.sh +++ b/python/private/runtime_env_toolchain_interpreter.sh @@ -17,16 +17,14 @@ die() { exit 1 } -# We use `which` to locate the Python interpreter command on PATH. `command -v` -# is another option, but it doesn't check whether the file it finds has the -# executable bit. +# We use `command -v` to locate the Python interpreter command on PATH. # # A tricky situation happens when this wrapper is invoked as part of running a # tool, e.g. passing a py_binary target to `ctx.actions.run()`. Bazel will unset # the PATH variable. Then the shell will see there's no PATH and initialize its -# own, sometimes without exporting it. This causes `which` to fail and this +# own, sometimes without exporting it. This causes `command -v` to fail and this # script to think there's no Python interpreter installed. To avoid this we -# explicitly pass PATH to each `which` invocation. We can't just export PATH +# explicitly pass PATH to each `command -v` invocation. We can't just export PATH # because that would modify the environment seen by the final user Python # program. # @@ -37,9 +35,9 @@ die() { # https://github.com/bazelbuild/bazel/issues/8415 # Try the "python3" command name first, then fall back on "python". -PYTHON_BIN="$(PATH="$PATH" which python3 2> /dev/null)" +PYTHON_BIN="$(PATH="$PATH" command -v python3 2> /dev/null)" if [ -z "${PYTHON_BIN:-}" ]; then - PYTHON_BIN="$(PATH="$PATH" which python 2>/dev/null)" + PYTHON_BIN="$(PATH="$PATH" command -v python 2>/dev/null)" fi if [ -z "${PYTHON_BIN:-}" ]; then die "Neither 'python3' nor 'python' were found on the target \ pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy