From f40068284cb1074b0205ff6267385a5c987325e2 Mon Sep 17 00:00:00 2001 From: Greg Roodt Date: Mon, 18 Jul 2022 16:15:56 +1000 Subject: [PATCH 001/234] pip-tools: 6.6.2 -> 6.8.0 (#762) --- python/pip_install/repositories.bzl | 19 +++++++++++++++++-- python/pip_install/requirements.bzl | 1 + 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/python/pip_install/repositories.bzl b/python/pip_install/repositories.bzl index 91390f5de1..96bf175bd4 100644 --- a/python/pip_install/repositories.bzl +++ b/python/pip_install/repositories.bzl @@ -7,6 +7,11 @@ load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") load("//third_party/github.com/bazelbuild/bazel-skylib/lib:versions.bzl", "versions") _RULE_DEPS = [ + ( + "pypi__build", + "https://files.pythonhosted.org/packages/7a/24/ee8271da317b692fcb9d026ff7f344ac6c4ec661a97f0e2a11fa7992544a/build-0.8.0-py3-none-any.whl", + "19b0ed489f92ace6947698c3ca8436cb0556a66e2aa2d34cd70e2a5d27cd0437", + ), ( "pypi__click", "https://files.pythonhosted.org/packages/76/0a/b6c5f311e32aeb3b406e03c079ade51e905ea630fc19d1262a46249c1c86/click-8.0.1-py3-none-any.whl", @@ -22,6 +27,11 @@ _RULE_DEPS = [ "https://files.pythonhosted.org/packages/1b/21/3e6ebd12d8dccc55bcb7338db462c75ac86dbd0ac7439ac114616b21667b/installer-0.5.1-py3-none-any.whl", "1d6c8d916ed82771945b9c813699e6f57424ded970c9d8bf16bbc23e1e826ed3", ), + ( + "pypi__packaging", + "https://files.pythonhosted.org/packages/05/8e/8de486cbd03baba4deef4142bd643a3e7bbe954a784dc1bb17142572d127/packaging-21.3-py3-none-any.whl", + "ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522", + ), ( "pypi__pep517", "https://files.pythonhosted.org/packages/f4/67/846c08e18fefb265a66e6fd5a34269d649b779718d9bf59622085dabd370/pep517-0.12.0-py2.py3-none-any.whl", @@ -34,8 +44,13 @@ _RULE_DEPS = [ ), ( "pypi__pip_tools", - "https://files.pythonhosted.org/packages/fe/5c/8995799b0ccf832906b4968b4eb2045beb9b3de79e96e6b1a6e4fc4e6974/pip_tools-6.6.2-py3-none-any.whl", - "6b486548e5a139e30e4c4a225b3b7c2d46942a9f6d1a91143c21b1de4d02fd9b", + "https://files.pythonhosted.org/packages/bf/3a/a8b09ca5ea24e4ddfa4d2cdf885e8c6618a4b658b32553f897f948aa0f67/pip_tools-6.8.0-py3-none-any.whl", + "3e5cd4acbf383d19bdfdeab04738b6313ebf4ad22ce49bf529c729061eabfab8", + ), + ( + "pypi__pyparsing", + "https://files.pythonhosted.org/packages/6c/10/a7d0fa5baea8fe7b50f448ab742f26f52b80bfca85ac2be9d35cdd9a3246/pyparsing-3.0.9-py3-none-any.whl", + "5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc", ), ( "pypi__setuptools", diff --git a/python/pip_install/requirements.bzl b/python/pip_install/requirements.bzl index 0c661339b1..afb94113bf 100644 --- a/python/pip_install/requirements.bzl +++ b/python/pip_install/requirements.bzl @@ -68,6 +68,7 @@ def compile_pip_requirements( ] + extra_args deps = [ + requirement("build"), requirement("click"), requirement("colorama"), requirement("pep517"), From 4b3c2b3e9755500c22f332b631405a1830e2c57c Mon Sep 17 00:00:00 2001 From: Martin Medler <36563496+martis42@users.noreply.github.com> Date: Tue, 26 Jul 2022 21:58:47 +0200 Subject: [PATCH 002/234] Make hermetic interpreters compatible to disallow_empty_glob (#761) A single filegroup is used to aggregate the interpreter files. Its platform specific regex patterns are not compatible to the flag `--incompatible_disallow_empty_glob` which forbids any pattern to return an empty list. For example, on a Linux host the `"*.exe",` will be empty. --- python/repositories.bzl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/repositories.bzl b/python/repositories.bzl index 1441432547..50610782e9 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -140,6 +140,8 @@ filegroup( "Scripts/**", "share/**", ], + # Platform-agnostic filegroup can't match on all patterns. + allow_empty = True, exclude = [ "**/* *", # Bazel does not support spaces in file names. ], From d2782233a5fc13a59a0e5c70839305fa53ea72e5 Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Wed, 27 Jul 2022 21:14:48 -0400 Subject: [PATCH 003/234] [gazelle] Use filepath.WalkDir instead of filepath.Walk (#770) --- gazelle/README.md | 2 ++ gazelle/generate.go | 14 ++++++-------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/gazelle/README.md b/gazelle/README.md index 51055cb953..fe3fb2d0c9 100644 --- a/gazelle/README.md +++ b/gazelle/README.md @@ -4,6 +4,8 @@ This directory contains a plugin for [Gazelle](https://github.com/bazelbuild/bazel-gazelle) that generates BUILD file content for Python code. +It requires Go 1.16+ to compile. + ## Installation First, you'll need to add Gazelle to your `WORKSPACE` file. diff --git a/gazelle/generate.go b/gazelle/generate.go index 685068d7f5..077acb821a 100644 --- a/gazelle/generate.go +++ b/gazelle/generate.go @@ -2,6 +2,7 @@ package python import ( "fmt" + "io/fs" "log" "os" "path/filepath" @@ -29,9 +30,6 @@ const ( var ( buildFilenames = []string{"BUILD", "BUILD.bazel"} - // errHaltDigging is an error that signals whether the generator should halt - // digging the source tree searching for modules in subdirectories. - errHaltDigging = fmt.Errorf("halt digging") ) // GenerateRules extracts build metadata from source files in a directory. @@ -106,9 +104,9 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes // boundaryPackages represents child Bazel packages that are used as a // boundary to stop processing under that tree. boundaryPackages := make(map[string]struct{}) - err := filepath.Walk( + err := filepath.WalkDir( filepath.Join(args.Dir, d), - func(path string, info os.FileInfo, err error) error { + func(path string, entry fs.DirEntry, err error) error { if err != nil { return err } @@ -120,7 +118,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes return nil } } - if info.IsDir() { + if entry.IsDir() { // If we are visiting a directory, we determine if we should // halt digging the tree based on a few criterias: // 1. The directory has a BUILD or BUILD.bazel files. Then @@ -135,7 +133,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } if !cfg.CoarseGrainedGeneration() && hasEntrypointFile(path) { - return errHaltDigging + return fs.SkipDir } return nil @@ -168,7 +166,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes return nil }, ) - if err != nil && err != errHaltDigging { + if err != nil { log.Printf("ERROR: %v\n", err) return language.GenerateResult{} } From 9cdb4f3f6aded1ccc62a10d004f9927ccc72702f Mon Sep 17 00:00:00 2001 From: Tetsuo Kiso Date: Fri, 29 Jul 2022 00:53:41 +0900 Subject: [PATCH 004/234] Exclude static libraries and tests to reduce zipped Python executables (#758) --- python/repositories.bzl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/python/repositories.bzl b/python/repositories.bzl index 50610782e9..b0af316419 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -144,6 +144,12 @@ filegroup( allow_empty = True, exclude = [ "**/* *", # Bazel does not support spaces in file names. + # static libraries + "lib/*.a", + "lib/**/*.a", + # tests for the standard libraries. + "lib/python{python_version}/**/test/**", + "lib/python{python_version}/**/tests/**", ], ), ) From 07ead72db31aea7add5350bcf69205336bfecbe2 Mon Sep 17 00:00:00 2001 From: Morten larsen Date: Mon, 1 Aug 2022 12:25:41 +0200 Subject: [PATCH 005/234] exec_compatible_with -> target_compatible_with #704 (#747) --- python/private/toolchains_repo.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/private/toolchains_repo.bzl b/python/private/toolchains_repo.bzl index 14576bcf58..282859a685 100644 --- a/python/private/toolchains_repo.bzl +++ b/python/private/toolchains_repo.bzl @@ -48,7 +48,7 @@ def _toolchains_repo_impl(rctx): # for executing build actions. toolchain( name = "{platform}_toolchain", - exec_compatible_with = {compatible_with}, + target_compatible_with = {compatible_with}, toolchain = "@{user_repository_name}_{platform}//:python_runtimes", toolchain_type = "@bazel_tools//tools/python:toolchain_type", ) From e67e7dd719d34d5a13c15b24d0234c1ac753b52d Mon Sep 17 00:00:00 2001 From: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Date: Mon, 1 Aug 2022 04:13:05 -0700 Subject: [PATCH 006/234] fix: fail if the user is root (#749) --- python/repositories.bzl | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/python/repositories.bzl b/python/repositories.bzl index b0af316419..09b05fa4ac 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -108,13 +108,26 @@ def _python_repository_impl(rctx): rctx.file(distutils_path, rctx.attr.distutils_content) # Make the Python installation read-only. - if "windows" not in rctx.os.name: - exec_result = rctx.execute(["chmod", "-R", "ugo-w", "lib"]) - if exec_result.return_code: - fail_msg = "Failed to make interpreter installation read-only. 'chmod' error msg: {}".format( - exec_result.stderr, - ) - fail(fail_msg) + if not rctx.attr.ignore_root_user_error: + if "windows" not in rctx.os.name: + exec_result = rctx.execute(["chmod", "-R", "ugo-w", "lib"]) + if exec_result.return_code != 0: + fail_msg = "Failed to make interpreter installation read-only. 'chmod' error msg: {}".format( + exec_result.stderr, + ) + fail(fail_msg) + exec_result = rctx.execute(["touch", "lib/.test"]) + if exec_result.return_code == 0: + exec_result = rctx.execute(["id", "-u"]) + if exec_result.return_code != 0: + fail("Could not determine current user ID. 'id -u' error msg: {}".format( + exec_result.stderr, + )) + uid = int(exec_result.stdout.strip()) + if uid == 0: + fail("The current user is root, please run as non-root when using the hermetic Python interpreter. See https://github.com/bazelbuild/rules_python/pull/713.") + else: + fail("The current user has CAP_DAC_OVERRIDE set, please drop this capability when using the hermetic Python interpreter. See https://github.com/bazelbuild/rules_python/pull/713.") python_bin = "python.exe" if ("windows" in platform) else "bin/python3" @@ -227,6 +240,11 @@ python_repository = repository_rule( "Either distutils or distutils_content can be specified, but not both.", mandatory = False, ), + "ignore_root_user_error": attr.bool( + default = False, + doc = "Whether the check for root should be ignored or not. This causes cache misses with .pyc files.", + mandatory = False, + ), "platform": attr.string( doc = "The platform name for the Python interpreter tarball.", mandatory = True, From 73e2490a87ecbd18738b178774bd1354dac34927 Mon Sep 17 00:00:00 2001 From: Tetsuo Kiso Date: Mon, 1 Aug 2022 20:43:10 +0900 Subject: [PATCH 007/234] Simplify glob pattern to exclude static libraries (#771) --- python/repositories.bzl | 1 - 1 file changed, 1 deletion(-) diff --git a/python/repositories.bzl b/python/repositories.bzl index 09b05fa4ac..8bb8a9ced9 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -158,7 +158,6 @@ filegroup( exclude = [ "**/* *", # Bazel does not support spaces in file names. # static libraries - "lib/*.a", "lib/**/*.a", # tests for the standard libraries. "lib/python{python_version}/**/test/**", From ac5b9736356638df6669376be73fa17b05ab1bf9 Mon Sep 17 00:00:00 2001 From: Greg Roodt Date: Tue, 2 Aug 2022 03:07:31 +1000 Subject: [PATCH 008/234] . (#774) --- python/pip_install/repositories.bzl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/pip_install/repositories.bzl b/python/pip_install/repositories.bzl index 96bf175bd4..5b834d6ca3 100644 --- a/python/pip_install/repositories.bzl +++ b/python/pip_install/repositories.bzl @@ -39,8 +39,8 @@ _RULE_DEPS = [ ), ( "pypi__pip", - "https://files.pythonhosted.org/packages/96/2f/caec18213f6a67852f6997fb0673ae08d2e93d1b81573edb93ba4ef06970/pip-22.1.2-py3-none-any.whl", - "a3edacb89022ef5258bf61852728bf866632a394da837ca49eb4303635835f17", + "https://files.pythonhosted.org/packages/84/25/5734a44897751d8bac6822efb819acda2d969bcc1b915bbd7d48102952cb/pip-22.2.1-py3-none-any.whl", + "0bbbc87dfbe6eed217beff0021f8b7dea04c8f4a0baa9d31dc4cff281ffc5b2b", ), ( "pypi__pip_tools", From 1045ca1ebeb5979b9d915580cffcdd3d6733718d Mon Sep 17 00:00:00 2001 From: Jesse Schalken Date: Wed, 3 Aug 2022 11:54:26 +1000 Subject: [PATCH 009/234] Fix download of Windows Python toolchain on Linux (#769) --- python/repositories.bzl | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/python/repositories.bzl b/python/repositories.bzl index 8bb8a9ced9..30c284191a 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -110,7 +110,8 @@ def _python_repository_impl(rctx): # Make the Python installation read-only. if not rctx.attr.ignore_root_user_error: if "windows" not in rctx.os.name: - exec_result = rctx.execute(["chmod", "-R", "ugo-w", "lib"]) + lib_dir = "lib" if "windows" not in platform else "Lib" + exec_result = rctx.execute(["chmod", "-R", "ugo-w", lib_dir]) if exec_result.return_code != 0: fail_msg = "Failed to make interpreter installation read-only. 'chmod' error msg: {}".format( exec_result.stderr, @@ -131,6 +132,29 @@ def _python_repository_impl(rctx): python_bin = "python.exe" if ("windows" in platform) else "bin/python3" + if "windows" in platform: + glob_include = [ + "*.exe", + "*.dll", + "bin/**", + "DLLs/**", + "extensions/**", + "include/**", + "Lib/**", + "libs/**", + "Scripts/**", + "share/**", + ] + else: + glob_include = [ + "bin/**", + "extensions/**", + "include/**", + "lib/**", + "libs/**", + "share/**", + ] + build_content = """\ # Generated by python/repositories.bzl @@ -141,18 +165,7 @@ package(default_visibility = ["//visibility:public"]) filegroup( name = "files", srcs = glob( - include = [ - "*.exe", - "*.dll", - "bin/**", - "DLLs/**", - "extensions/**", - "include/**", - "lib/**", - "libs/**", - "Scripts/**", - "share/**", - ], + include = {glob_include}, # Platform-agnostic filegroup can't match on all patterns. allow_empty = True, exclude = [ @@ -206,6 +219,7 @@ py_runtime_pair( py3_runtime = ":py3_runtime", ) """.format( + glob_include = repr(glob_include), python_path = python_bin, python_version = python_short_version, ) From 8048ff7c72c1c6a80b238408414561c3683ff87c Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Wed, 3 Aug 2022 23:36:07 -0700 Subject: [PATCH 010/234] chore: remove pkginfo from bzlmod file (#778) --- MODULE.bazel | 1 - 1 file changed, 1 deletion(-) diff --git a/MODULE.bazel b/MODULE.bazel index ed619e4300..42c507df80 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -11,7 +11,6 @@ use_repo( "pypi__click", "pypi__pip", "pypi__pip_tools", - "pypi__pkginfo", "pypi__setuptools", "pypi__wheel", ) From ebeb822453e5ba179149de250f33cd50c523a5c0 Mon Sep 17 00:00:00 2001 From: aptenodytes-forsteri <92043606+aptenodytes-forsteri@users.noreply.github.com> Date: Thu, 4 Aug 2022 14:04:03 -0400 Subject: [PATCH 011/234] 709/from imports (#760) * Support "from" imports in the python gazelle plugin. Fixes #709. * Test case for pip imports using "from foo import bar". * Test cases for imports of the form "from foo import bar". * Remove unnecessary flag (replaced with continue's). * Make sure from imports work with std modules. - Add test case with `from __future__ import print_function`. * Fix indentation error. - Make sure that `from foo import bar, baz` works. - Add test case for this. * Fix error message. - Keep error the same as before. Co-authored-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- gazelle/parse.py | 27 +- gazelle/parser.go | 7 +- gazelle/resolve.go | 187 +- gazelle/testdata/from_imports/BUILD.in | 1 + gazelle/testdata/from_imports/BUILD.out | 1 + gazelle/testdata/from_imports/README.md | 7 + gazelle/testdata/from_imports/WORKSPACE | 1 + gazelle/testdata/from_imports/foo/BUILD.in | 1 + gazelle/testdata/from_imports/foo/BUILD.out | 8 + gazelle/testdata/from_imports/foo/__init__.py | 1 + .../testdata/from_imports/foo/bar/BUILD.in | 21 + .../testdata/from_imports/foo/bar/BUILD.out | 21 + .../testdata/from_imports/foo/bar/__init__.py | 1 + gazelle/testdata/from_imports/foo/bar/baz.py | 1 + .../testdata/from_imports/gazelle_python.yaml | 5 + .../from_imports/import_from_init_py/BUILD.in | 0 .../import_from_init_py/BUILD.out | 9 + .../import_from_init_py/__init__.py | 2 + .../import_from_multiple/BUILD.in | 0 .../import_from_multiple/BUILD.out | 12 + .../import_from_multiple/__init__.py | 2 + .../from_imports/import_nested_file/BUILD.in | 0 .../from_imports/import_nested_file/BUILD.out | 9 + .../import_nested_file/__init__.py | 2 + .../import_nested_module/BUILD.in | 0 .../import_nested_module/BUILD.out | 9 + .../import_nested_module/__init__.py | 2 + .../from_imports/import_nested_var/BUILD.in | 0 .../from_imports/import_nested_var/BUILD.out | 9 + .../import_nested_var/__init__.py | 2 + .../import_top_level_var/BUILD.in | 0 .../import_top_level_var/BUILD.out | 9 + .../import_top_level_var/__init__.py | 2 + .../testdata/from_imports/std_module/BUILD.in | 0 .../from_imports/std_module/BUILD.out | 8 + .../from_imports/std_module/__init__.py | 3 + gazelle/testdata/from_imports/test.yaml | 1 + .../BUILD.in | 0 .../BUILD.out | 25 + .../README.md | 15 + .../WORKSPACE | 1 + .../__init__.py | 1 + .../__main__.py | 7 + .../bar.py | 5 + .../gazelle_python.yaml | 1665 +++++++++++++++++ .../test.yaml | 1 + 46 files changed, 1998 insertions(+), 93 deletions(-) create mode 100644 gazelle/testdata/from_imports/BUILD.in create mode 100644 gazelle/testdata/from_imports/BUILD.out create mode 100644 gazelle/testdata/from_imports/README.md create mode 100644 gazelle/testdata/from_imports/WORKSPACE create mode 100644 gazelle/testdata/from_imports/foo/BUILD.in create mode 100644 gazelle/testdata/from_imports/foo/BUILD.out create mode 100644 gazelle/testdata/from_imports/foo/__init__.py create mode 100644 gazelle/testdata/from_imports/foo/bar/BUILD.in create mode 100644 gazelle/testdata/from_imports/foo/bar/BUILD.out create mode 100644 gazelle/testdata/from_imports/foo/bar/__init__.py create mode 100644 gazelle/testdata/from_imports/foo/bar/baz.py create mode 100644 gazelle/testdata/from_imports/gazelle_python.yaml create mode 100644 gazelle/testdata/from_imports/import_from_init_py/BUILD.in create mode 100644 gazelle/testdata/from_imports/import_from_init_py/BUILD.out create mode 100644 gazelle/testdata/from_imports/import_from_init_py/__init__.py create mode 100644 gazelle/testdata/from_imports/import_from_multiple/BUILD.in create mode 100644 gazelle/testdata/from_imports/import_from_multiple/BUILD.out create mode 100644 gazelle/testdata/from_imports/import_from_multiple/__init__.py create mode 100644 gazelle/testdata/from_imports/import_nested_file/BUILD.in create mode 100644 gazelle/testdata/from_imports/import_nested_file/BUILD.out create mode 100644 gazelle/testdata/from_imports/import_nested_file/__init__.py create mode 100644 gazelle/testdata/from_imports/import_nested_module/BUILD.in create mode 100644 gazelle/testdata/from_imports/import_nested_module/BUILD.out create mode 100644 gazelle/testdata/from_imports/import_nested_module/__init__.py create mode 100644 gazelle/testdata/from_imports/import_nested_var/BUILD.in create mode 100644 gazelle/testdata/from_imports/import_nested_var/BUILD.out create mode 100644 gazelle/testdata/from_imports/import_nested_var/__init__.py create mode 100644 gazelle/testdata/from_imports/import_top_level_var/BUILD.in create mode 100644 gazelle/testdata/from_imports/import_top_level_var/BUILD.out create mode 100644 gazelle/testdata/from_imports/import_top_level_var/__init__.py create mode 100644 gazelle/testdata/from_imports/std_module/BUILD.in create mode 100644 gazelle/testdata/from_imports/std_module/BUILD.out create mode 100644 gazelle/testdata/from_imports/std_module/__init__.py create mode 100644 gazelle/testdata/from_imports/test.yaml create mode 100644 gazelle/testdata/with_third_party_requirements_from_imports/BUILD.in create mode 100644 gazelle/testdata/with_third_party_requirements_from_imports/BUILD.out create mode 100644 gazelle/testdata/with_third_party_requirements_from_imports/README.md create mode 100644 gazelle/testdata/with_third_party_requirements_from_imports/WORKSPACE create mode 100644 gazelle/testdata/with_third_party_requirements_from_imports/__init__.py create mode 100644 gazelle/testdata/with_third_party_requirements_from_imports/__main__.py create mode 100644 gazelle/testdata/with_third_party_requirements_from_imports/bar.py create mode 100644 gazelle/testdata/with_third_party_requirements_from_imports/gazelle_python.yaml create mode 100644 gazelle/testdata/with_third_party_requirements_from_imports/test.yaml diff --git a/gazelle/parse.py b/gazelle/parse.py index dec3a16cc9..6b07c0e8f5 100644 --- a/gazelle/parse.py +++ b/gazelle/parse.py @@ -21,15 +21,18 @@ def parse_import_statements(content, filepath): "name": subnode.name, "lineno": node.lineno, "filepath": filepath, + "from": "" } modules.append(module) elif isinstance(node, ast.ImportFrom) and node.level == 0: - module = { - "name": node.module, - "lineno": node.lineno, - "filepath": filepath, - } - modules.append(module) + for subnode in node.names: + module = { + "name": f"{node.module}.{subnode.name}", + "lineno": node.lineno, + "filepath": filepath, + "from": node.module + } + modules.append(module) return modules @@ -47,9 +50,10 @@ def parse(repo_root, rel_package_path, filename): abs_filepath = os.path.join(repo_root, rel_filepath) with open(abs_filepath, "r") as file: content = file.read() - # From simple benchmarks, 2 workers gave the best performance here. + # From simple benchmarks, 2 workers gave the best performance here. with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor: - modules_future = executor.submit(parse_import_statements, content, rel_filepath) + modules_future = executor.submit(parse_import_statements, content, + rel_filepath) comments_future = executor.submit(parse_comments, content) modules = modules_future.result() comments = comments_future.result() @@ -69,11 +73,12 @@ def main(stdin, stdout): filenames = parse_request["filenames"] outputs = list() if len(filenames) == 1: - outputs.append(parse(repo_root, rel_package_path, filenames[0])) + outputs.append(parse(repo_root, rel_package_path, + filenames[0])) else: futures = [ - executor.submit(parse, repo_root, rel_package_path, filename) - for filename in filenames + executor.submit(parse, repo_root, rel_package_path, + filename) for filename in filenames if filename != "" ] for future in concurrent.futures.as_completed(futures): diff --git a/gazelle/parser.go b/gazelle/parser.go index 2a82c946e1..d287caf233 100644 --- a/gazelle/parser.go +++ b/gazelle/parser.go @@ -133,13 +133,13 @@ func (p *python3Parser) parse(pyFilenames *treeset.Set) (*treeset.Set, error) { for _, m := range res.Modules { // Check for ignored dependencies set via an annotation to the Python // module. - if annotations.ignores(m.Name) { + if annotations.ignores(m.Name) || annotations.ignores(m.From) { continue } // Check for ignored dependencies set via a Gazelle directive in a BUILD // file. - if p.ignoresDependency(m.Name) { + if p.ignoresDependency(m.Name) || p.ignoresDependency(m.From) { continue } @@ -170,6 +170,9 @@ type module struct { LineNumber uint32 `json:"lineno"` // The path to the module file relative to the Bazel workspace root. Filepath string `json:"filepath"` + // If this was a from import, e.g. from foo import bar, From indicates the module + // from which it is imported. + From string `json:"from"` } // moduleComparator compares modules by name. diff --git a/gazelle/resolve.go b/gazelle/resolve.go index 8f68dfd036..220876da60 100644 --- a/gazelle/resolve.go +++ b/gazelle/resolve.go @@ -140,99 +140,126 @@ func (py *Resolver) Resolve( it := modules.Iterator() explainDependency := os.Getenv("EXPLAIN_DEPENDENCY") hasFatalError := false - MODULE_LOOP: + MODULES_LOOP: for it.Next() { mod := it.Value().(module) - imp := resolve.ImportSpec{Lang: languageName, Imp: mod.Name} - if override, ok := resolve.FindRuleWithOverride(c, imp, languageName); ok { - if override.Repo == "" { - override.Repo = from.Repo - } - if !override.Equal(from) { - if override.Repo == from.Repo { - override.Repo = "" - } - dep := override.String() - deps.Add(dep) - if explainDependency == dep { - log.Printf("Explaining dependency (%s): "+ - "in the target %q, the file %q imports %q at line %d, "+ - "which resolves using the \"gazelle:resolve\" directive.\n", - explainDependency, from.String(), mod.Filepath, mod.Name, mod.LineNumber) + moduleParts := strings.Split(mod.Name, ".") + possibleModules := []string{mod.Name} + for len(moduleParts) > 1 { + // Iterate back through the possible imports until + // a match is found. + // For example, "from foo.bar import baz" where bar is a variable, we should try + // `foo.bar.baz` first, then `foo.bar`, then `foo`. In the first case, the import could be file `baz.py` + // in the directory `foo/bar`. + // Or, the import could be variable `bar` in file `foo/bar.py`. + // The import could also be from a standard module, e.g. `six.moves`, where + // the dependency is actually `six`. + moduleParts = moduleParts[:len(moduleParts)-1] + possibleModules = append(possibleModules, strings.Join(moduleParts, ".")) + } + errs := []error{} + POSSIBLE_MODULE_LOOP: + for _, moduleName := range possibleModules { + imp := resolve.ImportSpec{Lang: languageName, Imp: moduleName} + if override, ok := resolve.FindRuleWithOverride(c, imp, languageName); ok { + if override.Repo == "" { + override.Repo = from.Repo } - } - } else { - if dep, ok := cfg.FindThirdPartyDependency(mod.Name); ok { - deps.Add(dep) - if explainDependency == dep { - log.Printf("Explaining dependency (%s): "+ - "in the target %q, the file %q imports %q at line %d, "+ - "which resolves from the third-party module %q from the wheel %q.\n", - explainDependency, from.String(), mod.Filepath, mod.Name, mod.LineNumber, mod.Name, dep) + if !override.Equal(from) { + if override.Repo == from.Repo { + override.Repo = "" + } + dep := override.String() + deps.Add(dep) + if explainDependency == dep { + log.Printf("Explaining dependency (%s): "+ + "in the target %q, the file %q imports %q at line %d, "+ + "which resolves using the \"gazelle:resolve\" directive.\n", + explainDependency, from.String(), mod.Filepath, moduleName, mod.LineNumber) + } + continue MODULES_LOOP } } else { - matches := ix.FindRulesByImportWithConfig(c, imp, languageName) - if len(matches) == 0 { - // Check if the imported module is part of the standard library. - if isStd, err := isStdModule(mod); err != nil { - log.Println("ERROR: ", err) - hasFatalError = true - continue MODULE_LOOP - } else if isStd { - continue MODULE_LOOP + if dep, ok := cfg.FindThirdPartyDependency(moduleName); ok { + deps.Add(dep) + if explainDependency == dep { + log.Printf("Explaining dependency (%s): "+ + "in the target %q, the file %q imports %q at line %d, "+ + "which resolves from the third-party module %q from the wheel %q.\n", + explainDependency, from.String(), mod.Filepath, moduleName, mod.LineNumber, mod.Name, dep) } - if cfg.ValidateImportStatements() { - err := fmt.Errorf( - "%[1]q at line %[2]d from %[3]q is an invalid dependency: possible solutions:\n"+ - "\t1. Add it as a dependency in the requirements.txt file.\n"+ - "\t2. Instruct Gazelle to resolve to a known dependency using the gazelle:resolve directive.\n"+ - "\t3. Ignore it with a comment '# gazelle:ignore %[1]s' in the Python file.\n", - mod.Name, mod.LineNumber, mod.Filepath, - ) - log.Printf("ERROR: failed to validate dependencies for target %q: %v\n", from.String(), err) - hasFatalError = true - continue MODULE_LOOP + continue MODULES_LOOP + } else { + matches := ix.FindRulesByImportWithConfig(c, imp, languageName) + if len(matches) == 0 { + // Check if the imported module is part of the standard library. + if isStd, err := isStdModule(module{Name: moduleName}); err != nil { + log.Println("Error checking if standard module: ", err) + hasFatalError = true + continue POSSIBLE_MODULE_LOOP + } else if isStd { + continue MODULES_LOOP + } else if cfg.ValidateImportStatements() { + err := fmt.Errorf( + "%[1]q at line %[2]d from %[3]q is an invalid dependency: possible solutions:\n"+ + "\t1. Add it as a dependency in the requirements.txt file.\n"+ + "\t2. Instruct Gazelle to resolve to a known dependency using the gazelle:resolve directive.\n"+ + "\t3. Ignore it with a comment '# gazelle:ignore %[1]s' in the Python file.\n", + moduleName, mod.LineNumber, mod.Filepath, + ) + errs = append(errs, err) + continue POSSIBLE_MODULE_LOOP + } } - } - filteredMatches := make([]resolve.FindResult, 0, len(matches)) - for _, match := range matches { - if match.IsSelfImport(from) { - // Prevent from adding itself as a dependency. - continue MODULE_LOOP + filteredMatches := make([]resolve.FindResult, 0, len(matches)) + for _, match := range matches { + if match.IsSelfImport(from) { + // Prevent from adding itself as a dependency. + continue MODULES_LOOP + } + filteredMatches = append(filteredMatches, match) } - filteredMatches = append(filteredMatches, match) - } - if len(filteredMatches) == 0 { - continue - } - if len(filteredMatches) > 1 { - sameRootMatches := make([]resolve.FindResult, 0, len(filteredMatches)) - for _, match := range filteredMatches { - if strings.HasPrefix(match.Label.Pkg, pythonProjectRoot) { - sameRootMatches = append(sameRootMatches, match) + if len(filteredMatches) == 0 { + continue POSSIBLE_MODULE_LOOP + } + if len(filteredMatches) > 1 { + sameRootMatches := make([]resolve.FindResult, 0, len(filteredMatches)) + for _, match := range filteredMatches { + if strings.HasPrefix(match.Label.Pkg, pythonProjectRoot) { + sameRootMatches = append(sameRootMatches, match) + } } + if len(sameRootMatches) != 1 { + err := fmt.Errorf( + "multiple targets (%s) may be imported with %q at line %d in %q "+ + "- this must be fixed using the \"gazelle:resolve\" directive", + targetListFromResults(filteredMatches), moduleName, mod.LineNumber, mod.Filepath) + errs = append(errs, err) + continue POSSIBLE_MODULE_LOOP + } + filteredMatches = sameRootMatches } - if len(sameRootMatches) != 1 { - err := fmt.Errorf( - "multiple targets (%s) may be imported with %q at line %d in %q "+ - "- this must be fixed using the \"gazelle:resolve\" directive", - targetListFromResults(filteredMatches), mod.Name, mod.LineNumber, mod.Filepath) - log.Println("ERROR: ", err) - hasFatalError = true - continue MODULE_LOOP + matchLabel := filteredMatches[0].Label.Rel(from.Repo, from.Pkg) + dep := matchLabel.String() + deps.Add(dep) + if explainDependency == dep { + log.Printf("Explaining dependency (%s): "+ + "in the target %q, the file %q imports %q at line %d, "+ + "which resolves from the first-party indexed labels.\n", + explainDependency, from.String(), mod.Filepath, moduleName, mod.LineNumber) } - filteredMatches = sameRootMatches - } - matchLabel := filteredMatches[0].Label.Rel(from.Repo, from.Pkg) - dep := matchLabel.String() - deps.Add(dep) - if explainDependency == dep { - log.Printf("Explaining dependency (%s): "+ - "in the target %q, the file %q imports %q at line %d, "+ - "which resolves from the first-party indexed labels.\n", - explainDependency, from.String(), mod.Filepath, mod.Name, mod.LineNumber) + continue MODULES_LOOP } } + } // End possible modules loop. + if len(errs) > 0 { + // If, after trying all possible modules, we still haven't found anything, error out. + joinedErrs := "" + for _, err := range errs { + joinedErrs = fmt.Sprintf("%s%s\n", joinedErrs, err) + } + log.Printf("ERROR: failed to validate dependencies for target %q: %v\n", from.String(), joinedErrs) + hasFatalError = true } } if hasFatalError { diff --git a/gazelle/testdata/from_imports/BUILD.in b/gazelle/testdata/from_imports/BUILD.in new file mode 100644 index 0000000000..93f2259140 --- /dev/null +++ b/gazelle/testdata/from_imports/BUILD.in @@ -0,0 +1 @@ +# gazelle:python_extension enabled diff --git a/gazelle/testdata/from_imports/BUILD.out b/gazelle/testdata/from_imports/BUILD.out new file mode 100644 index 0000000000..93f2259140 --- /dev/null +++ b/gazelle/testdata/from_imports/BUILD.out @@ -0,0 +1 @@ +# gazelle:python_extension enabled diff --git a/gazelle/testdata/from_imports/README.md b/gazelle/testdata/from_imports/README.md new file mode 100644 index 0000000000..161dd18e33 --- /dev/null +++ b/gazelle/testdata/from_imports/README.md @@ -0,0 +1,7 @@ +# From Imports + +This test case simulates imports of the form: + +```python +from foo import bar +``` diff --git a/gazelle/testdata/from_imports/WORKSPACE b/gazelle/testdata/from_imports/WORKSPACE new file mode 100644 index 0000000000..4959898cdd --- /dev/null +++ b/gazelle/testdata/from_imports/WORKSPACE @@ -0,0 +1 @@ +# This is a test data Bazel workspace. diff --git a/gazelle/testdata/from_imports/foo/BUILD.in b/gazelle/testdata/from_imports/foo/BUILD.in new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/gazelle/testdata/from_imports/foo/BUILD.in @@ -0,0 +1 @@ + diff --git a/gazelle/testdata/from_imports/foo/BUILD.out b/gazelle/testdata/from_imports/foo/BUILD.out new file mode 100644 index 0000000000..4404d30461 --- /dev/null +++ b/gazelle/testdata/from_imports/foo/BUILD.out @@ -0,0 +1,8 @@ +load("@rules_python//python:defs.bzl", "py_library") + +py_library( + name = "foo", + srcs = ["__init__.py"], + imports = [".."], + visibility = ["//:__subpackages__"], +) diff --git a/gazelle/testdata/from_imports/foo/__init__.py b/gazelle/testdata/from_imports/foo/__init__.py new file mode 100644 index 0000000000..8c4ff6a255 --- /dev/null +++ b/gazelle/testdata/from_imports/foo/__init__.py @@ -0,0 +1 @@ +foo = "foo" diff --git a/gazelle/testdata/from_imports/foo/bar/BUILD.in b/gazelle/testdata/from_imports/foo/bar/BUILD.in new file mode 100644 index 0000000000..fbbec0284b --- /dev/null +++ b/gazelle/testdata/from_imports/foo/bar/BUILD.in @@ -0,0 +1,21 @@ +load("@rules_python//python:defs.bzl", "py_library") + +# gazelle:python_ignore_files baz.py + +py_library( + name = "baz", + srcs = [ + "baz.py", + ], + imports = ["../.."], + visibility = ["//:__subpackages__"], +) + +py_library( + name = "bar", + srcs = [ + "__init__.py", + ], + imports = ["../.."], + visibility = ["//:__subpackages__"], +) \ No newline at end of file diff --git a/gazelle/testdata/from_imports/foo/bar/BUILD.out b/gazelle/testdata/from_imports/foo/bar/BUILD.out new file mode 100644 index 0000000000..fbbec0284b --- /dev/null +++ b/gazelle/testdata/from_imports/foo/bar/BUILD.out @@ -0,0 +1,21 @@ +load("@rules_python//python:defs.bzl", "py_library") + +# gazelle:python_ignore_files baz.py + +py_library( + name = "baz", + srcs = [ + "baz.py", + ], + imports = ["../.."], + visibility = ["//:__subpackages__"], +) + +py_library( + name = "bar", + srcs = [ + "__init__.py", + ], + imports = ["../.."], + visibility = ["//:__subpackages__"], +) \ No newline at end of file diff --git a/gazelle/testdata/from_imports/foo/bar/__init__.py b/gazelle/testdata/from_imports/foo/bar/__init__.py new file mode 100644 index 0000000000..2e96e096cc --- /dev/null +++ b/gazelle/testdata/from_imports/foo/bar/__init__.py @@ -0,0 +1 @@ +bar = "bar" diff --git a/gazelle/testdata/from_imports/foo/bar/baz.py b/gazelle/testdata/from_imports/foo/bar/baz.py new file mode 100644 index 0000000000..a15f053fe4 --- /dev/null +++ b/gazelle/testdata/from_imports/foo/bar/baz.py @@ -0,0 +1 @@ +baz = "baz" diff --git a/gazelle/testdata/from_imports/gazelle_python.yaml b/gazelle/testdata/from_imports/gazelle_python.yaml new file mode 100644 index 0000000000..5f7922f40f --- /dev/null +++ b/gazelle/testdata/from_imports/gazelle_python.yaml @@ -0,0 +1,5 @@ +manifest: + modules_mapping: + boto3: rootboto3 + boto4: rootboto4 + pip_deps_repository_name: root_pip_deps diff --git a/gazelle/testdata/from_imports/import_from_init_py/BUILD.in b/gazelle/testdata/from_imports/import_from_init_py/BUILD.in new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/testdata/from_imports/import_from_init_py/BUILD.out b/gazelle/testdata/from_imports/import_from_init_py/BUILD.out new file mode 100644 index 0000000000..99b48610c2 --- /dev/null +++ b/gazelle/testdata/from_imports/import_from_init_py/BUILD.out @@ -0,0 +1,9 @@ +load("@rules_python//python:defs.bzl", "py_library") + +py_library( + name = "import_from_init_py", + srcs = ["__init__.py"], + imports = [".."], + visibility = ["//:__subpackages__"], + deps = ["//foo/bar"], +) \ No newline at end of file diff --git a/gazelle/testdata/from_imports/import_from_init_py/__init__.py b/gazelle/testdata/from_imports/import_from_init_py/__init__.py new file mode 100644 index 0000000000..350a327d20 --- /dev/null +++ b/gazelle/testdata/from_imports/import_from_init_py/__init__.py @@ -0,0 +1,2 @@ +# bar is a variable inside foo/bar/__init__.py +from foo.bar import bar diff --git a/gazelle/testdata/from_imports/import_from_multiple/BUILD.in b/gazelle/testdata/from_imports/import_from_multiple/BUILD.in new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/testdata/from_imports/import_from_multiple/BUILD.out b/gazelle/testdata/from_imports/import_from_multiple/BUILD.out new file mode 100644 index 0000000000..d8219bb4d1 --- /dev/null +++ b/gazelle/testdata/from_imports/import_from_multiple/BUILD.out @@ -0,0 +1,12 @@ +load("@rules_python//python:defs.bzl", "py_library") + +py_library( + name = "import_from_multiple", + srcs = ["__init__.py"], + imports = [".."], + visibility = ["//:__subpackages__"], + deps = [ + "//foo/bar", + "//foo/bar:baz", + ], +) \ No newline at end of file diff --git a/gazelle/testdata/from_imports/import_from_multiple/__init__.py b/gazelle/testdata/from_imports/import_from_multiple/__init__.py new file mode 100644 index 0000000000..864059b428 --- /dev/null +++ b/gazelle/testdata/from_imports/import_from_multiple/__init__.py @@ -0,0 +1,2 @@ +# Import multiple values from the same import. +from foo.bar import bar, baz diff --git a/gazelle/testdata/from_imports/import_nested_file/BUILD.in b/gazelle/testdata/from_imports/import_nested_file/BUILD.in new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/testdata/from_imports/import_nested_file/BUILD.out b/gazelle/testdata/from_imports/import_nested_file/BUILD.out new file mode 100644 index 0000000000..662da9c9a0 --- /dev/null +++ b/gazelle/testdata/from_imports/import_nested_file/BUILD.out @@ -0,0 +1,9 @@ +load("@rules_python//python:defs.bzl", "py_library") + +py_library( + name = "import_nested_file", + srcs = ["__init__.py"], + imports = [".."], + visibility = ["//:__subpackages__"], + deps = ["//foo/bar:baz"], +) \ No newline at end of file diff --git a/gazelle/testdata/from_imports/import_nested_file/__init__.py b/gazelle/testdata/from_imports/import_nested_file/__init__.py new file mode 100644 index 0000000000..d5e6b2592b --- /dev/null +++ b/gazelle/testdata/from_imports/import_nested_file/__init__.py @@ -0,0 +1,2 @@ +# baz.py is a file at foo/bar/baz.py +from foo.bar import baz diff --git a/gazelle/testdata/from_imports/import_nested_module/BUILD.in b/gazelle/testdata/from_imports/import_nested_module/BUILD.in new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/testdata/from_imports/import_nested_module/BUILD.out b/gazelle/testdata/from_imports/import_nested_module/BUILD.out new file mode 100644 index 0000000000..ec6da507dd --- /dev/null +++ b/gazelle/testdata/from_imports/import_nested_module/BUILD.out @@ -0,0 +1,9 @@ +load("@rules_python//python:defs.bzl", "py_library") + +py_library( + name = "import_nested_module", + srcs = ["__init__.py"], + imports = [".."], + visibility = ["//:__subpackages__"], + deps = ["//foo/bar"], +) \ No newline at end of file diff --git a/gazelle/testdata/from_imports/import_nested_module/__init__.py b/gazelle/testdata/from_imports/import_nested_module/__init__.py new file mode 100644 index 0000000000..3b04f00fed --- /dev/null +++ b/gazelle/testdata/from_imports/import_nested_module/__init__.py @@ -0,0 +1,2 @@ +# bar is a module at foo/bar/__init__.py +from foo import bar diff --git a/gazelle/testdata/from_imports/import_nested_var/BUILD.in b/gazelle/testdata/from_imports/import_nested_var/BUILD.in new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/testdata/from_imports/import_nested_var/BUILD.out b/gazelle/testdata/from_imports/import_nested_var/BUILD.out new file mode 100644 index 0000000000..8ee527e17a --- /dev/null +++ b/gazelle/testdata/from_imports/import_nested_var/BUILD.out @@ -0,0 +1,9 @@ +load("@rules_python//python:defs.bzl", "py_library") + +py_library( + name = "import_nested_var", + srcs = ["__init__.py"], + imports = [".."], + visibility = ["//:__subpackages__"], + deps = ["//foo/bar:baz"], +) \ No newline at end of file diff --git a/gazelle/testdata/from_imports/import_nested_var/__init__.py b/gazelle/testdata/from_imports/import_nested_var/__init__.py new file mode 100644 index 0000000000..de5069d540 --- /dev/null +++ b/gazelle/testdata/from_imports/import_nested_var/__init__.py @@ -0,0 +1,2 @@ +# baz is a variable in foo/bar/baz.py +from foo.bar.baz import baz diff --git a/gazelle/testdata/from_imports/import_top_level_var/BUILD.in b/gazelle/testdata/from_imports/import_top_level_var/BUILD.in new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/testdata/from_imports/import_top_level_var/BUILD.out b/gazelle/testdata/from_imports/import_top_level_var/BUILD.out new file mode 100644 index 0000000000..6b584d713b --- /dev/null +++ b/gazelle/testdata/from_imports/import_top_level_var/BUILD.out @@ -0,0 +1,9 @@ +load("@rules_python//python:defs.bzl", "py_library") + +py_library( + name = "import_top_level_var", + srcs = ["__init__.py"], + imports = [".."], + visibility = ["//:__subpackages__"], + deps = ["//foo"], +) \ No newline at end of file diff --git a/gazelle/testdata/from_imports/import_top_level_var/__init__.py b/gazelle/testdata/from_imports/import_top_level_var/__init__.py new file mode 100644 index 0000000000..532f11a889 --- /dev/null +++ b/gazelle/testdata/from_imports/import_top_level_var/__init__.py @@ -0,0 +1,2 @@ +# foo is a variable in foo/__init__.py +from foo import foo diff --git a/gazelle/testdata/from_imports/std_module/BUILD.in b/gazelle/testdata/from_imports/std_module/BUILD.in new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/testdata/from_imports/std_module/BUILD.out b/gazelle/testdata/from_imports/std_module/BUILD.out new file mode 100644 index 0000000000..4903999afc --- /dev/null +++ b/gazelle/testdata/from_imports/std_module/BUILD.out @@ -0,0 +1,8 @@ +load("@rules_python//python:defs.bzl", "py_library") + +py_library( + name = "std_module", + srcs = ["__init__.py"], + imports = [".."], + visibility = ["//:__subpackages__"], +) \ No newline at end of file diff --git a/gazelle/testdata/from_imports/std_module/__init__.py b/gazelle/testdata/from_imports/std_module/__init__.py new file mode 100644 index 0000000000..7e6bc9dc02 --- /dev/null +++ b/gazelle/testdata/from_imports/std_module/__init__.py @@ -0,0 +1,3 @@ +# Gazelle should recognize this from import +# as the standard module __future__. +from __future__ import print_function diff --git a/gazelle/testdata/from_imports/test.yaml b/gazelle/testdata/from_imports/test.yaml new file mode 100644 index 0000000000..ed97d539c0 --- /dev/null +++ b/gazelle/testdata/from_imports/test.yaml @@ -0,0 +1 @@ +--- diff --git a/gazelle/testdata/with_third_party_requirements_from_imports/BUILD.in b/gazelle/testdata/with_third_party_requirements_from_imports/BUILD.in new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/testdata/with_third_party_requirements_from_imports/BUILD.out b/gazelle/testdata/with_third_party_requirements_from_imports/BUILD.out new file mode 100644 index 0000000000..577f167143 --- /dev/null +++ b/gazelle/testdata/with_third_party_requirements_from_imports/BUILD.out @@ -0,0 +1,25 @@ +load("@rules_python//python:defs.bzl", "py_binary", "py_library") + +py_library( + name = "with_third_party_requirements_from_imports", + srcs = [ + "__init__.py", + "bar.py", + ], + visibility = ["//:__subpackages__"], + deps = [ + "@gazelle_python_test_google_cloud_aiplatform//:pkg", + "@gazelle_python_test_google_cloud_storage//:pkg", + ], +) + +py_binary( + name = "with_third_party_requirements_from_imports_bin", + srcs = ["__main__.py"], + main = "__main__.py", + visibility = ["//:__subpackages__"], + deps = [ + ":with_third_party_requirements_from_imports", + "@gazelle_python_test_google_cloud_aiplatform//:pkg", + ], +) diff --git a/gazelle/testdata/with_third_party_requirements_from_imports/README.md b/gazelle/testdata/with_third_party_requirements_from_imports/README.md new file mode 100644 index 0000000000..c50a1ca100 --- /dev/null +++ b/gazelle/testdata/with_third_party_requirements_from_imports/README.md @@ -0,0 +1,15 @@ +# With third-party requirements (from imports) + +This test case covers imports of the form: + +```python +from my_pip_dep import foo +``` + +for example + +```python +from google.cloud import aiplatform, storage +``` + +See https://github.com/bazelbuild/rules_python/issues/709 and https://github.com/sramirezmartin/gazelle-toy-example. diff --git a/gazelle/testdata/with_third_party_requirements_from_imports/WORKSPACE b/gazelle/testdata/with_third_party_requirements_from_imports/WORKSPACE new file mode 100644 index 0000000000..faff6af87a --- /dev/null +++ b/gazelle/testdata/with_third_party_requirements_from_imports/WORKSPACE @@ -0,0 +1 @@ +# This is a Bazel workspace for the Gazelle test data. diff --git a/gazelle/testdata/with_third_party_requirements_from_imports/__init__.py b/gazelle/testdata/with_third_party_requirements_from_imports/__init__.py new file mode 100644 index 0000000000..6b58ff30a8 --- /dev/null +++ b/gazelle/testdata/with_third_party_requirements_from_imports/__init__.py @@ -0,0 +1 @@ +# For test purposes only. diff --git a/gazelle/testdata/with_third_party_requirements_from_imports/__main__.py b/gazelle/testdata/with_third_party_requirements_from_imports/__main__.py new file mode 100644 index 0000000000..8733018885 --- /dev/null +++ b/gazelle/testdata/with_third_party_requirements_from_imports/__main__.py @@ -0,0 +1,7 @@ +from google.cloud import aiplatform + +from bar import main + +if __name__ == "__main__": + print(aiplatform) + main() diff --git a/gazelle/testdata/with_third_party_requirements_from_imports/bar.py b/gazelle/testdata/with_third_party_requirements_from_imports/bar.py new file mode 100644 index 0000000000..7875c1630b --- /dev/null +++ b/gazelle/testdata/with_third_party_requirements_from_imports/bar.py @@ -0,0 +1,5 @@ +from google.cloud import aiplatform, storage + +def main(): + a = dir(aiplatform) + b = dir(storage) diff --git a/gazelle/testdata/with_third_party_requirements_from_imports/gazelle_python.yaml b/gazelle/testdata/with_third_party_requirements_from_imports/gazelle_python.yaml new file mode 100644 index 0000000000..21edbc0a0d --- /dev/null +++ b/gazelle/testdata/with_third_party_requirements_from_imports/gazelle_python.yaml @@ -0,0 +1,1665 @@ +manifest: + modules_mapping: + cachetools: cachetools + cachetools.__init__: cachetools + cachetools.func: cachetools + cachetools.keys: cachetools + certifi: certifi + certifi.__init__: certifi + certifi.__main__: certifi + certifi.core: certifi + charset_normalizer: charset_normalizer + charset_normalizer.__init__: charset_normalizer + charset_normalizer.api: charset_normalizer + charset_normalizer.assets: charset_normalizer + charset_normalizer.assets.__init__: charset_normalizer + charset_normalizer.cd: charset_normalizer + charset_normalizer.cli: charset_normalizer + charset_normalizer.cli.__init__: charset_normalizer + charset_normalizer.cli.normalizer: charset_normalizer + charset_normalizer.constant: charset_normalizer + charset_normalizer.legacy: charset_normalizer + charset_normalizer.md: charset_normalizer + charset_normalizer.models: charset_normalizer + charset_normalizer.utils: charset_normalizer + charset_normalizer.version: charset_normalizer + dateutil: python_dateutil + dateutil.__init__: python_dateutil + dateutil._common: python_dateutil + dateutil._version: python_dateutil + dateutil.easter: python_dateutil + dateutil.parser: python_dateutil + dateutil.parser.__init__: python_dateutil + dateutil.parser._parser: python_dateutil + dateutil.parser.isoparser: python_dateutil + dateutil.relativedelta: python_dateutil + dateutil.rrule: python_dateutil + dateutil.tz: python_dateutil + dateutil.tz.__init__: python_dateutil + dateutil.tz._common: python_dateutil + dateutil.tz._factories: python_dateutil + dateutil.tz.tz: python_dateutil + dateutil.tz.win: python_dateutil + dateutil.tzwin: python_dateutil + dateutil.utils: python_dateutil + dateutil.zoneinfo: python_dateutil + dateutil.zoneinfo.__init__: python_dateutil + dateutil.zoneinfo.rebuild: python_dateutil + docs.conf: google_cloud_resource_manager + google._async_resumable_media: google_resumable_media + google._async_resumable_media.__init__: google_resumable_media + google._async_resumable_media._download: google_resumable_media + google._async_resumable_media._helpers: google_resumable_media + google._async_resumable_media._upload: google_resumable_media + google._async_resumable_media.requests: google_resumable_media + google._async_resumable_media.requests.__init__: google_resumable_media + google._async_resumable_media.requests._request_helpers: google_resumable_media + google._async_resumable_media.requests.download: google_resumable_media + google._async_resumable_media.requests.upload: google_resumable_media + google.api: googleapis_common_protos + google.api.__init__: googleapis_common_protos + google.api.annotations_pb2: googleapis_common_protos + google.api.auth_pb2: googleapis_common_protos + google.api.backend_pb2: googleapis_common_protos + google.api.billing_pb2: googleapis_common_protos + google.api.client_pb2: googleapis_common_protos + google.api.config_change_pb2: googleapis_common_protos + google.api.consumer_pb2: googleapis_common_protos + google.api.context_pb2: googleapis_common_protos + google.api.control_pb2: googleapis_common_protos + google.api.distribution_pb2: googleapis_common_protos + google.api.documentation_pb2: googleapis_common_protos + google.api.endpoint_pb2: googleapis_common_protos + google.api.error_reason_pb2: googleapis_common_protos + google.api.field_behavior_pb2: googleapis_common_protos + google.api.http_pb2: googleapis_common_protos + google.api.httpbody_pb2: googleapis_common_protos + google.api.label_pb2: googleapis_common_protos + google.api.launch_stage_pb2: googleapis_common_protos + google.api.log_pb2: googleapis_common_protos + google.api.logging_pb2: googleapis_common_protos + google.api.metric_pb2: googleapis_common_protos + google.api.monitored_resource_pb2: googleapis_common_protos + google.api.monitoring_pb2: googleapis_common_protos + google.api.quota_pb2: googleapis_common_protos + google.api.resource_pb2: googleapis_common_protos + google.api.routing_pb2: googleapis_common_protos + google.api.service_pb2: googleapis_common_protos + google.api.source_info_pb2: googleapis_common_protos + google.api.system_parameter_pb2: googleapis_common_protos + google.api.usage_pb2: googleapis_common_protos + google.api.visibility_pb2: googleapis_common_protos + google.api_core: google_api_core + google.api_core.__init__: google_api_core + google.api_core.bidi: google_api_core + google.api_core.client_info: google_api_core + google.api_core.client_options: google_api_core + google.api_core.datetime_helpers: google_api_core + google.api_core.exceptions: google_api_core + google.api_core.extended_operation: google_api_core + google.api_core.future: google_api_core + google.api_core.future.__init__: google_api_core + google.api_core.future._helpers: google_api_core + google.api_core.future.async_future: google_api_core + google.api_core.future.base: google_api_core + google.api_core.future.polling: google_api_core + google.api_core.gapic_v1: google_api_core + google.api_core.gapic_v1.__init__: google_api_core + google.api_core.gapic_v1.client_info: google_api_core + google.api_core.gapic_v1.config: google_api_core + google.api_core.gapic_v1.config_async: google_api_core + google.api_core.gapic_v1.method: google_api_core + google.api_core.gapic_v1.method_async: google_api_core + google.api_core.gapic_v1.routing_header: google_api_core + google.api_core.general_helpers: google_api_core + google.api_core.grpc_helpers: google_api_core + google.api_core.grpc_helpers_async: google_api_core + google.api_core.iam: google_api_core + google.api_core.operation: google_api_core + google.api_core.operation_async: google_api_core + google.api_core.operations_v1: google_api_core + google.api_core.operations_v1.__init__: google_api_core + google.api_core.operations_v1.abstract_operations_client: google_api_core + google.api_core.operations_v1.operations_async_client: google_api_core + google.api_core.operations_v1.operations_client: google_api_core + google.api_core.operations_v1.operations_client_config: google_api_core + google.api_core.operations_v1.pagers: google_api_core + google.api_core.operations_v1.transports: google_api_core + google.api_core.operations_v1.transports.__init__: google_api_core + google.api_core.operations_v1.transports.base: google_api_core + google.api_core.operations_v1.transports.rest: google_api_core + google.api_core.page_iterator: google_api_core + google.api_core.page_iterator_async: google_api_core + google.api_core.path_template: google_api_core + google.api_core.protobuf_helpers: google_api_core + google.api_core.rest_helpers: google_api_core + google.api_core.rest_streaming: google_api_core + google.api_core.retry: google_api_core + google.api_core.retry_async: google_api_core + google.api_core.timeout: google_api_core + google.api_core.version: google_api_core + google.auth: google_auth + google.auth.__init__: google_auth + google.auth._cloud_sdk: google_auth + google.auth._credentials_async: google_auth + google.auth._default: google_auth + google.auth._default_async: google_auth + google.auth._helpers: google_auth + google.auth._jwt_async: google_auth + google.auth._oauth2client: google_auth + google.auth._service_account_info: google_auth + google.auth.app_engine: google_auth + google.auth.aws: google_auth + google.auth.compute_engine: google_auth + google.auth.compute_engine.__init__: google_auth + google.auth.compute_engine._metadata: google_auth + google.auth.compute_engine.credentials: google_auth + google.auth.credentials: google_auth + google.auth.crypt: google_auth + google.auth.crypt.__init__: google_auth + google.auth.crypt._cryptography_rsa: google_auth + google.auth.crypt._helpers: google_auth + google.auth.crypt._python_rsa: google_auth + google.auth.crypt.base: google_auth + google.auth.crypt.es256: google_auth + google.auth.crypt.rsa: google_auth + google.auth.downscoped: google_auth + google.auth.environment_vars: google_auth + google.auth.exceptions: google_auth + google.auth.external_account: google_auth + google.auth.iam: google_auth + google.auth.identity_pool: google_auth + google.auth.impersonated_credentials: google_auth + google.auth.jwt: google_auth + google.auth.transport: google_auth + google.auth.transport.__init__: google_auth + google.auth.transport._aiohttp_requests: google_auth + google.auth.transport._http_client: google_auth + google.auth.transport._mtls_helper: google_auth + google.auth.transport.grpc: google_auth + google.auth.transport.mtls: google_auth + google.auth.transport.requests: google_auth + google.auth.transport.urllib3: google_auth + google.auth.version: google_auth + google.cloud._helpers: google_cloud_core + google.cloud._helpers.__init__: google_cloud_core + google.cloud._http: google_cloud_core + google.cloud._http.__init__: google_cloud_core + google.cloud._testing: google_cloud_core + google.cloud._testing.__init__: google_cloud_core + google.cloud.aiplatform: google_cloud_aiplatform + google.cloud.aiplatform.__init__: google_cloud_aiplatform + google.cloud.aiplatform._matching_engine: google_cloud_aiplatform + google.cloud.aiplatform._matching_engine.__init__: google_cloud_aiplatform + google.cloud.aiplatform._matching_engine.match_service_pb2: google_cloud_aiplatform + google.cloud.aiplatform._matching_engine.match_service_pb2_grpc: google_cloud_aiplatform + google.cloud.aiplatform._matching_engine.matching_engine_index: google_cloud_aiplatform + google.cloud.aiplatform._matching_engine.matching_engine_index_config: google_cloud_aiplatform + google.cloud.aiplatform._matching_engine.matching_engine_index_endpoint: google_cloud_aiplatform + google.cloud.aiplatform.base: google_cloud_aiplatform + google.cloud.aiplatform.compat: google_cloud_aiplatform + google.cloud.aiplatform.compat.__init__: google_cloud_aiplatform + google.cloud.aiplatform.compat.services: google_cloud_aiplatform + google.cloud.aiplatform.compat.services.__init__: google_cloud_aiplatform + google.cloud.aiplatform.compat.types: google_cloud_aiplatform + google.cloud.aiplatform.compat.types.__init__: google_cloud_aiplatform + google.cloud.aiplatform.constants: google_cloud_aiplatform + google.cloud.aiplatform.constants.__init__: google_cloud_aiplatform + google.cloud.aiplatform.constants.base: google_cloud_aiplatform + google.cloud.aiplatform.constants.prediction: google_cloud_aiplatform + google.cloud.aiplatform.datasets: google_cloud_aiplatform + google.cloud.aiplatform.datasets.__init__: google_cloud_aiplatform + google.cloud.aiplatform.datasets._datasources: google_cloud_aiplatform + google.cloud.aiplatform.datasets.column_names_dataset: google_cloud_aiplatform + google.cloud.aiplatform.datasets.dataset: google_cloud_aiplatform + google.cloud.aiplatform.datasets.image_dataset: google_cloud_aiplatform + google.cloud.aiplatform.datasets.tabular_dataset: google_cloud_aiplatform + google.cloud.aiplatform.datasets.text_dataset: google_cloud_aiplatform + google.cloud.aiplatform.datasets.time_series_dataset: google_cloud_aiplatform + google.cloud.aiplatform.datasets.video_dataset: google_cloud_aiplatform + google.cloud.aiplatform.explain: google_cloud_aiplatform + google.cloud.aiplatform.explain.__init__: google_cloud_aiplatform + google.cloud.aiplatform.explain.lit: google_cloud_aiplatform + google.cloud.aiplatform.explain.metadata: google_cloud_aiplatform + google.cloud.aiplatform.explain.metadata.__init__: google_cloud_aiplatform + google.cloud.aiplatform.explain.metadata.metadata_builder: google_cloud_aiplatform + google.cloud.aiplatform.explain.metadata.tf: google_cloud_aiplatform + google.cloud.aiplatform.explain.metadata.tf.__init__: google_cloud_aiplatform + google.cloud.aiplatform.explain.metadata.tf.v1: google_cloud_aiplatform + google.cloud.aiplatform.explain.metadata.tf.v1.__init__: google_cloud_aiplatform + google.cloud.aiplatform.explain.metadata.tf.v1.saved_model_metadata_builder: google_cloud_aiplatform + google.cloud.aiplatform.explain.metadata.tf.v2: google_cloud_aiplatform + google.cloud.aiplatform.explain.metadata.tf.v2.__init__: google_cloud_aiplatform + google.cloud.aiplatform.explain.metadata.tf.v2.saved_model_metadata_builder: google_cloud_aiplatform + google.cloud.aiplatform.featurestore: google_cloud_aiplatform + google.cloud.aiplatform.featurestore.__init__: google_cloud_aiplatform + google.cloud.aiplatform.featurestore.entity_type: google_cloud_aiplatform + google.cloud.aiplatform.featurestore.feature: google_cloud_aiplatform + google.cloud.aiplatform.featurestore.featurestore: google_cloud_aiplatform + google.cloud.aiplatform.gapic: google_cloud_aiplatform + google.cloud.aiplatform.gapic.__init__: google_cloud_aiplatform + google.cloud.aiplatform.gapic.schema: google_cloud_aiplatform + google.cloud.aiplatform.gapic.schema.__init__: google_cloud_aiplatform + google.cloud.aiplatform.helpers: google_cloud_aiplatform + google.cloud.aiplatform.helpers.__init__: google_cloud_aiplatform + google.cloud.aiplatform.helpers.container_uri_builders: google_cloud_aiplatform + google.cloud.aiplatform.hyperparameter_tuning: google_cloud_aiplatform + google.cloud.aiplatform.initializer: google_cloud_aiplatform + google.cloud.aiplatform.jobs: google_cloud_aiplatform + google.cloud.aiplatform.metadata: google_cloud_aiplatform + google.cloud.aiplatform.metadata.__init__: google_cloud_aiplatform + google.cloud.aiplatform.metadata.artifact: google_cloud_aiplatform + google.cloud.aiplatform.metadata.constants: google_cloud_aiplatform + google.cloud.aiplatform.metadata.context: google_cloud_aiplatform + google.cloud.aiplatform.metadata.execution: google_cloud_aiplatform + google.cloud.aiplatform.metadata.metadata: google_cloud_aiplatform + google.cloud.aiplatform.metadata.metadata_store: google_cloud_aiplatform + google.cloud.aiplatform.metadata.resource: google_cloud_aiplatform + google.cloud.aiplatform.model_evaluation: google_cloud_aiplatform + google.cloud.aiplatform.model_evaluation.__init__: google_cloud_aiplatform + google.cloud.aiplatform.model_evaluation.model_evaluation: google_cloud_aiplatform + google.cloud.aiplatform.models: google_cloud_aiplatform + google.cloud.aiplatform.pipeline_jobs: google_cloud_aiplatform + google.cloud.aiplatform.schema: google_cloud_aiplatform + google.cloud.aiplatform.tensorboard: google_cloud_aiplatform + google.cloud.aiplatform.tensorboard.__init__: google_cloud_aiplatform + google.cloud.aiplatform.tensorboard.plugins.tf_profiler.profile_uploader: google_cloud_aiplatform + google.cloud.aiplatform.tensorboard.tensorboard_resource: google_cloud_aiplatform + google.cloud.aiplatform.tensorboard.uploader: google_cloud_aiplatform + google.cloud.aiplatform.tensorboard.uploader_main: google_cloud_aiplatform + google.cloud.aiplatform.tensorboard.uploader_utils: google_cloud_aiplatform + google.cloud.aiplatform.training_jobs: google_cloud_aiplatform + google.cloud.aiplatform.training_utils: google_cloud_aiplatform + google.cloud.aiplatform.training_utils.__init__: google_cloud_aiplatform + google.cloud.aiplatform.training_utils.cloud_profiler: google_cloud_aiplatform + google.cloud.aiplatform.training_utils.cloud_profiler.__init__: google_cloud_aiplatform + google.cloud.aiplatform.training_utils.cloud_profiler.cloud_profiler_utils: google_cloud_aiplatform + google.cloud.aiplatform.training_utils.cloud_profiler.initializer: google_cloud_aiplatform + google.cloud.aiplatform.training_utils.cloud_profiler.plugins.base_plugin: google_cloud_aiplatform + google.cloud.aiplatform.training_utils.cloud_profiler.plugins.tensorflow.tensorboard_api: google_cloud_aiplatform + google.cloud.aiplatform.training_utils.cloud_profiler.plugins.tensorflow.tf_profiler: google_cloud_aiplatform + google.cloud.aiplatform.training_utils.cloud_profiler.webserver: google_cloud_aiplatform + google.cloud.aiplatform.training_utils.cloud_profiler.wsgi_types: google_cloud_aiplatform + google.cloud.aiplatform.training_utils.environment_variables: google_cloud_aiplatform + google.cloud.aiplatform.utils: google_cloud_aiplatform + google.cloud.aiplatform.utils.__init__: google_cloud_aiplatform + google.cloud.aiplatform.utils.column_transformations_utils: google_cloud_aiplatform + google.cloud.aiplatform.utils.console_utils: google_cloud_aiplatform + google.cloud.aiplatform.utils.enhanced_library: google_cloud_aiplatform + google.cloud.aiplatform.utils.enhanced_library.__init__: google_cloud_aiplatform + google.cloud.aiplatform.utils.enhanced_library._decorators: google_cloud_aiplatform + google.cloud.aiplatform.utils.enhanced_library.value_converter: google_cloud_aiplatform + google.cloud.aiplatform.utils.featurestore_utils: google_cloud_aiplatform + google.cloud.aiplatform.utils.gcs_utils: google_cloud_aiplatform + google.cloud.aiplatform.utils.pipeline_utils: google_cloud_aiplatform + google.cloud.aiplatform.utils.resource_manager_utils: google_cloud_aiplatform + google.cloud.aiplatform.utils.source_utils: google_cloud_aiplatform + google.cloud.aiplatform.utils.tensorboard_utils: google_cloud_aiplatform + google.cloud.aiplatform.utils.worker_spec_utils: google_cloud_aiplatform + google.cloud.aiplatform.utils.yaml_utils: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.instance: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.instance.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.instance_v1: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.instance_v1.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.instance_v1.types: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.instance_v1.types.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.instance_v1.types.image_classification: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.instance_v1.types.image_object_detection: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.instance_v1.types.image_segmentation: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.instance_v1.types.text_classification: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.instance_v1.types.text_extraction: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.instance_v1.types.text_sentiment: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.instance_v1.types.video_action_recognition: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.instance_v1.types.video_classification: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.instance_v1.types.video_object_tracking: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.params: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.params.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.params_v1: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.params_v1.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.params_v1.types: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.params_v1.types.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.params_v1.types.image_classification: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.params_v1.types.image_object_detection: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.params_v1.types.image_segmentation: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.params_v1.types.video_action_recognition: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.params_v1.types.video_classification: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.params_v1.types.video_object_tracking: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.prediction: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.prediction.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.prediction_v1: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.prediction_v1.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.prediction_v1.types: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.prediction_v1.types.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.prediction_v1.types.classification: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.prediction_v1.types.image_object_detection: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.prediction_v1.types.image_segmentation: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.prediction_v1.types.tabular_classification: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.prediction_v1.types.tabular_regression: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.prediction_v1.types.text_extraction: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.prediction_v1.types.text_sentiment: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.prediction_v1.types.video_action_recognition: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.prediction_v1.types.video_classification: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.predict.prediction_v1.types.video_object_tracking: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.trainingjob: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.trainingjob.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.trainingjob.definition: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.trainingjob.definition.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.trainingjob.definition_v1: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.trainingjob.definition_v1.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.trainingjob.definition_v1.types: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.trainingjob.definition_v1.types.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.trainingjob.definition_v1.types.automl_image_classification: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.trainingjob.definition_v1.types.automl_image_object_detection: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.trainingjob.definition_v1.types.automl_image_segmentation: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.trainingjob.definition_v1.types.automl_tables: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.trainingjob.definition_v1.types.automl_text_classification: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.trainingjob.definition_v1.types.automl_text_extraction: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.trainingjob.definition_v1.types.automl_text_sentiment: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.trainingjob.definition_v1.types.automl_video_action_recognition: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.trainingjob.definition_v1.types.automl_video_classification: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.trainingjob.definition_v1.types.automl_video_object_tracking: google_cloud_aiplatform + google.cloud.aiplatform.v1.schema.trainingjob.definition_v1.types.export_evaluated_data_items_config: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.instance: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.instance.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.instance_v1beta1: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.instance_v1beta1.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.instance_v1beta1.types: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.instance_v1beta1.types.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.instance_v1beta1.types.image_classification: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.instance_v1beta1.types.image_object_detection: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.instance_v1beta1.types.image_segmentation: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.instance_v1beta1.types.text_classification: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.instance_v1beta1.types.text_extraction: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.instance_v1beta1.types.text_sentiment: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.instance_v1beta1.types.video_action_recognition: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.instance_v1beta1.types.video_classification: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.instance_v1beta1.types.video_object_tracking: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.params: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.params.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.params_v1beta1: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.params_v1beta1.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.params_v1beta1.types: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.params_v1beta1.types.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.params_v1beta1.types.image_classification: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.params_v1beta1.types.image_object_detection: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.params_v1beta1.types.image_segmentation: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.params_v1beta1.types.video_action_recognition: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.params_v1beta1.types.video_classification: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.params_v1beta1.types.video_object_tracking: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.prediction: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.prediction.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.prediction_v1beta1: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.prediction_v1beta1.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.prediction_v1beta1.types: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.prediction_v1beta1.types.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.prediction_v1beta1.types.classification: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.prediction_v1beta1.types.image_object_detection: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.prediction_v1beta1.types.image_segmentation: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.prediction_v1beta1.types.tabular_classification: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.prediction_v1beta1.types.tabular_regression: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.prediction_v1beta1.types.text_extraction: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.prediction_v1beta1.types.text_sentiment: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.prediction_v1beta1.types.time_series_forecasting: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.prediction_v1beta1.types.video_action_recognition: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.prediction_v1beta1.types.video_classification: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.predict.prediction_v1beta1.types.video_object_tracking: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.trainingjob: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.trainingjob.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.trainingjob.definition: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.trainingjob.definition.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.trainingjob.definition_v1beta1: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.trainingjob.definition_v1beta1.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.trainingjob.definition_v1beta1.types: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.trainingjob.definition_v1beta1.types.__init__: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.trainingjob.definition_v1beta1.types.automl_forecasting: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.trainingjob.definition_v1beta1.types.automl_image_classification: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.trainingjob.definition_v1beta1.types.automl_image_object_detection: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.trainingjob.definition_v1beta1.types.automl_image_segmentation: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.trainingjob.definition_v1beta1.types.automl_tables: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.trainingjob.definition_v1beta1.types.automl_text_classification: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.trainingjob.definition_v1beta1.types.automl_text_extraction: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.trainingjob.definition_v1beta1.types.automl_text_sentiment: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.trainingjob.definition_v1beta1.types.automl_time_series_forecasting: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.trainingjob.definition_v1beta1.types.automl_video_action_recognition: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.trainingjob.definition_v1beta1.types.automl_video_classification: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.trainingjob.definition_v1beta1.types.automl_video_object_tracking: google_cloud_aiplatform + google.cloud.aiplatform.v1beta1.schema.trainingjob.definition_v1beta1.types.export_evaluated_data_items_config: google_cloud_aiplatform + google.cloud.aiplatform.version: google_cloud_aiplatform + google.cloud.aiplatform_v1: google_cloud_aiplatform + google.cloud.aiplatform_v1.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.dataset_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.dataset_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.dataset_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.dataset_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.dataset_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.dataset_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.dataset_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.dataset_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.dataset_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.dataset_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.endpoint_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.endpoint_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.endpoint_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.endpoint_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.endpoint_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.endpoint_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.endpoint_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.endpoint_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.endpoint_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.endpoint_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.featurestore_online_serving_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.featurestore_online_serving_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.featurestore_online_serving_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.featurestore_online_serving_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.featurestore_online_serving_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.featurestore_online_serving_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.featurestore_online_serving_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.featurestore_online_serving_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.featurestore_online_serving_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.featurestore_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.featurestore_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.featurestore_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.featurestore_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.featurestore_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.featurestore_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.featurestore_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.featurestore_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.featurestore_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.featurestore_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.index_endpoint_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.index_endpoint_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.index_endpoint_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.index_endpoint_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.index_endpoint_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.index_endpoint_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.index_endpoint_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.index_endpoint_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.index_endpoint_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.index_endpoint_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.index_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.index_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.index_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.index_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.index_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.index_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.index_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.index_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.index_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.index_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.job_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.job_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.job_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.job_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.job_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.job_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.job_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.job_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.job_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.job_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.metadata_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.metadata_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.metadata_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.metadata_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.metadata_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.metadata_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.metadata_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.metadata_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.metadata_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.metadata_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.migration_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.migration_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.migration_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.migration_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.migration_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.migration_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.migration_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.migration_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.migration_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.migration_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.model_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.model_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.model_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.model_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.model_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.model_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.model_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.model_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.model_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.model_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.pipeline_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.pipeline_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.pipeline_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.pipeline_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.pipeline_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.pipeline_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.pipeline_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.pipeline_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.pipeline_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.pipeline_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.prediction_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.prediction_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.prediction_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.prediction_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.prediction_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.prediction_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.prediction_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.prediction_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.prediction_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.specialist_pool_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.specialist_pool_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.specialist_pool_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.specialist_pool_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.specialist_pool_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.specialist_pool_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.specialist_pool_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.specialist_pool_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.specialist_pool_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.specialist_pool_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.tensorboard_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.tensorboard_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.tensorboard_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.tensorboard_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.tensorboard_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.tensorboard_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.tensorboard_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.tensorboard_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.tensorboard_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.tensorboard_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.vizier_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.vizier_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.vizier_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.vizier_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.vizier_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.vizier_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.vizier_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.vizier_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.vizier_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1.services.vizier_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1.types: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.accelerator_type: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.annotation: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.annotation_spec: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.artifact: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.batch_prediction_job: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.completion_stats: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.context: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.custom_job: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.data_item: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.data_labeling_job: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.dataset: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.dataset_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.deployed_index_ref: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.deployed_model_ref: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.encryption_spec: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.endpoint: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.endpoint_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.entity_type: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.env_var: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.event: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.execution: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.explanation: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.explanation_metadata: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.feature: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.feature_monitoring_stats: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.feature_selector: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.featurestore: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.featurestore_monitoring: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.featurestore_online_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.featurestore_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.hyperparameter_tuning_job: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.index: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.index_endpoint: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.index_endpoint_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.index_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.io: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.job_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.job_state: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.lineage_subgraph: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.machine_resources: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.manual_batch_tuning_parameters: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.metadata_schema: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.metadata_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.metadata_store: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.migratable_resource: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.migration_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.model: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.model_deployment_monitoring_job: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.model_evaluation: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.model_evaluation_slice: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.model_monitoring: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.model_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.operation: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.pipeline_job: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.pipeline_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.pipeline_state: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.prediction_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.specialist_pool: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.specialist_pool_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.study: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.tensorboard: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.tensorboard_data: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.tensorboard_experiment: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.tensorboard_run: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.tensorboard_service: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.tensorboard_time_series: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.training_pipeline: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.types: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.unmanaged_container_model: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.user_action_reference: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.value: google_cloud_aiplatform + google.cloud.aiplatform_v1.types.vizier_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.dataset_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.dataset_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.dataset_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.dataset_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.dataset_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.dataset_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.dataset_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.dataset_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.dataset_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.dataset_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.endpoint_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.endpoint_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.endpoint_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.endpoint_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.endpoint_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.endpoint_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.endpoint_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.endpoint_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.endpoint_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.endpoint_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.featurestore_online_serving_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.featurestore_online_serving_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.featurestore_online_serving_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.featurestore_online_serving_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.featurestore_online_serving_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.featurestore_online_serving_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.featurestore_online_serving_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.featurestore_online_serving_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.featurestore_online_serving_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.featurestore_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.featurestore_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.featurestore_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.featurestore_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.featurestore_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.featurestore_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.featurestore_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.featurestore_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.featurestore_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.featurestore_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.index_endpoint_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.index_endpoint_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.index_endpoint_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.index_endpoint_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.index_endpoint_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.index_endpoint_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.index_endpoint_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.index_endpoint_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.index_endpoint_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.index_endpoint_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.index_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.index_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.index_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.index_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.index_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.index_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.index_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.index_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.index_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.index_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.job_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.job_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.job_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.job_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.job_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.job_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.job_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.job_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.job_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.job_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.metadata_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.metadata_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.metadata_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.metadata_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.metadata_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.metadata_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.metadata_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.metadata_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.metadata_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.metadata_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.migration_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.migration_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.migration_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.migration_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.migration_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.migration_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.migration_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.migration_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.migration_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.migration_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.model_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.model_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.model_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.model_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.model_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.model_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.model_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.model_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.model_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.model_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.pipeline_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.pipeline_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.pipeline_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.pipeline_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.pipeline_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.pipeline_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.pipeline_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.pipeline_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.pipeline_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.pipeline_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.prediction_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.prediction_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.prediction_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.prediction_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.prediction_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.prediction_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.prediction_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.prediction_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.prediction_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.specialist_pool_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.specialist_pool_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.specialist_pool_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.specialist_pool_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.specialist_pool_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.specialist_pool_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.specialist_pool_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.specialist_pool_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.specialist_pool_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.specialist_pool_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.tensorboard_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.tensorboard_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.tensorboard_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.tensorboard_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.tensorboard_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.tensorboard_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.tensorboard_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.tensorboard_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.tensorboard_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.tensorboard_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.vizier_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.vizier_service.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.vizier_service.async_client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.vizier_service.client: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.vizier_service.pagers: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.vizier_service.transports: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.vizier_service.transports.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.vizier_service.transports.base: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.vizier_service.transports.grpc: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.services.vizier_service.transports.grpc_asyncio: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.__init__: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.accelerator_type: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.annotation: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.annotation_spec: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.artifact: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.batch_prediction_job: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.completion_stats: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.context: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.custom_job: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.data_item: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.data_labeling_job: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.dataset: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.dataset_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.deployed_index_ref: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.deployed_model_ref: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.encryption_spec: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.endpoint: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.endpoint_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.entity_type: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.env_var: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.event: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.execution: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.explanation: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.explanation_metadata: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.feature: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.feature_monitoring_stats: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.feature_selector: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.featurestore: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.featurestore_monitoring: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.featurestore_online_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.featurestore_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.hyperparameter_tuning_job: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.index: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.index_endpoint: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.index_endpoint_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.index_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.io: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.job_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.job_state: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.lineage_subgraph: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.machine_resources: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.manual_batch_tuning_parameters: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.metadata_schema: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.metadata_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.metadata_store: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.migratable_resource: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.migration_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.model: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.model_deployment_monitoring_job: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.model_evaluation: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.model_evaluation_slice: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.model_monitoring: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.model_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.operation: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.pipeline_job: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.pipeline_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.pipeline_state: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.prediction_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.specialist_pool: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.specialist_pool_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.study: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.tensorboard: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.tensorboard_data: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.tensorboard_experiment: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.tensorboard_run: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.tensorboard_service: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.tensorboard_time_series: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.training_pipeline: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.types: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.unmanaged_container_model: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.user_action_reference: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.value: google_cloud_aiplatform + google.cloud.aiplatform_v1beta1.types.vizier_service: google_cloud_aiplatform + google.cloud.bigquery: google_cloud_bigquery + google.cloud.bigquery.__init__: google_cloud_bigquery + google.cloud.bigquery._helpers: google_cloud_bigquery + google.cloud.bigquery._http: google_cloud_bigquery + google.cloud.bigquery._pandas_helpers: google_cloud_bigquery + google.cloud.bigquery._tqdm_helpers: google_cloud_bigquery + google.cloud.bigquery.client: google_cloud_bigquery + google.cloud.bigquery.dataset: google_cloud_bigquery + google.cloud.bigquery.dbapi: google_cloud_bigquery + google.cloud.bigquery.dbapi.__init__: google_cloud_bigquery + google.cloud.bigquery.dbapi._helpers: google_cloud_bigquery + google.cloud.bigquery.dbapi.connection: google_cloud_bigquery + google.cloud.bigquery.dbapi.cursor: google_cloud_bigquery + google.cloud.bigquery.dbapi.exceptions: google_cloud_bigquery + google.cloud.bigquery.dbapi.types: google_cloud_bigquery + google.cloud.bigquery.encryption_configuration: google_cloud_bigquery + google.cloud.bigquery.enums: google_cloud_bigquery + google.cloud.bigquery.exceptions: google_cloud_bigquery + google.cloud.bigquery.external_config: google_cloud_bigquery + google.cloud.bigquery.format_options: google_cloud_bigquery + google.cloud.bigquery.iam: google_cloud_bigquery + google.cloud.bigquery.job: google_cloud_bigquery + google.cloud.bigquery.job.__init__: google_cloud_bigquery + google.cloud.bigquery.job.base: google_cloud_bigquery + google.cloud.bigquery.job.copy_: google_cloud_bigquery + google.cloud.bigquery.job.extract: google_cloud_bigquery + google.cloud.bigquery.job.load: google_cloud_bigquery + google.cloud.bigquery.job.query: google_cloud_bigquery + google.cloud.bigquery.magics: google_cloud_bigquery + google.cloud.bigquery.magics.__init__: google_cloud_bigquery + google.cloud.bigquery.magics.line_arg_parser: google_cloud_bigquery + google.cloud.bigquery.magics.line_arg_parser.__init__: google_cloud_bigquery + google.cloud.bigquery.magics.line_arg_parser.exceptions: google_cloud_bigquery + google.cloud.bigquery.magics.line_arg_parser.lexer: google_cloud_bigquery + google.cloud.bigquery.magics.line_arg_parser.parser: google_cloud_bigquery + google.cloud.bigquery.magics.line_arg_parser.visitors: google_cloud_bigquery + google.cloud.bigquery.magics.magics: google_cloud_bigquery + google.cloud.bigquery.model: google_cloud_bigquery + google.cloud.bigquery.opentelemetry_tracing: google_cloud_bigquery + google.cloud.bigquery.query: google_cloud_bigquery + google.cloud.bigquery.retry: google_cloud_bigquery + google.cloud.bigquery.routine: google_cloud_bigquery + google.cloud.bigquery.routine.__init__: google_cloud_bigquery + google.cloud.bigquery.routine.routine: google_cloud_bigquery + google.cloud.bigquery.schema: google_cloud_bigquery + google.cloud.bigquery.table: google_cloud_bigquery + google.cloud.bigquery.version: google_cloud_bigquery + google.cloud.bigquery_v2: google_cloud_bigquery + google.cloud.bigquery_v2.__init__: google_cloud_bigquery + google.cloud.bigquery_v2.types: google_cloud_bigquery + google.cloud.bigquery_v2.types.__init__: google_cloud_bigquery + google.cloud.bigquery_v2.types.encryption_config: google_cloud_bigquery + google.cloud.bigquery_v2.types.model: google_cloud_bigquery + google.cloud.bigquery_v2.types.model_reference: google_cloud_bigquery + google.cloud.bigquery_v2.types.standard_sql: google_cloud_bigquery + google.cloud.bigquery_v2.types.table_reference: google_cloud_bigquery + google.cloud.client: google_cloud_core + google.cloud.client.__init__: google_cloud_core + google.cloud.environment_vars: google_cloud_core + google.cloud.environment_vars.__init__: google_cloud_core + google.cloud.exceptions: google_cloud_core + google.cloud.exceptions.__init__: google_cloud_core + google.cloud.extended_operations_pb2: googleapis_common_protos + google.cloud.location.locations_pb2: googleapis_common_protos + google.cloud.obsolete: google_cloud_core + google.cloud.obsolete.__init__: google_cloud_core + google.cloud.operation: google_cloud_core + google.cloud.operation.__init__: google_cloud_core + google.cloud.resourcemanager: google_cloud_resource_manager + google.cloud.resourcemanager.__init__: google_cloud_resource_manager + google.cloud.resourcemanager_v3: google_cloud_resource_manager + google.cloud.resourcemanager_v3.__init__: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.__init__: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.folders: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.folders.__init__: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.folders.async_client: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.folders.client: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.folders.pagers: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.folders.transports: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.folders.transports.__init__: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.folders.transports.base: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.folders.transports.grpc: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.folders.transports.grpc_asyncio: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.organizations: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.organizations.__init__: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.organizations.async_client: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.organizations.client: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.organizations.pagers: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.organizations.transports: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.organizations.transports.__init__: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.organizations.transports.base: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.organizations.transports.grpc: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.organizations.transports.grpc_asyncio: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.projects: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.projects.__init__: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.projects.async_client: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.projects.client: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.projects.pagers: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.projects.transports: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.projects.transports.__init__: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.projects.transports.base: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.projects.transports.grpc: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.projects.transports.grpc_asyncio: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_bindings: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_bindings.__init__: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_bindings.async_client: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_bindings.client: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_bindings.pagers: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_bindings.transports: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_bindings.transports.__init__: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_bindings.transports.base: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_bindings.transports.grpc: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_bindings.transports.grpc_asyncio: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_keys: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_keys.__init__: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_keys.async_client: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_keys.client: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_keys.pagers: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_keys.transports: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_keys.transports.__init__: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_keys.transports.base: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_keys.transports.grpc: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_keys.transports.grpc_asyncio: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_values: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_values.__init__: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_values.async_client: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_values.client: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_values.pagers: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_values.transports: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_values.transports.__init__: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_values.transports.base: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_values.transports.grpc: google_cloud_resource_manager + google.cloud.resourcemanager_v3.services.tag_values.transports.grpc_asyncio: google_cloud_resource_manager + google.cloud.resourcemanager_v3.types: google_cloud_resource_manager + google.cloud.resourcemanager_v3.types.__init__: google_cloud_resource_manager + google.cloud.resourcemanager_v3.types.folders: google_cloud_resource_manager + google.cloud.resourcemanager_v3.types.organizations: google_cloud_resource_manager + google.cloud.resourcemanager_v3.types.projects: google_cloud_resource_manager + google.cloud.resourcemanager_v3.types.tag_bindings: google_cloud_resource_manager + google.cloud.resourcemanager_v3.types.tag_keys: google_cloud_resource_manager + google.cloud.resourcemanager_v3.types.tag_values: google_cloud_resource_manager + google.cloud.storage: google_cloud_storage + google.cloud.storage.__init__: google_cloud_storage + google.cloud.storage._helpers: google_cloud_storage + google.cloud.storage._http: google_cloud_storage + google.cloud.storage._signing: google_cloud_storage + google.cloud.storage.acl: google_cloud_storage + google.cloud.storage.batch: google_cloud_storage + google.cloud.storage.blob: google_cloud_storage + google.cloud.storage.bucket: google_cloud_storage + google.cloud.storage.client: google_cloud_storage + google.cloud.storage.constants: google_cloud_storage + google.cloud.storage.fileio: google_cloud_storage + google.cloud.storage.hmac_key: google_cloud_storage + google.cloud.storage.iam: google_cloud_storage + google.cloud.storage.notification: google_cloud_storage + google.cloud.storage.retry: google_cloud_storage + google.cloud.storage.version: google_cloud_storage + google.cloud.version: google_cloud_core + google.gapic.metadata: googleapis_common_protos + google.gapic.metadata.__init__: googleapis_common_protos + google.gapic.metadata.gapic_metadata_pb2: googleapis_common_protos + google.iam.v1: grpc_google_iam_v1 + google.iam.v1.__init__: grpc_google_iam_v1 + google.iam.v1.iam_policy_pb2: grpc_google_iam_v1 + google.iam.v1.iam_policy_pb2_grpc: grpc_google_iam_v1 + google.iam.v1.logging: grpc_google_iam_v1 + google.iam.v1.logging.__init__: grpc_google_iam_v1 + google.iam.v1.logging.audit_data_pb2: grpc_google_iam_v1 + google.iam.v1.options_pb2: grpc_google_iam_v1 + google.iam.v1.options_pb2_grpc: grpc_google_iam_v1 + google.iam.v1.policy_pb2: grpc_google_iam_v1 + google.iam.v1.policy_pb2_grpc: grpc_google_iam_v1 + google.logging.type: googleapis_common_protos + google.logging.type.__init__: googleapis_common_protos + google.logging.type.http_request_pb2: googleapis_common_protos + google.logging.type.log_severity_pb2: googleapis_common_protos + google.longrunning: googleapis_common_protos + google.longrunning.__init__: googleapis_common_protos + google.longrunning.operations_grpc: googleapis_common_protos + google.longrunning.operations_grpc_pb2: googleapis_common_protos + google.longrunning.operations_pb2: googleapis_common_protos + google.longrunning.operations_pb2_grpc: googleapis_common_protos + google.longrunning.operations_proto: googleapis_common_protos + google.longrunning.operations_proto_pb2: googleapis_common_protos + google.oauth2: google_auth + google.oauth2.__init__: google_auth + google.oauth2._client: google_auth + google.oauth2._client_async: google_auth + google.oauth2._credentials_async: google_auth + google.oauth2._id_token_async: google_auth + google.oauth2._reauth_async: google_auth + google.oauth2._service_account_async: google_auth + google.oauth2.challenges: google_auth + google.oauth2.credentials: google_auth + google.oauth2.id_token: google_auth + google.oauth2.reauth: google_auth + google.oauth2.service_account: google_auth + google.oauth2.sts: google_auth + google.oauth2.utils: google_auth + google.protobuf: protobuf + google.protobuf.__init__: protobuf + google.protobuf.any_pb2: protobuf + google.protobuf.api_pb2: protobuf + google.protobuf.compiler: protobuf + google.protobuf.compiler.__init__: protobuf + google.protobuf.compiler.plugin_pb2: protobuf + google.protobuf.descriptor: protobuf + google.protobuf.descriptor_database: protobuf + google.protobuf.descriptor_pb2: protobuf + google.protobuf.descriptor_pool: protobuf + google.protobuf.duration_pb2: protobuf + google.protobuf.empty_pb2: protobuf + google.protobuf.field_mask_pb2: protobuf + google.protobuf.internal: protobuf + google.protobuf.internal.__init__: protobuf + google.protobuf.internal._api_implementation: protobuf + google.protobuf.internal.api_implementation: protobuf + google.protobuf.internal.builder: protobuf + google.protobuf.internal.containers: protobuf + google.protobuf.internal.decoder: protobuf + google.protobuf.internal.encoder: protobuf + google.protobuf.internal.enum_type_wrapper: protobuf + google.protobuf.internal.extension_dict: protobuf + google.protobuf.internal.message_listener: protobuf + google.protobuf.internal.python_message: protobuf + google.protobuf.internal.type_checkers: protobuf + google.protobuf.internal.well_known_types: protobuf + google.protobuf.internal.wire_format: protobuf + google.protobuf.json_format: protobuf + google.protobuf.message: protobuf + google.protobuf.message_factory: protobuf + google.protobuf.proto_builder: protobuf + google.protobuf.pyext: protobuf + google.protobuf.pyext.__init__: protobuf + google.protobuf.pyext._message: protobuf + google.protobuf.pyext.cpp_message: protobuf + google.protobuf.reflection: protobuf + google.protobuf.service: protobuf + google.protobuf.service_reflection: protobuf + google.protobuf.source_context_pb2: protobuf + google.protobuf.struct_pb2: protobuf + google.protobuf.symbol_database: protobuf + google.protobuf.text_encoding: protobuf + google.protobuf.text_format: protobuf + google.protobuf.timestamp_pb2: protobuf + google.protobuf.type_pb2: protobuf + google.protobuf.util: protobuf + google.protobuf.util.__init__: protobuf + google.protobuf.util.json_format_pb2: protobuf + google.protobuf.util.json_format_proto3_pb2: protobuf + google.protobuf.wrappers_pb2: protobuf + google.resumable_media: google_resumable_media + google.resumable_media.__init__: google_resumable_media + google.resumable_media._download: google_resumable_media + google.resumable_media._helpers: google_resumable_media + google.resumable_media._upload: google_resumable_media + google.resumable_media.common: google_resumable_media + google.resumable_media.requests: google_resumable_media + google.resumable_media.requests.__init__: google_resumable_media + google.resumable_media.requests._request_helpers: google_resumable_media + google.resumable_media.requests.download: google_resumable_media + google.resumable_media.requests.upload: google_resumable_media + google.rpc: googleapis_common_protos + google.rpc.__init__: googleapis_common_protos + google.rpc.code_pb2: googleapis_common_protos + google.rpc.context: googleapis_common_protos + google.rpc.context.__init__: googleapis_common_protos + google.rpc.context.attribute_context_pb2: googleapis_common_protos + google.rpc.error_details_pb2: googleapis_common_protos + google.rpc.status_pb2: googleapis_common_protos + google.type: googleapis_common_protos + google.type.__init__: googleapis_common_protos + google.type.calendar_period_pb2: googleapis_common_protos + google.type.color_pb2: googleapis_common_protos + google.type.date_pb2: googleapis_common_protos + google.type.datetime_pb2: googleapis_common_protos + google.type.dayofweek_pb2: googleapis_common_protos + google.type.decimal_pb2: googleapis_common_protos + google.type.expr_pb2: googleapis_common_protos + google.type.fraction_pb2: googleapis_common_protos + google.type.interval_pb2: googleapis_common_protos + google.type.latlng_pb2: googleapis_common_protos + google.type.localized_text_pb2: googleapis_common_protos + google.type.money_pb2: googleapis_common_protos + google.type.month_pb2: googleapis_common_protos + google.type.phone_number_pb2: googleapis_common_protos + google.type.postal_address_pb2: googleapis_common_protos + google.type.quaternion_pb2: googleapis_common_protos + google.type.timeofday_pb2: googleapis_common_protos + google_crc32c: google_crc32c + google_crc32c.__config__: google_crc32c + google_crc32c.__init__: google_crc32c + google_crc32c._checksum: google_crc32c + google_crc32c._crc32c: google_crc32c + google_crc32c.cext: google_crc32c + google_crc32c.libs.libcrc32c-672e1704: google_crc32c + google_crc32c.python: google_crc32c + grpc: grpcio + grpc.__init__: grpcio + grpc._auth: grpcio + grpc._channel: grpcio + grpc._common: grpcio + grpc._compression: grpcio + grpc._cython: grpcio + grpc._cython.__init__: grpcio + grpc._cython._cygrpc: grpcio + grpc._cython._cygrpc.__init__: grpcio + grpc._cython.cygrpc: grpcio + grpc._grpcio_metadata: grpcio + grpc._interceptor: grpcio + grpc._plugin_wrapping: grpcio + grpc._runtime_protos: grpcio + grpc._server: grpcio + grpc._simple_stubs: grpcio + grpc._utilities: grpcio + grpc.aio: grpcio + grpc.aio.__init__: grpcio + grpc.aio._base_call: grpcio + grpc.aio._base_channel: grpcio + grpc.aio._base_server: grpcio + grpc.aio._call: grpcio + grpc.aio._channel: grpcio + grpc.aio._interceptor: grpcio + grpc.aio._metadata: grpcio + grpc.aio._server: grpcio + grpc.aio._typing: grpcio + grpc.aio._utils: grpcio + grpc.beta: grpcio + grpc.beta.__init__: grpcio + grpc.beta._client_adaptations: grpcio + grpc.beta._metadata: grpcio + grpc.beta._server_adaptations: grpcio + grpc.beta.implementations: grpcio + grpc.beta.interfaces: grpcio + grpc.beta.utilities: grpcio + grpc.experimental: grpcio + grpc.experimental.__init__: grpcio + grpc.experimental.aio: grpcio + grpc.experimental.aio.__init__: grpcio + grpc.experimental.gevent: grpcio + grpc.experimental.session_cache: grpcio + grpc.framework: grpcio + grpc.framework.__init__: grpcio + grpc.framework.common: grpcio + grpc.framework.common.__init__: grpcio + grpc.framework.common.cardinality: grpcio + grpc.framework.common.style: grpcio + grpc.framework.foundation: grpcio + grpc.framework.foundation.__init__: grpcio + grpc.framework.foundation.abandonment: grpcio + grpc.framework.foundation.callable_util: grpcio + grpc.framework.foundation.future: grpcio + grpc.framework.foundation.logging_pool: grpcio + grpc.framework.foundation.stream: grpcio + grpc.framework.foundation.stream_util: grpcio + grpc.framework.interfaces: grpcio + grpc.framework.interfaces.__init__: grpcio + grpc.framework.interfaces.base: grpcio + grpc.framework.interfaces.base.__init__: grpcio + grpc.framework.interfaces.base.base: grpcio + grpc.framework.interfaces.base.utilities: grpcio + grpc.framework.interfaces.face: grpcio + grpc.framework.interfaces.face.__init__: grpcio + grpc.framework.interfaces.face.face: grpcio + grpc.framework.interfaces.face.utilities: grpcio + grpc_status: grpcio_status + grpc_status.__init__: grpcio_status + grpc_status._async: grpcio_status + grpc_status._common: grpcio_status + grpc_status.rpc_status: grpcio_status + idna: idna + idna.__init__: idna + idna.codec: idna + idna.compat: idna + idna.core: idna + idna.idnadata: idna + idna.intranges: idna + idna.package_data: idna + idna.uts46data: idna + packaging: packaging + packaging.__about__: packaging + packaging.__init__: packaging + packaging._manylinux: packaging + packaging._musllinux: packaging + packaging._structures: packaging + packaging.markers: packaging + packaging.requirements: packaging + packaging.specifiers: packaging + packaging.tags: packaging + packaging.utils: packaging + packaging.version: packaging + proto: proto_plus + proto.__init__: proto_plus + proto._file_info: proto_plus + proto._package_info: proto_plus + proto.datetime_helpers: proto_plus + proto.enums: proto_plus + proto.fields: proto_plus + proto.marshal: proto_plus + proto.marshal.__init__: proto_plus + proto.marshal.collections: proto_plus + proto.marshal.collections.__init__: proto_plus + proto.marshal.collections.maps: proto_plus + proto.marshal.collections.repeated: proto_plus + proto.marshal.compat: proto_plus + proto.marshal.marshal: proto_plus + proto.marshal.rules: proto_plus + proto.marshal.rules.__init__: proto_plus + proto.marshal.rules.bytes: proto_plus + proto.marshal.rules.dates: proto_plus + proto.marshal.rules.enums: proto_plus + proto.marshal.rules.message: proto_plus + proto.marshal.rules.stringy_numbers: proto_plus + proto.marshal.rules.struct: proto_plus + proto.marshal.rules.wrappers: proto_plus + proto.message: proto_plus + proto.modules: proto_plus + proto.primitives: proto_plus + proto.utils: proto_plus + pyasn1: pyasn1 + pyasn1.__init__: pyasn1 + pyasn1.codec: pyasn1 + pyasn1.codec.__init__: pyasn1 + pyasn1.codec.ber: pyasn1 + pyasn1.codec.ber.__init__: pyasn1 + pyasn1.codec.ber.decoder: pyasn1 + pyasn1.codec.ber.encoder: pyasn1 + pyasn1.codec.ber.eoo: pyasn1 + pyasn1.codec.cer: pyasn1 + pyasn1.codec.cer.__init__: pyasn1 + pyasn1.codec.cer.decoder: pyasn1 + pyasn1.codec.cer.encoder: pyasn1 + pyasn1.codec.der: pyasn1 + pyasn1.codec.der.__init__: pyasn1 + pyasn1.codec.der.decoder: pyasn1 + pyasn1.codec.der.encoder: pyasn1 + pyasn1.codec.native: pyasn1 + pyasn1.codec.native.__init__: pyasn1 + pyasn1.codec.native.decoder: pyasn1 + pyasn1.codec.native.encoder: pyasn1 + pyasn1.compat: pyasn1 + pyasn1.compat.__init__: pyasn1 + pyasn1.compat.binary: pyasn1 + pyasn1.compat.calling: pyasn1 + pyasn1.compat.dateandtime: pyasn1 + pyasn1.compat.integer: pyasn1 + pyasn1.compat.octets: pyasn1 + pyasn1.compat.string: pyasn1 + pyasn1.debug: pyasn1 + pyasn1.error: pyasn1 + pyasn1.type: pyasn1 + pyasn1.type.__init__: pyasn1 + pyasn1.type.base: pyasn1 + pyasn1.type.char: pyasn1 + pyasn1.type.constraint: pyasn1 + pyasn1.type.error: pyasn1 + pyasn1.type.namedtype: pyasn1 + pyasn1.type.namedval: pyasn1 + pyasn1.type.opentype: pyasn1 + pyasn1.type.tag: pyasn1 + pyasn1.type.tagmap: pyasn1 + pyasn1.type.univ: pyasn1 + pyasn1.type.useful: pyasn1 + pyasn1_modules: pyasn1_modules + pyasn1_modules.__init__: pyasn1_modules + pyasn1_modules.pem: pyasn1_modules + pyasn1_modules.rfc1155: pyasn1_modules + pyasn1_modules.rfc1157: pyasn1_modules + pyasn1_modules.rfc1901: pyasn1_modules + pyasn1_modules.rfc1902: pyasn1_modules + pyasn1_modules.rfc1905: pyasn1_modules + pyasn1_modules.rfc2251: pyasn1_modules + pyasn1_modules.rfc2314: pyasn1_modules + pyasn1_modules.rfc2315: pyasn1_modules + pyasn1_modules.rfc2437: pyasn1_modules + pyasn1_modules.rfc2459: pyasn1_modules + pyasn1_modules.rfc2511: pyasn1_modules + pyasn1_modules.rfc2560: pyasn1_modules + pyasn1_modules.rfc2631: pyasn1_modules + pyasn1_modules.rfc2634: pyasn1_modules + pyasn1_modules.rfc2985: pyasn1_modules + pyasn1_modules.rfc2986: pyasn1_modules + pyasn1_modules.rfc3114: pyasn1_modules + pyasn1_modules.rfc3161: pyasn1_modules + pyasn1_modules.rfc3274: pyasn1_modules + pyasn1_modules.rfc3279: pyasn1_modules + pyasn1_modules.rfc3280: pyasn1_modules + pyasn1_modules.rfc3281: pyasn1_modules + pyasn1_modules.rfc3412: pyasn1_modules + pyasn1_modules.rfc3414: pyasn1_modules + pyasn1_modules.rfc3447: pyasn1_modules + pyasn1_modules.rfc3560: pyasn1_modules + pyasn1_modules.rfc3565: pyasn1_modules + pyasn1_modules.rfc3709: pyasn1_modules + pyasn1_modules.rfc3770: pyasn1_modules + pyasn1_modules.rfc3779: pyasn1_modules + pyasn1_modules.rfc3852: pyasn1_modules + pyasn1_modules.rfc4043: pyasn1_modules + pyasn1_modules.rfc4055: pyasn1_modules + pyasn1_modules.rfc4073: pyasn1_modules + pyasn1_modules.rfc4108: pyasn1_modules + pyasn1_modules.rfc4210: pyasn1_modules + pyasn1_modules.rfc4211: pyasn1_modules + pyasn1_modules.rfc4334: pyasn1_modules + pyasn1_modules.rfc4985: pyasn1_modules + pyasn1_modules.rfc5035: pyasn1_modules + pyasn1_modules.rfc5083: pyasn1_modules + pyasn1_modules.rfc5084: pyasn1_modules + pyasn1_modules.rfc5208: pyasn1_modules + pyasn1_modules.rfc5280: pyasn1_modules + pyasn1_modules.rfc5480: pyasn1_modules + pyasn1_modules.rfc5649: pyasn1_modules + pyasn1_modules.rfc5652: pyasn1_modules + pyasn1_modules.rfc5751: pyasn1_modules + pyasn1_modules.rfc5755: pyasn1_modules + pyasn1_modules.rfc5913: pyasn1_modules + pyasn1_modules.rfc5914: pyasn1_modules + pyasn1_modules.rfc5915: pyasn1_modules + pyasn1_modules.rfc5916: pyasn1_modules + pyasn1_modules.rfc5917: pyasn1_modules + pyasn1_modules.rfc5924: pyasn1_modules + pyasn1_modules.rfc5934: pyasn1_modules + pyasn1_modules.rfc5940: pyasn1_modules + pyasn1_modules.rfc5958: pyasn1_modules + pyasn1_modules.rfc5990: pyasn1_modules + pyasn1_modules.rfc6010: pyasn1_modules + pyasn1_modules.rfc6019: pyasn1_modules + pyasn1_modules.rfc6031: pyasn1_modules + pyasn1_modules.rfc6032: pyasn1_modules + pyasn1_modules.rfc6120: pyasn1_modules + pyasn1_modules.rfc6170: pyasn1_modules + pyasn1_modules.rfc6187: pyasn1_modules + pyasn1_modules.rfc6210: pyasn1_modules + pyasn1_modules.rfc6211: pyasn1_modules + pyasn1_modules.rfc6402: pyasn1_modules + pyasn1_modules.rfc6402-1: pyasn1_modules + pyasn1_modules.rfc6482: pyasn1_modules + pyasn1_modules.rfc6486: pyasn1_modules + pyasn1_modules.rfc6487: pyasn1_modules + pyasn1_modules.rfc6664: pyasn1_modules + pyasn1_modules.rfc6955: pyasn1_modules + pyasn1_modules.rfc6960: pyasn1_modules + pyasn1_modules.rfc7030: pyasn1_modules + pyasn1_modules.rfc7191: pyasn1_modules + pyasn1_modules.rfc7229: pyasn1_modules + pyasn1_modules.rfc7292: pyasn1_modules + pyasn1_modules.rfc7296: pyasn1_modules + pyasn1_modules.rfc7508: pyasn1_modules + pyasn1_modules.rfc7585: pyasn1_modules + pyasn1_modules.rfc7633: pyasn1_modules + pyasn1_modules.rfc7773: pyasn1_modules + pyasn1_modules.rfc7894: pyasn1_modules + pyasn1_modules.rfc7894-1: pyasn1_modules + pyasn1_modules.rfc7906: pyasn1_modules + pyasn1_modules.rfc7914: pyasn1_modules + pyasn1_modules.rfc8017: pyasn1_modules + pyasn1_modules.rfc8018: pyasn1_modules + pyasn1_modules.rfc8103: pyasn1_modules + pyasn1_modules.rfc8209: pyasn1_modules + pyasn1_modules.rfc8226: pyasn1_modules + pyasn1_modules.rfc8358: pyasn1_modules + pyasn1_modules.rfc8360: pyasn1_modules + pyasn1_modules.rfc8398: pyasn1_modules + pyasn1_modules.rfc8410: pyasn1_modules + pyasn1_modules.rfc8418: pyasn1_modules + pyasn1_modules.rfc8419: pyasn1_modules + pyasn1_modules.rfc8479: pyasn1_modules + pyasn1_modules.rfc8494: pyasn1_modules + pyasn1_modules.rfc8520: pyasn1_modules + pyasn1_modules.rfc8619: pyasn1_modules + pyasn1_modules.rfc8649: pyasn1_modules + pyparsing: pyparsing + pyparsing.__init__: pyparsing + pyparsing.actions: pyparsing + pyparsing.common: pyparsing + pyparsing.core: pyparsing + pyparsing.diagram: pyparsing + pyparsing.diagram.__init__: pyparsing + pyparsing.exceptions: pyparsing + pyparsing.helpers: pyparsing + pyparsing.results: pyparsing + pyparsing.testing: pyparsing + pyparsing.unicode: pyparsing + pyparsing.util: pyparsing + requests: requests + requests.__init__: requests + requests.__version__: requests + requests._internal_utils: requests + requests.adapters: requests + requests.api: requests + requests.auth: requests + requests.certs: requests + requests.compat: requests + requests.cookies: requests + requests.exceptions: requests + requests.help: requests + requests.hooks: requests + requests.models: requests + requests.packages: requests + requests.sessions: requests + requests.status_codes: requests + requests.structures: requests + requests.utils: requests + rsa: rsa + rsa.__init__: rsa + rsa._compat: rsa + rsa.asn1: rsa + rsa.cli: rsa + rsa.common: rsa + rsa.core: rsa + rsa.key: rsa + rsa.parallel: rsa + rsa.pem: rsa + rsa.pkcs1: rsa + rsa.pkcs1_v2: rsa + rsa.prime: rsa + rsa.randnum: rsa + rsa.transform: rsa + rsa.util: rsa + samples.generated_samples.cloudresourcemanager_v3_generated_folders_create_folder_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_folders_create_folder_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_folders_delete_folder_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_folders_delete_folder_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_folders_get_folder_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_folders_get_folder_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_folders_get_iam_policy_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_folders_get_iam_policy_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_folders_list_folders_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_folders_list_folders_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_folders_move_folder_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_folders_move_folder_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_folders_search_folders_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_folders_search_folders_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_folders_set_iam_policy_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_folders_set_iam_policy_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_folders_test_iam_permissions_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_folders_test_iam_permissions_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_folders_undelete_folder_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_folders_undelete_folder_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_folders_update_folder_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_folders_update_folder_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_organizations_get_iam_policy_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_organizations_get_iam_policy_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_organizations_get_organization_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_organizations_get_organization_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_organizations_search_organizations_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_organizations_search_organizations_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_organizations_set_iam_policy_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_organizations_set_iam_policy_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_organizations_test_iam_permissions_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_organizations_test_iam_permissions_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_projects_create_project_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_projects_create_project_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_projects_delete_project_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_projects_delete_project_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_projects_get_iam_policy_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_projects_get_iam_policy_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_projects_get_project_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_projects_get_project_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_projects_list_projects_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_projects_list_projects_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_projects_move_project_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_projects_move_project_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_projects_search_projects_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_projects_search_projects_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_projects_set_iam_policy_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_projects_set_iam_policy_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_projects_test_iam_permissions_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_projects_test_iam_permissions_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_projects_undelete_project_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_projects_undelete_project_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_projects_update_project_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_projects_update_project_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_bindings_create_tag_binding_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_bindings_create_tag_binding_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_bindings_delete_tag_binding_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_bindings_delete_tag_binding_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_bindings_list_tag_bindings_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_bindings_list_tag_bindings_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_keys_create_tag_key_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_keys_create_tag_key_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_keys_delete_tag_key_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_keys_delete_tag_key_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_keys_get_iam_policy_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_keys_get_iam_policy_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_keys_get_tag_key_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_keys_get_tag_key_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_keys_list_tag_keys_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_keys_list_tag_keys_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_keys_set_iam_policy_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_keys_set_iam_policy_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_keys_test_iam_permissions_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_keys_test_iam_permissions_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_keys_update_tag_key_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_keys_update_tag_key_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_values_create_tag_value_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_values_create_tag_value_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_values_delete_tag_value_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_values_delete_tag_value_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_values_get_iam_policy_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_values_get_iam_policy_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_values_get_tag_value_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_values_get_tag_value_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_values_list_tag_values_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_values_list_tag_values_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_values_set_iam_policy_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_values_set_iam_policy_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_values_test_iam_permissions_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_values_test_iam_permissions_sync: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_values_update_tag_value_async: google_cloud_resource_manager + samples.generated_samples.cloudresourcemanager_v3_generated_tag_values_update_tag_value_sync: google_cloud_resource_manager + scripts.fixup_resourcemanager_v3_keywords: google_cloud_resource_manager + scripts.readme-gen.readme_gen: google_cloud_resource_manager + six: six + tests: google_cloud_resource_manager + tests.__init__: google_cloud_resource_manager + tests.unit: google_cloud_resource_manager + tests.unit.__init__: google_cloud_resource_manager + tests.unit.gapic: google_cloud_resource_manager + tests.unit.gapic.__init__: google_cloud_resource_manager + tests.unit.gapic.resourcemanager_v3: google_cloud_resource_manager + tests.unit.gapic.resourcemanager_v3.__init__: google_cloud_resource_manager + tests.unit.gapic.resourcemanager_v3.test_folders: google_cloud_resource_manager + tests.unit.gapic.resourcemanager_v3.test_organizations: google_cloud_resource_manager + tests.unit.gapic.resourcemanager_v3.test_projects: google_cloud_resource_manager + tests.unit.gapic.resourcemanager_v3.test_tag_bindings: google_cloud_resource_manager + tests.unit.gapic.resourcemanager_v3.test_tag_keys: google_cloud_resource_manager + tests.unit.gapic.resourcemanager_v3.test_tag_values: google_cloud_resource_manager + urllib3: urllib3 + urllib3.__init__: urllib3 + urllib3._collections: urllib3 + urllib3._version: urllib3 + urllib3.connection: urllib3 + urllib3.connectionpool: urllib3 + urllib3.contrib: urllib3 + urllib3.contrib.__init__: urllib3 + urllib3.contrib._appengine_environ: urllib3 + urllib3.contrib._securetransport: urllib3 + urllib3.contrib._securetransport.__init__: urllib3 + urllib3.contrib._securetransport.bindings: urllib3 + urllib3.contrib._securetransport.low_level: urllib3 + urllib3.contrib.appengine: urllib3 + urllib3.contrib.ntlmpool: urllib3 + urllib3.contrib.pyopenssl: urllib3 + urllib3.contrib.securetransport: urllib3 + urllib3.contrib.socks: urllib3 + urllib3.exceptions: urllib3 + urllib3.fields: urllib3 + urllib3.filepost: urllib3 + urllib3.packages: urllib3 + urllib3.packages.__init__: urllib3 + urllib3.packages.backports: urllib3 + urllib3.packages.backports.__init__: urllib3 + urllib3.packages.backports.makefile: urllib3 + urllib3.packages.six: urllib3 + urllib3.poolmanager: urllib3 + urllib3.request: urllib3 + urllib3.response: urllib3 + urllib3.util: urllib3 + urllib3.util.__init__: urllib3 + urllib3.util.connection: urllib3 + urllib3.util.proxy: urllib3 + urllib3.util.queue: urllib3 + urllib3.util.request: urllib3 + urllib3.util.response: urllib3 + urllib3.util.retry: urllib3 + urllib3.util.ssl_: urllib3 + urllib3.util.ssl_match_hostname: urllib3 + urllib3.util.ssltransport: urllib3 + urllib3.util.timeout: urllib3 + urllib3.util.url: urllib3 + urllib3.util.wait: urllib3 + pip_repository: + name: gazelle_python_test + incremental: true +integrity: 32e38932043eca090a64ca741758d8e4a5817c2cd7dc821fc927914c32fb3114 diff --git a/gazelle/testdata/with_third_party_requirements_from_imports/test.yaml b/gazelle/testdata/with_third_party_requirements_from_imports/test.yaml new file mode 100644 index 0000000000..ed97d539c0 --- /dev/null +++ b/gazelle/testdata/with_third_party_requirements_from_imports/test.yaml @@ -0,0 +1 @@ +--- From e69c2ae13e22e41c4e6f524430afa430d46d1eb2 Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Wed, 10 Aug 2022 15:30:40 +0100 Subject: [PATCH 012/234] Add a consistent `python` interpreter symlink (#782) When a Python repository is created, there is a difference between Unix/Windows for the path to the python interpreter. This patch adds a symlink from the platform specific path to the interpreter. This means that on either platform the `:python` target will always point to the interpreter. --- python/repositories.bzl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/repositories.bzl b/python/repositories.bzl index 30c284191a..ca54ab717e 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -204,7 +204,7 @@ cc_import( }}), ) -exports_files(["{python_path}"]) +exports_files(["python", "{python_path}"]) py_runtime( name = "py3_runtime", @@ -223,6 +223,7 @@ py_runtime_pair( python_path = python_bin, python_version = python_short_version, ) + rctx.symlink(python_bin, "python") rctx.file(STANDALONE_INTERPRETER_FILENAME, "# File intentionally left blank. Indicates that this is an interpreter repo created by rules_python.") rctx.file("BUILD.bazel", build_content) From e99bd61e611c438828b4b232af19006d9b8aa4ad Mon Sep 17 00:00:00 2001 From: Tetsuo Kiso Date: Wed, 10 Aug 2022 23:57:03 +0900 Subject: [PATCH 013/234] Exclude unused libpython{python_version}.so to reduce the size of zipped Python executables (#772) --- python/repositories.bzl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/python/repositories.bzl b/python/repositories.bzl index ca54ab717e..f897904e70 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -170,6 +170,9 @@ filegroup( allow_empty = True, exclude = [ "**/* *", # Bazel does not support spaces in file names. + # Unused shared libraries. `python` executable and the `:libpython` target + # depend on `libpython{python_version}.so.1.0`. + "lib/libpython{python_version}.so", # static libraries "lib/**/*.a", # tests for the standard libraries. From 73300c0cfc150fca0de95151fca47d0f9b286b99 Mon Sep 17 00:00:00 2001 From: Tetsuo Kiso Date: Thu, 11 Aug 2022 00:12:16 +0900 Subject: [PATCH 014/234] Update Python minor toolchain versions to allow smaller Python binaries (#779) Update Python minor toolchain versions to allow smaller Python toolchains Co-authored-by: Matt Mackay --- python/versions.bzl | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/python/versions.bzl b/python/versions.bzl index 2d05e1638d..b58160463c 100644 --- a/python/versions.bzl +++ b/python/versions.bzl @@ -48,13 +48,13 @@ TOOL_VERSIONS = { "strip_prefix": "python", }, "3.8.13": { - "url": "20220502/cpython-{python_version}+20220502-{platform}-{build}.tar.gz", + "url": "20220802/cpython-{python_version}+20220802-{platform}-{build}.tar.gz", "sha256": { - "aarch64-apple-darwin": "ba604867d8c6e0a1a85b1be789cad4c69af8a1699043f51e8a85998b55979127", + "aarch64-apple-darwin": "ae4131253d890b013171cb5f7b03cadc585ae263719506f7b7e063a7cf6fde76", # no aarch64-unknown-linux-gnu build available for 3.8.13 - "x86_64-apple-darwin": "52e3541f41d165002e19a60e11dcc145e90ffe1fe8a6f94b17d5b72a674674ea", - "x86_64-pc-windows-msvc": "1435b77b4d89f2a99719918fcf917a67cd711cad46f67516bed2462d18fbefb3", - "x86_64-unknown-linux-gnu": "884c6c4605c11685164237bad5f8f2773edcf3abb0637a83efa7912a54f658b3", + "x86_64-apple-darwin": "cd6e7c0a27daf7df00f6882eaba01490dd963f698e99aeee9706877333e0df69", + "x86_64-pc-windows-msvc": "f20643f1b3e263a56287319aea5c3888530c09ad9de3a5629b1a5d207807e6b9", + "x86_64-unknown-linux-gnu": "fb566629ccb5f76ef56d275a3f8017d683f1c20c5beb5d5f38b155ed11e16187", }, "strip_prefix": "python", }, @@ -80,6 +80,17 @@ TOOL_VERSIONS = { }, "strip_prefix": "python", }, + "3.9.13": { + "url": "20220802/cpython-{python_version}+20220802-{platform}-{build}.tar.gz", + "sha256": { + "aarch64-apple-darwin": "d9603edc296a2dcbc59d7ada780fd12527f05c3e0b99f7545112daf11636d6e5", + "aarch64-unknown-linux-gnu": "80415aac1b96255b9211f6a4c300f31e9940c7e07a23d0dec12b53aa52c0d25e", + "x86_64-apple-darwin": "9540a7efb7c8a54a48aff1cb9480e49588d9c0a3f934ad53f5b167338174afa3", + "x86_64-pc-windows-msvc": "b538127025a467c64b3351babca2e4d2ea7bdfb7867d5febb3529c34456cdcd4", + "x86_64-unknown-linux-gnu": "ce1cfca2715e7e646dd618a8cb9baff93000e345ccc979b801fc6ccde7ce97df", + }, + "strip_prefix": "python", + }, "3.10.2": { "url": "20220227/cpython-{python_version}+20220227-{platform}-{build}.tar.gz", "sha256": { @@ -102,13 +113,24 @@ TOOL_VERSIONS = { }, "strip_prefix": "python", }, + "3.10.6": { + "url": "20220802/cpython-{python_version}+20220802-{platform}-{build}.tar.gz", + "sha256": { + "aarch64-apple-darwin": "efaf66acdb9a4eb33d57702607d2e667b1a319d58c167a43c96896b97419b8b7", + "aarch64-unknown-linux-gnu": "81625f5c97f61e2e3d7e9f62c484b1aa5311f21bd6545451714b949a29da5435", + "x86_64-apple-darwin": "7718411adf3ea1480f3f018a643eb0550282aefe39e5ecb3f363a4a566a9398c", + "x86_64-pc-windows-msvc": "91889a7dbdceea585ff4d3b7856a6bb8f8a4eca83a0ff52a73542c2e67220eaa", + "x86_64-unknown-linux-gnu": "55aa2190d28dcfdf414d96dc5dcea9fe048fadcd583dc3981fec020869826111", + }, + "strip_prefix": "python", + }, } # buildifier: disable=unsorted-dict-items MINOR_MAPPING = { "3.8": "3.8.13", - "3.9": "3.9.12", - "3.10": "3.10.4", + "3.9": "3.9.13", + "3.10": "3.10.6", } PLATFORMS = { From d484807d171c9020e510e62acfa555ce0edce55f Mon Sep 17 00:00:00 2001 From: Asaf Flescher Date: Wed, 10 Aug 2022 11:35:59 -0400 Subject: [PATCH 015/234] Added importlib + reqs to pip-compile for python < 3.8 (#781) --- python/pip_install/repositories.bzl | 15 +++++++++++++++ python/pip_install/requirements.bzl | 3 +++ 2 files changed, 18 insertions(+) diff --git a/python/pip_install/repositories.bzl b/python/pip_install/repositories.bzl index 5b834d6ca3..7c70104977 100644 --- a/python/pip_install/repositories.bzl +++ b/python/pip_install/repositories.bzl @@ -67,6 +67,21 @@ _RULE_DEPS = [ "https://files.pythonhosted.org/packages/27/d6/003e593296a85fd6ed616ed962795b2f87709c3eee2bca4f6d0fe55c6d00/wheel-0.37.1-py2.py3-none-any.whl", "4bdcd7d840138086126cd09254dc6195fb4fc6f01c050a1d7236f2630db1d22a", ), + ( + "pypi__importlib_metadata", + "https://files.pythonhosted.org/packages/d7/31/74dcb59a601b95fce3b0334e8fc9db758f78e43075f22aeb3677dfb19f4c/importlib_metadata-1.4.0-py2.py3-none-any.whl", + "bdd9b7c397c273bcc9a11d6629a38487cd07154fa255a467bf704cd2c258e359", + ), + ( + "pypi__zipp", + "https://files.pythonhosted.org/packages/f4/50/cc72c5bcd48f6e98219fc4a88a5227e9e28b81637a99c49feba1d51f4d50/zipp-1.0.0-py2.py3-none-any.whl", + "8dda78f06bd1674bd8720df8a50bb47b6e1233c503a4eed8e7810686bde37656", + ), + ( + "pypi__more_itertools", + "https://files.pythonhosted.org/packages/bd/3f/c4b3dbd315e248f84c388bd4a72b131a29f123ecacc37ffb2b3834546e42/more_itertools-8.13.0-py3-none-any.whl", + "c5122bffc5f104d37c1626b8615b511f3427aa5389b94d61e5ef8236bfbc3ddb", + ), ] _GENERIC_WHEEL = """\ diff --git a/python/pip_install/requirements.bzl b/python/pip_install/requirements.bzl index afb94113bf..cca9213e1b 100644 --- a/python/pip_install/requirements.bzl +++ b/python/pip_install/requirements.bzl @@ -76,6 +76,9 @@ def compile_pip_requirements( requirement("pip_tools"), requirement("setuptools"), requirement("tomli"), + requirement("importlib_metadata"), + requirement("zipp"), + requirement("more_itertools"), ] attrs = { From 0609001c95a56074b1c00bd3e5b7cc7a59256f1d Mon Sep 17 00:00:00 2001 From: Matt Mackay Date: Wed, 10 Aug 2022 19:25:26 -0400 Subject: [PATCH 016/234] feat(gazelle_python_manifest): provide a target with the given name (#787) --- gazelle/manifest/defs.bzl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gazelle/manifest/defs.bzl b/gazelle/manifest/defs.bzl index a675e25465..bbcda72fc1 100644 --- a/gazelle/manifest/defs.bzl +++ b/gazelle/manifest/defs.bzl @@ -89,3 +89,10 @@ def gazelle_python_manifest( }, visibility = ["//visibility:private"], ) + + native.filegroup( + name = name, + srcs = [manifest], + tags = ["manual"], + visibility = ["//visibility:public"], + ) From c9b70d1d14a18e19607c7610127ffacb43855dba Mon Sep 17 00:00:00 2001 From: Matt Mackay Date: Wed, 10 Aug 2022 19:37:39 -0400 Subject: [PATCH 017/234] fix(gazelle): handle purelib and platlib packages that don't set 'Root-Is-Purelib: true' (#768) Co-authored-by: Alex Eagle --- gazelle/modules_mapping/generator.py | 61 ++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/gazelle/modules_mapping/generator.py b/gazelle/modules_mapping/generator.py index b93f9689ec..8523542aa2 100644 --- a/gazelle/modules_mapping/generator.py +++ b/gazelle/modules_mapping/generator.py @@ -17,26 +17,15 @@ def __init__(self, stderr, output_file): # by looking at the directory structure. def dig_wheel(self, whl): mapping = {} - wheel_name = get_wheel_name(whl) with zipfile.ZipFile(whl, "r") as zip_file: for path in zip_file.namelist(): if is_metadata(path): - continue - ext = pathlib.Path(path).suffix - if ext == ".py" or ext == ".so": - # Note the '/' here means that the __init__.py is not in the - # root of the wheel, therefore we can index the directory - # where this file is as an importable package. - if path.endswith("/__init__.py"): - module = path[: -len("/__init__.py")].replace("/", ".") - mapping[module] = wheel_name - # Always index the module file. - if ext == ".so": - # Also remove extra metadata that is embeded as part of - # the file name as an extra extension. - ext = "".join(pathlib.Path(path).suffixes) - module = path[: -len(ext)].replace("/", ".") - mapping[module] = wheel_name + if data_has_purelib_or_platlib(path): + module_for_path(path, whl, mapping) + else: + continue + else: + module_for_path(path, whl, mapping) return mapping # run is the entrypoint for the generator. @@ -73,6 +62,44 @@ def is_metadata(path): return top_level.endswith(".dist-info") or top_level.endswith(".data") +# The .data is allowed to contain a full purelib or platlib directory +# These get unpacked into site-packages, so require indexing too. +# This is the same if "Root-Is-Purelib: true" is set and the files are at the root. +# Ref: https://peps.python.org/pep-0427/#what-s-the-deal-with-purelib-vs-platlib +def data_has_purelib_or_platlib(path): + maybe_lib = path.split("/")[1].lower() + return is_metadata(path) and ( + maybe_lib == "purelib" or maybe_lib == "platlib" + ) + + + +def module_for_path(path, whl, mapping): + ext = pathlib.Path(path).suffix + if ext == ".py" or ext == ".so": + if "purelib" in path or "platlib" in path: + root = "/".join(path.split("/")[2:]) + else: + root = path + + wheel_name = get_wheel_name(whl) + + if root.endswith("/__init__.py"): + # Note the '/' here means that the __init__.py is not in the + # root of the wheel, therefore we can index the directory + # where this file is as an importable package. + module = root[: -len("/__init__.py")].replace("/", ".") + mapping[module] = wheel_name + + # Always index the module file. + if ext == ".so": + # Also remove extra metadata that is embeded as part of + # the file name as an extra extension. + ext = ''.join(pathlib.Path(root).suffixes) + module = root[: -len(ext)].replace("/", ".") + mapping[module] = wheel_name + + if __name__ == "__main__": output_file = sys.argv[1] wheels = sys.argv[2:] From d7ae3111bbf4d8e5db1fa1a4e329babd5a50a388 Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Sun, 14 Aug 2022 01:52:51 -0700 Subject: [PATCH 018/234] Ran black and isort to fix files missed by commit hook (#790) --- examples/build_file_generation/__init__.py | 1 + examples/build_file_generation/__main__.py | 1 - examples/pip_install/main.py | 1 + examples/pip_install/pip_install_test.py | 2 +- examples/pip_parse/pip_parse_test.py | 2 +- .../pip_repository_annotations_test.py | 8 +++--- gazelle/modules_mapping/generator.py | 7 ++---- gazelle/parse.py | 16 ++++++------ .../__main__.py | 3 +-- .../bar.py | 1 + python/pip_install/extract_wheels/bazel.py | 6 +---- .../extract_wheels/extract_single_wheel.py | 4 ++- .../parse_requirements_to_bzl.py | 25 +++++++++++-------- python/pip_install/extract_wheels/wheel.py | 4 +-- python/pip_install/pip_compile.py | 10 ++++++-- tools/wheelmaker.py | 2 +- 16 files changed, 49 insertions(+), 44 deletions(-) diff --git a/examples/build_file_generation/__init__.py b/examples/build_file_generation/__init__.py index 851fefb528..6dfd77cf05 100644 --- a/examples/build_file_generation/__init__.py +++ b/examples/build_file_generation/__init__.py @@ -1,5 +1,6 @@ import requests + def main(url): r = requests.get(url) print(r.text) diff --git a/examples/build_file_generation/__main__.py b/examples/build_file_generation/__main__.py index 8b6189cbbc..106c8365eb 100644 --- a/examples/build_file_generation/__main__.py +++ b/examples/build_file_generation/__main__.py @@ -1,5 +1,4 @@ from __init__ import main - if __name__ == "__main__": main("https://example.com") diff --git a/examples/pip_install/main.py b/examples/pip_install/main.py index 4440cdeb2e..b65ad0e5ea 100644 --- a/examples/pip_install/main.py +++ b/examples/pip_install/main.py @@ -1,5 +1,6 @@ import boto3 + def the_dir(): return dir(boto3) diff --git a/examples/pip_install/pip_install_test.py b/examples/pip_install/pip_install_test.py index eb4d7d8e95..6092768da6 100644 --- a/examples/pip_install/pip_install_test.py +++ b/examples/pip_install/pip_install_test.py @@ -52,7 +52,7 @@ def test_dist_info(self): env.split(" "), [ "external/pip/pypi__boto3/site-packages/boto3-1.14.51.dist-info/DESCRIPTION.rst", - 'external/pip/pypi__boto3/site-packages/boto3-1.14.51.dist-info/INSTALLER', + "external/pip/pypi__boto3/site-packages/boto3-1.14.51.dist-info/INSTALLER", "external/pip/pypi__boto3/site-packages/boto3-1.14.51.dist-info/METADATA", "external/pip/pypi__boto3/site-packages/boto3-1.14.51.dist-info/RECORD", "external/pip/pypi__boto3/site-packages/boto3-1.14.51.dist-info/WHEEL", diff --git a/examples/pip_parse/pip_parse_test.py b/examples/pip_parse/pip_parse_test.py index 030e38c077..c623a47567 100644 --- a/examples/pip_parse/pip_parse_test.py +++ b/examples/pip_parse/pip_parse_test.py @@ -49,7 +49,7 @@ def test_dist_info(self): self.assertListEqual( env.split(" "), [ - 'external/pypi_requests/site-packages/requests-2.25.1.dist-info/INSTALLER', + "external/pypi_requests/site-packages/requests-2.25.1.dist-info/INSTALLER", "external/pypi_requests/site-packages/requests-2.25.1.dist-info/LICENSE", "external/pypi_requests/site-packages/requests-2.25.1.dist-info/METADATA", "external/pypi_requests/site-packages/requests-2.25.1.dist-info/RECORD", diff --git a/examples/pip_repository_annotations/pip_repository_annotations_test.py b/examples/pip_repository_annotations/pip_repository_annotations_test.py index 468788f50b..e78880ae72 100644 --- a/examples/pip_repository_annotations/pip_repository_annotations_test.py +++ b/examples/pip_repository_annotations/pip_repository_annotations_test.py @@ -68,11 +68,9 @@ def test_data_exclude_glob(self): current_wheel_version = "0.37.1" r = runfiles.Create() - dist_info_dir = ( - "pip_repository_annotations_example/external/{}/site-packages/wheel-{}.dist-info".format( - self.wheel_pkg_dir(), - current_wheel_version, - ) + dist_info_dir = "pip_repository_annotations_example/external/{}/site-packages/wheel-{}.dist-info".format( + self.wheel_pkg_dir(), + current_wheel_version, ) # Note: `METADATA` is important as it's consumed by https://docs.python.org/3/library/importlib.metadata.html diff --git a/gazelle/modules_mapping/generator.py b/gazelle/modules_mapping/generator.py index 8523542aa2..ec3133af0e 100644 --- a/gazelle/modules_mapping/generator.py +++ b/gazelle/modules_mapping/generator.py @@ -68,10 +68,7 @@ def is_metadata(path): # Ref: https://peps.python.org/pep-0427/#what-s-the-deal-with-purelib-vs-platlib def data_has_purelib_or_platlib(path): maybe_lib = path.split("/")[1].lower() - return is_metadata(path) and ( - maybe_lib == "purelib" or maybe_lib == "platlib" - ) - + return is_metadata(path) and (maybe_lib == "purelib" or maybe_lib == "platlib") def module_for_path(path, whl, mapping): @@ -95,7 +92,7 @@ def module_for_path(path, whl, mapping): if ext == ".so": # Also remove extra metadata that is embeded as part of # the file name as an extra extension. - ext = ''.join(pathlib.Path(root).suffixes) + ext = "".join(pathlib.Path(root).suffixes) module = root[: -len(ext)].replace("/", ".") mapping[module] = wheel_name diff --git a/gazelle/parse.py b/gazelle/parse.py index 6b07c0e8f5..b892229386 100644 --- a/gazelle/parse.py +++ b/gazelle/parse.py @@ -21,7 +21,7 @@ def parse_import_statements(content, filepath): "name": subnode.name, "lineno": node.lineno, "filepath": filepath, - "from": "" + "from": "", } modules.append(module) elif isinstance(node, ast.ImportFrom) and node.level == 0: @@ -30,7 +30,7 @@ def parse_import_statements(content, filepath): "name": f"{node.module}.{subnode.name}", "lineno": node.lineno, "filepath": filepath, - "from": node.module + "from": node.module, } modules.append(module) return modules @@ -52,8 +52,9 @@ def parse(repo_root, rel_package_path, filename): content = file.read() # From simple benchmarks, 2 workers gave the best performance here. with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor: - modules_future = executor.submit(parse_import_statements, content, - rel_filepath) + modules_future = executor.submit( + parse_import_statements, content, rel_filepath + ) comments_future = executor.submit(parse_comments, content) modules = modules_future.result() comments = comments_future.result() @@ -73,12 +74,11 @@ def main(stdin, stdout): filenames = parse_request["filenames"] outputs = list() if len(filenames) == 1: - outputs.append(parse(repo_root, rel_package_path, - filenames[0])) + outputs.append(parse(repo_root, rel_package_path, filenames[0])) else: futures = [ - executor.submit(parse, repo_root, rel_package_path, - filename) for filename in filenames + executor.submit(parse, repo_root, rel_package_path, filename) + for filename in filenames if filename != "" ] for future in concurrent.futures.as_completed(futures): diff --git a/gazelle/testdata/with_third_party_requirements_from_imports/__main__.py b/gazelle/testdata/with_third_party_requirements_from_imports/__main__.py index 8733018885..9f529cb0df 100644 --- a/gazelle/testdata/with_third_party_requirements_from_imports/__main__.py +++ b/gazelle/testdata/with_third_party_requirements_from_imports/__main__.py @@ -1,6 +1,5 @@ -from google.cloud import aiplatform - from bar import main +from google.cloud import aiplatform if __name__ == "__main__": print(aiplatform) diff --git a/gazelle/testdata/with_third_party_requirements_from_imports/bar.py b/gazelle/testdata/with_third_party_requirements_from_imports/bar.py index 7875c1630b..99a4b1ce95 100644 --- a/gazelle/testdata/with_third_party_requirements_from_imports/bar.py +++ b/gazelle/testdata/with_third_party_requirements_from_imports/bar.py @@ -1,5 +1,6 @@ from google.cloud import aiplatform, storage + def main(): a = dir(aiplatform) b = dir(storage) diff --git a/python/pip_install/extract_wheels/bazel.py b/python/pip_install/extract_wheels/bazel.py index d7aa706433..013e4a23e1 100644 --- a/python/pip_install/extract_wheels/bazel.py +++ b/python/pip_install/extract_wheels/bazel.py @@ -6,11 +6,7 @@ from pathlib import Path from typing import Dict, Iterable, List, Optional, Set -from python.pip_install.extract_wheels import ( - annotation, - namespace_pkgs, - wheel, -) +from python.pip_install.extract_wheels import annotation, namespace_pkgs, wheel WHEEL_FILE_LABEL = "whl" PY_LIBRARY_LABEL = "pkg" diff --git a/python/pip_install/extract_wheels/extract_single_wheel.py b/python/pip_install/extract_wheels/extract_single_wheel.py index c69fbd5958..27f29ac838 100644 --- a/python/pip_install/extract_wheels/extract_single_wheel.py +++ b/python/pip_install/extract_wheels/extract_single_wheel.py @@ -6,9 +6,11 @@ import sys from tempfile import NamedTemporaryFile -from python.pip_install.extract_wheels.extract_wheels import configure_reproducible_wheels from python.pip_install.extract_wheels import arguments, bazel, requirements from python.pip_install.extract_wheels.annotation import annotation_from_str_path +from python.pip_install.extract_wheels.extract_wheels import ( + configure_reproducible_wheels, +) def main() -> None: diff --git a/python/pip_install/extract_wheels/parse_requirements_to_bzl.py b/python/pip_install/extract_wheels/parse_requirements_to_bzl.py index e2efa5ae1c..5762cf542c 100644 --- a/python/pip_install/extract_wheels/parse_requirements_to_bzl.py +++ b/python/pip_install/extract_wheels/parse_requirements_to_bzl.py @@ -40,25 +40,25 @@ def parse_install_requirements( if ( # PEP-440 direct references are considered pinned # See: https://peps.python.org/pep-0440/#direct-references and https://peps.python.org/pep-0508/ - not install_req.link and - not install_req.is_pinned + not install_req.link + and not install_req.is_pinned ): unpinned_reqs.append(str(install_req)) - install_req_and_lines.append( - (install_req, line) - ) + install_req_and_lines.append((install_req, line)) else: extra_pip_args.extend(shlex.split(line)) if len(unpinned_reqs) > 0: unpinned_reqs_str = "\n".join(unpinned_reqs) - raise RuntimeError(f"""\ + raise RuntimeError( + f"""\ The `requirements_lock` file must be fully pinned. See `compile_pip_requirements`. Alternatively, use `pip-tools` or a similar mechanism to produce a pinned lockfile. The following requirements were not pinned: -{unpinned_reqs_str}""") +{unpinned_reqs_str}""" + ) return install_req_and_lines @@ -259,14 +259,19 @@ def main(output: TextIO) -> None: } ) - output.write(textwrap.dedent( - """\ + output.write( + textwrap.dedent( + """\ \"\"\"Starlark representation of locked requirements. @generated by rules_python pip_parse repository rule from {} \"\"\" - """.format(args.requirements_lock_label))) + """.format( + args.requirements_lock_label + ) + ) + ) output.write( generate_parsed_requirements_contents( requirements_lock=args.requirements_lock, diff --git a/python/pip_install/extract_wheels/wheel.py b/python/pip_install/extract_wheels/wheel.py index 3f101005d0..024d6e5fa2 100644 --- a/python/pip_install/extract_wheels/wheel.py +++ b/python/pip_install/extract_wheels/wheel.py @@ -20,7 +20,7 @@ def path(self) -> str: @property def name(self) -> str: # TODO Also available as installer.sources.WheelSource.distribution - name = str(self.metadata['Name']) + name = str(self.metadata["Name"]) return canonicalize_name(name) @property @@ -59,7 +59,7 @@ def entry_points(self) -> Dict[str, Tuple[str, str]]: def dependencies(self, extras_requested: Optional[Set[str]] = None) -> Set[str]: dependency_set = set() - for wheel_req in self.metadata.get_all('Requires-Dist', []): + for wheel_req in self.metadata.get_all("Requires-Dist", []): req = pkg_resources.Requirement(wheel_req) # type: ignore if req.marker is None or any( diff --git a/python/pip_install/pip_compile.py b/python/pip_install/pip_compile.py index aeb36de049..09b3c9b035 100644 --- a/python/pip_install/pip_compile.py +++ b/python/pip_install/pip_compile.py @@ -43,7 +43,11 @@ def _select_golden_requirements_file( parts = requirements_in.split(os.path.sep, 2) if parts[0] == "external": requirements_in = parts[2] - requirements_txt = requirements_txt if "BUILD_WORKSPACE_DIRECTORY" in os.environ else os.path.join("..", "..", requirements_txt) + requirements_txt = ( + requirements_txt + if "BUILD_WORKSPACE_DIRECTORY" in os.environ + else os.path.join("..", "..", requirements_txt) + ) os.chdir(os.path.join(parts[0], parts[1])) update_target_label = sys.argv.pop(1) @@ -79,7 +83,9 @@ def _select_golden_requirements_file( # # Changing to the WORKSPACE root avoids 'file not found' errors when the `.update` target is run # from different directories within the WORKSPACE. - requirements_txt = os.path.join(os.environ["BUILD_WORKSPACE_DIRECTORY"], requirements_txt) + requirements_txt = os.path.join( + os.environ["BUILD_WORKSPACE_DIRECTORY"], requirements_txt + ) else: err_msg = ( "Expected to find BUILD_WORKSPACE_DIRECTORY (running under `bazel run`) or " diff --git a/tools/wheelmaker.py b/tools/wheelmaker.py index 0bd585f3bb..b5ad346d70 100644 --- a/tools/wheelmaker.py +++ b/tools/wheelmaker.py @@ -146,7 +146,7 @@ def arcname_from(name): size = 0 with open(real_filename, "rb") as f: while True: - block = f.read(2 ** 20) + block = f.read(2**20) if not block: break hash.update(block) From 599ddb8954a94987284e56fa0cc85e45584f1eb5 Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Sun, 14 Aug 2022 02:01:13 -0700 Subject: [PATCH 019/234] Fix leading forward slashes in RECORD files produced by `py_wheel`. (#789) --- examples/wheel/wheel_test.py | 24 ++++++++++++++++++++++++ tools/wheelmaker.py | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/examples/wheel/wheel_test.py b/examples/wheel/wheel_test.py index f326af20c6..8200e54cfd 100644 --- a/examples/wheel/wheel_test.py +++ b/examples/wheel/wheel_test.py @@ -238,6 +238,14 @@ def test_custom_package_root_wheel(self): ], ) + record_contents = zf.read( + "examples_custom_package_root-0.0.1.dist-info/RECORD" + ).decode("utf-8") + + # Ensure RECORD files do not have leading forward slashes + for line in record_contents.splitlines(): + self.assertFalse(line.startswith("/")) + def test_custom_package_root_multi_prefix_wheel(self): filename = os.path.join( os.environ["TEST_SRCDIR"], @@ -261,6 +269,14 @@ def test_custom_package_root_multi_prefix_wheel(self): ], ) + record_contents = zf.read( + "example_custom_package_root_multi_prefix-0.0.1.dist-info/RECORD" + ).decode("utf-8") + + # Ensure RECORD files do not have leading forward slashes + for line in record_contents.splitlines(): + self.assertFalse(line.startswith("/")) + def test_custom_package_root_multi_prefix_reverse_order_wheel(self): filename = os.path.join( os.environ["TEST_SRCDIR"], @@ -284,6 +300,14 @@ def test_custom_package_root_multi_prefix_reverse_order_wheel(self): ], ) + record_contents = zf.read( + "example_custom_package_root_multi_prefix_reverse_order-0.0.1.dist-info/RECORD" + ).decode("utf-8") + + # Ensure RECORD files do not have leading forward slashes + for line in record_contents.splitlines(): + self.assertFalse(line.startswith("/")) + def test_python_requires_wheel(self): filename = os.path.join( os.environ["TEST_SRCDIR"], diff --git a/tools/wheelmaker.py b/tools/wheelmaker.py index b5ad346d70..fb8e37b5a9 100644 --- a/tools/wheelmaker.py +++ b/tools/wheelmaker.py @@ -214,7 +214,7 @@ def add_recordfile(self): contents = b"" for filename, digest, size in entries: if sys.version_info[0] > 2 and isinstance(filename, str): - filename = filename.encode("utf-8", "surrogateescape") + filename = filename.lstrip("/").encode("utf-8", "surrogateescape") contents += b"%s,%s,%s\n" % (filename, digest, size) self.add_string(record_path, contents) From a2b7f4288fc7ad4ed387aa20cb2d09bf497a1b10 Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Sun, 14 Aug 2022 05:52:03 -0400 Subject: [PATCH 020/234] Add type annotations to runfiles library (#764) --- python/runfiles/runfiles.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/python/runfiles/runfiles.py b/python/runfiles/runfiles.py index f11613d321..4449c711ad 100644 --- a/python/runfiles/runfiles.py +++ b/python/runfiles/runfiles.py @@ -68,16 +68,23 @@ import os import posixpath +if False: + # Mypy needs these symbols imported, but since they only exist in python 3.5+, + # this import may fail at runtime. Luckily mypy can follow this conditional import. + from typing import Callable, Dict, Optional, Tuple, Union def CreateManifestBased(manifest_path): + # type: (str) -> _Runfiles return _Runfiles(_ManifestBased(manifest_path)) def CreateDirectoryBased(runfiles_dir_path): + # type: (str) -> _Runfiles return _Runfiles(_DirectoryBased(runfiles_dir_path)) def Create(env=None): + # type: (Optional[Dict[str, str]]) -> Optional[_Runfiles] """Returns a new `Runfiles` instance. The returned object is either: @@ -120,9 +127,11 @@ class _Runfiles(object): """ def __init__(self, strategy): + # type: (Union[_ManifestBased, _DirectoryBased]) -> None self._strategy = strategy def Rlocation(self, path): + # type: (str) -> Optional[str] """Returns the runtime path of a runfile. Runfiles are data-dependencies of Bazel-built binaries and tests. @@ -162,6 +171,7 @@ def Rlocation(self, path): return self._strategy.RlocationChecked(path) def EnvVars(self): + # type: () -> Dict[str, str] """Returns environment variables for subprocesses. The caller should set the returned key-value pairs in the environment of @@ -179,6 +189,7 @@ class _ManifestBased(object): """`Runfiles` strategy that parses a runfiles-manifest to look up runfiles.""" def __init__(self, path): + # type: (str) -> None if not path: raise ValueError() if not isinstance(path, str): @@ -187,10 +198,12 @@ def __init__(self, path): self._runfiles = _ManifestBased._LoadRunfiles(path) def RlocationChecked(self, path): + # type: (str) -> Optional[str] return self._runfiles.get(path) @staticmethod def _LoadRunfiles(path): + # type: (str) -> Dict[str, str] """Loads the runfiles manifest.""" result = {} with open(path, "r") as f: @@ -205,6 +218,7 @@ def _LoadRunfiles(path): return result def _GetRunfilesDir(self): + # type: () -> str if self._path.endswith("/MANIFEST") or self._path.endswith("\\MANIFEST"): return self._path[: -len("/MANIFEST")] elif self._path.endswith(".runfiles_manifest"): @@ -213,6 +227,7 @@ def _GetRunfilesDir(self): return "" def EnvVars(self): + # type: () -> Dict[str, str] directory = self._GetRunfilesDir() return { "RUNFILES_MANIFEST_FILE": self._path, @@ -227,6 +242,7 @@ class _DirectoryBased(object): """`Runfiles` strategy that appends runfiles paths to the runfiles root.""" def __init__(self, path): + # type: (str) -> None if not path: raise ValueError() if not isinstance(path, str): @@ -234,12 +250,15 @@ def __init__(self, path): self._runfiles_root = path def RlocationChecked(self, path): + # type: (str) -> str + # Use posixpath instead of os.path, because Bazel only creates a runfiles # tree on Unix platforms, so `Create()` will only create a directory-based # runfiles strategy on those platforms. return posixpath.join(self._runfiles_root, path) def EnvVars(self): + # type: () -> Dict[str, str] return { "RUNFILES_DIR": self._runfiles_root, # TODO(laszlocsomor): remove JAVA_RUNFILES once the Java launcher can @@ -251,6 +270,7 @@ def EnvVars(self): def _PathsFrom( argv0, runfiles_mf, runfiles_dir, is_runfiles_manifest, is_runfiles_directory ): + # type: (str, str, str, Callable[[str], bool], Callable[[str], bool]) -> Tuple[str, str] """Discover runfiles manifest and runfiles directory paths. Args: From e0a78297164ad8eacabc965111ff19d4e4144786 Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Mon, 15 Aug 2022 18:41:12 -0700 Subject: [PATCH 021/234] Added label to py_wheel progress message. (#791) --- python/packaging.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/packaging.bzl b/python/packaging.bzl index 9ad2daf647..19b5894e2a 100644 --- a/python/packaging.bzl +++ b/python/packaging.bzl @@ -226,7 +226,7 @@ def _py_wheel_impl(ctx): outputs = [outfile, name_file], arguments = [args], executable = ctx.executable._wheelmaker, - progress_message = "Building wheel", + progress_message = "Building wheel {}".format(ctx.label), ) return [ DefaultInfo( From 6a43ebd6e4d8a11aaa5c303e7b03c72a136f62a0 Mon Sep 17 00:00:00 2001 From: Jesse Schalken Date: Sat, 27 Aug 2022 20:06:54 +1000 Subject: [PATCH 022/234] Add option to use "pip download" instead of "pip wheel" to download wheels for other platforms (#773) --- docs/pip_repository.md | 16 +++++++++------- examples/pip_parse_vendored/requirements.bzl | 2 +- python/pip_install/extract_wheels/arguments.py | 6 ++++++ .../extract_wheels/extract_single_wheel.py | 2 +- .../pip_install/extract_wheels/extract_wheels.py | 2 +- python/pip_install/pip_repository.bzl | 10 ++++++++++ 6 files changed, 28 insertions(+), 10 deletions(-) diff --git a/docs/pip_repository.md b/docs/pip_repository.md index ef7f72bcd2..c66d8bfd91 100644 --- a/docs/pip_repository.md +++ b/docs/pip_repository.md @@ -5,10 +5,10 @@ ## pip_repository
-pip_repository(name, annotations, enable_implicit_namespace_pkgs, environment, extra_pip_args,
-               incremental, isolated, pip_data_exclude, python_interpreter, python_interpreter_target,
-               quiet, repo_prefix, requirements, requirements_darwin, requirements_linux,
-               requirements_lock, requirements_windows, timeout)
+pip_repository(name, annotations, download_only, enable_implicit_namespace_pkgs, environment,
+               extra_pip_args, incremental, isolated, pip_data_exclude, python_interpreter,
+               python_interpreter_target, quiet, repo_prefix, requirements, requirements_darwin,
+               requirements_linux, requirements_lock, requirements_windows, timeout)
 
A rule for importing `requirements.txt` dependencies into Bazel. @@ -58,6 +58,7 @@ py_binary( | :-------------: | :-------------: | :-------------: | :-------------: | :-------------: | | name | A unique name for this repository. | Name | required | | | annotations | Optional annotations to apply to packages | Dictionary: String -> String | optional | {} | +| download_only | Whether to use "pip download" instead of "pip wheel". Disables building wheels from source, but allows use of --platform, --python-version, --implementation, and --abi in --extra_pip_args to download wheels for a different platform from the host platform. | Boolean | optional | False | | enable_implicit_namespace_pkgs | If true, disables conversion of native namespace packages into pkg-util style namespace packages. When set all py_binary and py_test targets must specify either legacy_create_init=False or the global Bazel option --incompatible_default_to_explicit_init_py to prevent __init__.py being automatically generated in every directory.

This option is required to support some packages which cannot handle the conversion to pkg-util style. | Boolean | optional | False | | environment | Environment variables to set in the pip subprocess. Can be used to set common variables such as http_proxy, https_proxy and no_proxy Note that pip is run with "--isolated" on the CLI so PIP_<VAR>_<NAME> style env vars are ignored, but env vars that control requests and urllib3 can be passed. | Dictionary: String -> String | optional | {} | | extra_pip_args | Extra arguments to pass on to pip. Must not contain spaces. | List of strings | optional | [] | @@ -81,9 +82,9 @@ py_binary( ## whl_library
-whl_library(name, annotation, enable_implicit_namespace_pkgs, environment, extra_pip_args, isolated,
-            pip_data_exclude, python_interpreter, python_interpreter_target, quiet, repo, repo_prefix,
-            requirement, timeout)
+whl_library(name, annotation, download_only, enable_implicit_namespace_pkgs, environment,
+            extra_pip_args, isolated, pip_data_exclude, python_interpreter, python_interpreter_target,
+            quiet, repo, repo_prefix, requirement, timeout)
 
@@ -97,6 +98,7 @@ Instantiated from pip_repository and inherits config options from there. | :-------------: | :-------------: | :-------------: | :-------------: | :-------------: | | name | A unique name for this repository. | Name | required | | | annotation | Optional json encoded file containing annotation to apply to the extracted wheel. See package_annotation | Label | optional | None | +| download_only | Whether to use "pip download" instead of "pip wheel". Disables building wheels from source, but allows use of --platform, --python-version, --implementation, and --abi in --extra_pip_args to download wheels for a different platform from the host platform. | Boolean | optional | False | | enable_implicit_namespace_pkgs | If true, disables conversion of native namespace packages into pkg-util style namespace packages. When set all py_binary and py_test targets must specify either legacy_create_init=False or the global Bazel option --incompatible_default_to_explicit_init_py to prevent __init__.py being automatically generated in every directory.

This option is required to support some packages which cannot handle the conversion to pkg-util style. | Boolean | optional | False | | environment | Environment variables to set in the pip subprocess. Can be used to set common variables such as http_proxy, https_proxy and no_proxy Note that pip is run with "--isolated" on the CLI so PIP_<VAR>_<NAME> style env vars are ignored, but env vars that control requests and urllib3 can be passed. | Dictionary: String -> String | optional | {} | | extra_pip_args | Extra arguments to pass on to pip. Must not contain spaces. | List of strings | optional | [] | diff --git a/examples/pip_parse_vendored/requirements.bzl b/examples/pip_parse_vendored/requirements.bzl index 038b612309..58c6e7bad1 100644 --- a/examples/pip_parse_vendored/requirements.bzl +++ b/examples/pip_parse_vendored/requirements.bzl @@ -12,7 +12,7 @@ all_requirements = ["@pip_certifi//:pkg", "@pip_charset_normalizer//:pkg", "@pip all_whl_requirements = ["@pip_certifi//:whl", "@pip_charset_normalizer//:whl", "@pip_idna//:whl", "@pip_requests//:whl", "@pip_urllib3//:whl"] _packages = [("pip_certifi", "certifi==2021.10.8 --hash=sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872 --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"), ("pip_charset_normalizer", "charset-normalizer==2.0.12 --hash=sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597 --hash=sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"), ("pip_idna", "idna==3.3 --hash=sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff --hash=sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"), ("pip_requests", "requests==2.27.1 --hash=sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61 --hash=sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"), ("pip_urllib3", "urllib3==1.26.9 --hash=sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14 --hash=sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e")] -_config = {"enable_implicit_namespace_pkgs": False, "environment": {}, "extra_pip_args": [], "isolated": True, "pip_data_exclude": [], "python_interpreter": "python3", "python_interpreter_target": interpreter, "quiet": True, "repo": "pip", "repo_prefix": "pip_", "timeout": 600} +_config = {"download_only": False, "enable_implicit_namespace_pkgs": False, "environment": {}, "extra_pip_args": [], "isolated": True, "pip_data_exclude": [], "python_interpreter": "python3", "python_interpreter_target": interpreter, "quiet": True, "repo": "pip", "repo_prefix": "pip_", "timeout": 600} _annotations = {} def _clean_name(name): diff --git a/python/pip_install/extract_wheels/arguments.py b/python/pip_install/extract_wheels/arguments.py index d7d34523a7..ce77bb028e 100644 --- a/python/pip_install/extract_wheels/arguments.py +++ b/python/pip_install/extract_wheels/arguments.py @@ -39,6 +39,12 @@ def parse_common_args(parser: ArgumentParser) -> ArgumentParser: required=True, help="Prefix to prepend to packages", ) + parser.add_argument( + "--download_only", + action="store_true", + help="Use 'pip download' instead of 'pip wheel'. Disables building wheels from source, but allows use of " + "--platform, --python-version, --implementation, and --abi in --extra_pip_args.", + ) return parser diff --git a/python/pip_install/extract_wheels/extract_single_wheel.py b/python/pip_install/extract_wheels/extract_single_wheel.py index 27f29ac838..a7cc672a76 100644 --- a/python/pip_install/extract_wheels/extract_single_wheel.py +++ b/python/pip_install/extract_wheels/extract_single_wheel.py @@ -38,7 +38,7 @@ def main() -> None: pip_args = ( [sys.executable, "-m", "pip"] + (["--isolated"] if args.isolated else []) - + ["wheel", "--no-deps"] + + ["download" if args.download_only else "wheel", "--no-deps"] + deserialized_args["extra_pip_args"] ) diff --git a/python/pip_install/extract_wheels/extract_wheels.py b/python/pip_install/extract_wheels/extract_wheels.py index 7e583eb442..2addaf89fd 100644 --- a/python/pip_install/extract_wheels/extract_wheels.py +++ b/python/pip_install/extract_wheels/extract_wheels.py @@ -80,7 +80,7 @@ def main() -> None: pip_args = ( [sys.executable, "-m", "pip"] + (["--isolated"] if args.isolated else []) - + ["wheel", "-r", args.requirements] + + ["download" if args.download_only else "wheel", "-r", args.requirements] + ["--wheel-dir", os.getcwd()] + deserialized_args["extra_pip_args"] ) diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl index 706edef5de..eab59f35cd 100644 --- a/python/pip_install/pip_repository.bzl +++ b/python/pip_install/pip_repository.bzl @@ -130,6 +130,9 @@ def _parse_optional_attrs(rctx, args): struct(arg = rctx.attr.extra_pip_args).to_json(), ] + if rctx.attr.download_only: + args.append("--download_only") + if rctx.attr.pip_data_exclude != None: args += [ "--pip_data_exclude", @@ -250,6 +253,13 @@ common_env = [ ] common_attrs = { + "download_only": attr.bool( + doc = """ +Whether to use "pip download" instead of "pip wheel". Disables building wheels from source, but allows use of +--platform, --python-version, --implementation, and --abi in --extra_pip_args to download wheels for a different +platform from the host platform. + """, + ), "enable_implicit_namespace_pkgs": attr.bool( default = False, doc = """ From 4999f631c2af4483008039032dc7aacdcb82ec90 Mon Sep 17 00:00:00 2001 From: Greg Roodt Date: Sun, 28 Aug 2022 06:14:46 +1000 Subject: [PATCH 023/234] =?UTF-8?q?Revert=20"Add=20option=20to=20use=20"pi?= =?UTF-8?q?p=20download"=20instead=20of=20"pip=20wheel"=20to=20do=E2=80=A6?= =?UTF-8?q?=20(#808)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Revert "Add option to use "pip download" instead of "pip wheel" to download wheels for other platforms (#773)" This reverts commit 6a43ebd6e4d8a11aaa5c303e7b03c72a136f62a0. --- docs/pip_repository.md | 16 +++++++--------- examples/pip_parse_vendored/requirements.bzl | 2 +- python/pip_install/extract_wheels/arguments.py | 6 ------ .../extract_wheels/extract_single_wheel.py | 2 +- .../pip_install/extract_wheels/extract_wheels.py | 2 +- python/pip_install/pip_repository.bzl | 10 ---------- 6 files changed, 10 insertions(+), 28 deletions(-) diff --git a/docs/pip_repository.md b/docs/pip_repository.md index c66d8bfd91..ef7f72bcd2 100644 --- a/docs/pip_repository.md +++ b/docs/pip_repository.md @@ -5,10 +5,10 @@ ## pip_repository
-pip_repository(name, annotations, download_only, enable_implicit_namespace_pkgs, environment,
-               extra_pip_args, incremental, isolated, pip_data_exclude, python_interpreter,
-               python_interpreter_target, quiet, repo_prefix, requirements, requirements_darwin,
-               requirements_linux, requirements_lock, requirements_windows, timeout)
+pip_repository(name, annotations, enable_implicit_namespace_pkgs, environment, extra_pip_args,
+               incremental, isolated, pip_data_exclude, python_interpreter, python_interpreter_target,
+               quiet, repo_prefix, requirements, requirements_darwin, requirements_linux,
+               requirements_lock, requirements_windows, timeout)
 
A rule for importing `requirements.txt` dependencies into Bazel. @@ -58,7 +58,6 @@ py_binary( | :-------------: | :-------------: | :-------------: | :-------------: | :-------------: | | name | A unique name for this repository. | Name | required | | | annotations | Optional annotations to apply to packages | Dictionary: String -> String | optional | {} | -| download_only | Whether to use "pip download" instead of "pip wheel". Disables building wheels from source, but allows use of --platform, --python-version, --implementation, and --abi in --extra_pip_args to download wheels for a different platform from the host platform. | Boolean | optional | False | | enable_implicit_namespace_pkgs | If true, disables conversion of native namespace packages into pkg-util style namespace packages. When set all py_binary and py_test targets must specify either legacy_create_init=False or the global Bazel option --incompatible_default_to_explicit_init_py to prevent __init__.py being automatically generated in every directory.

This option is required to support some packages which cannot handle the conversion to pkg-util style. | Boolean | optional | False | | environment | Environment variables to set in the pip subprocess. Can be used to set common variables such as http_proxy, https_proxy and no_proxy Note that pip is run with "--isolated" on the CLI so PIP_<VAR>_<NAME> style env vars are ignored, but env vars that control requests and urllib3 can be passed. | Dictionary: String -> String | optional | {} | | extra_pip_args | Extra arguments to pass on to pip. Must not contain spaces. | List of strings | optional | [] | @@ -82,9 +81,9 @@ py_binary( ## whl_library
-whl_library(name, annotation, download_only, enable_implicit_namespace_pkgs, environment,
-            extra_pip_args, isolated, pip_data_exclude, python_interpreter, python_interpreter_target,
-            quiet, repo, repo_prefix, requirement, timeout)
+whl_library(name, annotation, enable_implicit_namespace_pkgs, environment, extra_pip_args, isolated,
+            pip_data_exclude, python_interpreter, python_interpreter_target, quiet, repo, repo_prefix,
+            requirement, timeout)
 
@@ -98,7 +97,6 @@ Instantiated from pip_repository and inherits config options from there. | :-------------: | :-------------: | :-------------: | :-------------: | :-------------: | | name | A unique name for this repository. | Name | required | | | annotation | Optional json encoded file containing annotation to apply to the extracted wheel. See package_annotation | Label | optional | None | -| download_only | Whether to use "pip download" instead of "pip wheel". Disables building wheels from source, but allows use of --platform, --python-version, --implementation, and --abi in --extra_pip_args to download wheels for a different platform from the host platform. | Boolean | optional | False | | enable_implicit_namespace_pkgs | If true, disables conversion of native namespace packages into pkg-util style namespace packages. When set all py_binary and py_test targets must specify either legacy_create_init=False or the global Bazel option --incompatible_default_to_explicit_init_py to prevent __init__.py being automatically generated in every directory.

This option is required to support some packages which cannot handle the conversion to pkg-util style. | Boolean | optional | False | | environment | Environment variables to set in the pip subprocess. Can be used to set common variables such as http_proxy, https_proxy and no_proxy Note that pip is run with "--isolated" on the CLI so PIP_<VAR>_<NAME> style env vars are ignored, but env vars that control requests and urllib3 can be passed. | Dictionary: String -> String | optional | {} | | extra_pip_args | Extra arguments to pass on to pip. Must not contain spaces. | List of strings | optional | [] | diff --git a/examples/pip_parse_vendored/requirements.bzl b/examples/pip_parse_vendored/requirements.bzl index 58c6e7bad1..038b612309 100644 --- a/examples/pip_parse_vendored/requirements.bzl +++ b/examples/pip_parse_vendored/requirements.bzl @@ -12,7 +12,7 @@ all_requirements = ["@pip_certifi//:pkg", "@pip_charset_normalizer//:pkg", "@pip all_whl_requirements = ["@pip_certifi//:whl", "@pip_charset_normalizer//:whl", "@pip_idna//:whl", "@pip_requests//:whl", "@pip_urllib3//:whl"] _packages = [("pip_certifi", "certifi==2021.10.8 --hash=sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872 --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"), ("pip_charset_normalizer", "charset-normalizer==2.0.12 --hash=sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597 --hash=sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"), ("pip_idna", "idna==3.3 --hash=sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff --hash=sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"), ("pip_requests", "requests==2.27.1 --hash=sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61 --hash=sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"), ("pip_urllib3", "urllib3==1.26.9 --hash=sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14 --hash=sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e")] -_config = {"download_only": False, "enable_implicit_namespace_pkgs": False, "environment": {}, "extra_pip_args": [], "isolated": True, "pip_data_exclude": [], "python_interpreter": "python3", "python_interpreter_target": interpreter, "quiet": True, "repo": "pip", "repo_prefix": "pip_", "timeout": 600} +_config = {"enable_implicit_namespace_pkgs": False, "environment": {}, "extra_pip_args": [], "isolated": True, "pip_data_exclude": [], "python_interpreter": "python3", "python_interpreter_target": interpreter, "quiet": True, "repo": "pip", "repo_prefix": "pip_", "timeout": 600} _annotations = {} def _clean_name(name): diff --git a/python/pip_install/extract_wheels/arguments.py b/python/pip_install/extract_wheels/arguments.py index ce77bb028e..d7d34523a7 100644 --- a/python/pip_install/extract_wheels/arguments.py +++ b/python/pip_install/extract_wheels/arguments.py @@ -39,12 +39,6 @@ def parse_common_args(parser: ArgumentParser) -> ArgumentParser: required=True, help="Prefix to prepend to packages", ) - parser.add_argument( - "--download_only", - action="store_true", - help="Use 'pip download' instead of 'pip wheel'. Disables building wheels from source, but allows use of " - "--platform, --python-version, --implementation, and --abi in --extra_pip_args.", - ) return parser diff --git a/python/pip_install/extract_wheels/extract_single_wheel.py b/python/pip_install/extract_wheels/extract_single_wheel.py index a7cc672a76..27f29ac838 100644 --- a/python/pip_install/extract_wheels/extract_single_wheel.py +++ b/python/pip_install/extract_wheels/extract_single_wheel.py @@ -38,7 +38,7 @@ def main() -> None: pip_args = ( [sys.executable, "-m", "pip"] + (["--isolated"] if args.isolated else []) - + ["download" if args.download_only else "wheel", "--no-deps"] + + ["wheel", "--no-deps"] + deserialized_args["extra_pip_args"] ) diff --git a/python/pip_install/extract_wheels/extract_wheels.py b/python/pip_install/extract_wheels/extract_wheels.py index 2addaf89fd..7e583eb442 100644 --- a/python/pip_install/extract_wheels/extract_wheels.py +++ b/python/pip_install/extract_wheels/extract_wheels.py @@ -80,7 +80,7 @@ def main() -> None: pip_args = ( [sys.executable, "-m", "pip"] + (["--isolated"] if args.isolated else []) - + ["download" if args.download_only else "wheel", "-r", args.requirements] + + ["wheel", "-r", args.requirements] + ["--wheel-dir", os.getcwd()] + deserialized_args["extra_pip_args"] ) diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl index eab59f35cd..706edef5de 100644 --- a/python/pip_install/pip_repository.bzl +++ b/python/pip_install/pip_repository.bzl @@ -130,9 +130,6 @@ def _parse_optional_attrs(rctx, args): struct(arg = rctx.attr.extra_pip_args).to_json(), ] - if rctx.attr.download_only: - args.append("--download_only") - if rctx.attr.pip_data_exclude != None: args += [ "--pip_data_exclude", @@ -253,13 +250,6 @@ common_env = [ ] common_attrs = { - "download_only": attr.bool( - doc = """ -Whether to use "pip download" instead of "pip wheel". Disables building wheels from source, but allows use of ---platform, --python-version, --implementation, and --abi in --extra_pip_args to download wheels for a different -platform from the host platform. - """, - ), "enable_implicit_namespace_pkgs": attr.bool( default = False, doc = """ From dd2e947c175d5a8de0a6fe809438e1a73a361a20 Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Sat, 27 Aug 2022 13:53:31 -0700 Subject: [PATCH 024/234] Fix missing python includes for Unix hosts (#809) * Fix missing python includes for Unix hosts * Update python/pip_install/pip_repository.bzl Co-authored-by: Greg Roodt --- python/pip_install/pip_repository.bzl | 99 +++++++++++++++++++-------- python/repositories.bzl | 24 +++++++ 2 files changed, 95 insertions(+), 28 deletions(-) diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl index 706edef5de..6395bc5d3f 100644 --- a/python/pip_install/pip_repository.bzl +++ b/python/pip_install/pip_repository.bzl @@ -1,6 +1,6 @@ "" -load("//python:repositories.bzl", "STANDALONE_INTERPRETER_FILENAME") +load("//python:repositories.bzl", "is_standalone_interpreter") load("//python/pip_install:repositories.bzl", "all_requirements") load("//python/pip_install/private:srcs.bzl", "PIP_INSTALL_PY_SRCS") @@ -66,35 +66,68 @@ def _resolve_python_interpreter(rctx): fail("python interpreter `{}` not found in PATH".format(python_interpreter)) return python_interpreter -def _maybe_set_xcode_location_cflags(rctx, environment): - """Patch environment with CPPFLAGS of xcode sdk location. +def _get_xcode_location_cflags(rctx): + """Query the xcode sdk location to update cflags Figure out if this interpreter target comes from rules_python, and patch the xcode sdk location if so. Pip won't be able to compile c extensions from sdists with the pre built python distributions from indygreg otherwise. See https://github.com/indygreg/python-build-standalone/issues/103 """ - if ( - rctx.os.name.lower().startswith("mac os") and - rctx.attr.python_interpreter_target != None and - # This is a rules_python provided toolchain. - rctx.execute([ - "ls", - "{}/{}".format( - rctx.path(Label("@{}//:WORKSPACE".format(rctx.attr.python_interpreter_target.workspace_name))).dirname, - STANDALONE_INTERPRETER_FILENAME, - ), - ]).return_code == 0 and - not environment.get(CPPFLAGS) - ): - xcode_sdk_location = rctx.execute(["xcode-select", "--print-path"]) - if xcode_sdk_location.return_code == 0: - xcode_root = xcode_sdk_location.stdout.strip() - if COMMAND_LINE_TOOLS_PATH_SLUG not in xcode_root.lower(): - # This is a full xcode installation somewhere like /Applications/Xcode13.0.app/Contents/Developer - # so we need to change the path to to the macos specific tools which are in a different relative - # path than xcode installed command line tools. - xcode_root = "{}/Platforms/MacOSX.platform/Developer".format(xcode_root) - environment[CPPFLAGS] = "-isysroot {}/SDKs/MacOSX.sdk".format(xcode_root) + + # Only run on MacOS hosts + if not rctx.os.name.lower().startswith("mac os"): + return [] + + # Only update the location when using a hermetic toolchain. + if not is_standalone_interpreter(rctx, rctx.attr.python_interpreter_target): + return [] + + # Locate xcode-select + xcode_select = rctx.which("xcode-select") + + xcode_sdk_location = rctx.execute([xcode_select, "--print-path"]) + if xcode_sdk_location.return_code != 0: + return [] + + xcode_root = xcode_sdk_location.stdout.strip() + if COMMAND_LINE_TOOLS_PATH_SLUG not in xcode_root.lower(): + # This is a full xcode installation somewhere like /Applications/Xcode13.0.app/Contents/Developer + # so we need to change the path to to the macos specific tools which are in a different relative + # path than xcode installed command line tools. + xcode_root = "{}/Platforms/MacOSX.platform/Developer".format(xcode_root) + return [ + "-isysroot {}/SDKs/MacOSX.sdk".format(xcode_root), + ] + +def _get_toolchain_unix_cflags(rctx): + """Gather cflags from a standalone toolchain for unix systems. + + Pip won't be able to compile c extensions from sdists with the pre built python distributions from indygreg + otherwise. See https://github.com/indygreg/python-build-standalone/issues/103 + """ + + # Only run on Unix systems + if not rctx.os.name.lower().startswith(("mac os", "linux")): + return [] + + # Only update the location when using a standalone toolchain. + if not is_standalone_interpreter(rctx, rctx.attr.python_interpreter_target): + return [] + + er = rctx.execute([ + rctx.path(rctx.attr.python_interpreter_target).realpath, + "-c", + "import sys; print(f'{sys.version_info[0]}.{sys.version_info[1]}')", + ]) + if er.return_code != 0: + fail("could not get python version from interpreter (status {}): {}".format(er.return_code, er.stderr)) + _python_version = er.stdout + include_path = "{}/include/python{}".format( + rctx.path(Label("@{}//:WORKSPACE".format(rctx.attr.python_interpreter_target.workspace_name))).dirname.realpath, + _python_version, + ) + + return ["-isystem {}".format(include_path)] def _parse_optional_attrs(rctx, args): """Helper function to parse common attributes of pip_repository and whl_library repository rules. @@ -152,10 +185,20 @@ def _create_repository_execution_environment(rctx): Args: rctx: The repository context. - Returns: Dictionary of envrionment variable suitable to pass to rctx.execute. + Returns: + Dictionary of environment variable suitable to pass to rctx.execute. """ - env = {"PYTHONPATH": _construct_pypath(rctx)} - _maybe_set_xcode_location_cflags(rctx, env) + + # Gather any available CPPFLAGS values + cppflags = [] + cppflags.extend(_get_xcode_location_cflags(rctx)) + cppflags.extend(_get_toolchain_unix_cflags(rctx)) + + env = { + "PYTHONPATH": _construct_pypath(rctx), + CPPFLAGS: " ".join(cppflags), + } + return env _BUILD_FILE_CONTENTS = """\ diff --git a/python/repositories.bzl b/python/repositories.bzl index f897904e70..d500ce66de 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -37,6 +37,30 @@ def py_repositories(): STANDALONE_INTERPRETER_FILENAME = "STANDALONE_INTERPRETER" +def is_standalone_interpreter(rctx, python_interpreter_target): + """Query a python interpreter target for whether or not it's a rules_rust provided toolchain + + Args: + rctx (repository_ctx): The repository rule's context object. + python_interpreter_target (Target): A target representing a python interpreter. + + Returns: + bool: Whether or not the target is from a rules_python generated toolchain. + """ + + # Only update the location when using a hermetic toolchain. + if not python_interpreter_target: + return False + + # This is a rules_python provided toolchain. + return rctx.execute([ + "ls", + "{}/{}".format( + rctx.path(Label("@{}//:WORKSPACE".format(rctx.attr.python_interpreter_target.workspace_name))).dirname, + STANDALONE_INTERPRETER_FILENAME, + ), + ]).return_code == 0 + def _python_repository_impl(rctx): if rctx.attr.distutils and rctx.attr.distutils_content: fail("Only one of (distutils, distutils_content) should be set.") From 5ff0dc888ab1dfd5d834e9fe12eaa30fefceec52 Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Sat, 27 Aug 2022 14:11:15 -0700 Subject: [PATCH 025/234] Fix ability to download windows toolchains on case sensitive unix systems (#797) --- python/repositories.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/repositories.bzl b/python/repositories.bzl index d500ce66de..dc2c49e722 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -141,7 +141,7 @@ def _python_repository_impl(rctx): exec_result.stderr, ) fail(fail_msg) - exec_result = rctx.execute(["touch", "lib/.test"]) + exec_result = rctx.execute(["touch", "{}/.test".format(lib_dir)]) if exec_result.return_code == 0: exec_result = rctx.execute(["id", "-u"]) if exec_result.return_code != 0: From edfd9f48029fd273628b836c4b438a94e82f651e Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Sat, 27 Aug 2022 15:06:58 -0700 Subject: [PATCH 026/234] =?UTF-8?q?Revert=20"pip=5Fcompile:=20remove=20ext?= =?UTF-8?q?ernal/workspace=5Fname=20prefix=20from=20gener=E2=80=A6=20(#794?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bazelci/presubmit.yml | 1 - examples/pip_install/requirements.txt | 8 +- examples/pip_install/requirements_windows.txt | 6 +- examples/pip_parse/requirements_lock.txt | 6 +- examples/pip_parse_vendored/requirements.txt | 2 +- .../requirements.txt | 2 +- python/pip_install/pip_compile.py | 17 +-- tests/BUILD | 5 - tests/pip_deps/BUILD | 19 --- tests/pip_deps/README.md | 1 - tests/pip_deps/WORKSPACE | 26 ---- tests/pip_deps/pip_deps.bzl | 55 ------- tests/pip_deps/requirements.txt | 136 ------------------ tests/pip_deps/test.sh | 4 - .../requirements.txt | 6 +- 15 files changed, 18 insertions(+), 276 deletions(-) delete mode 100644 tests/pip_deps/BUILD delete mode 100644 tests/pip_deps/README.md delete mode 100644 tests/pip_deps/WORKSPACE delete mode 100644 tests/pip_deps/pip_deps.bzl delete mode 100644 tests/pip_deps/requirements.txt delete mode 100755 tests/pip_deps/test.sh diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 03687d442c..1cc121a4e7 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -36,6 +36,5 @@ platforms: - "-//gazelle/..." # The dependencies needed for this test are not cross-platform: https://github.com/bazelbuild/rules_python/issues/260 - "-//tests:pip_repository_entry_points_example" - - "-//tests:pip_deps_example" test_flags: - "--test_tag_filters=-fix-windows" \ No newline at end of file diff --git a/examples/pip_install/requirements.txt b/examples/pip_install/requirements.txt index db76801f39..8a06da02b6 100644 --- a/examples/pip_install/requirements.txt +++ b/examples/pip_install/requirements.txt @@ -7,7 +7,7 @@ boto3==1.14.51 \ --hash=sha256:a6bdb808e948bd264af135af50efb76253e85732c451fa605b7a287faf022432 \ --hash=sha256:f9dbccbcec916051c6588adbccae86547308ac4cd154f1eb7cf6422f0e391a71 - # via -r requirements.in + # via -r ./requirements.in botocore==1.17.63 \ --hash=sha256:40f13f6c9c29c307a9dc5982739e537ddce55b29787b90c3447b507e3283bcd6 \ --hash=sha256:aa88eafc6295132f4bc606f1df32b3248e0fa611724c0a216aceda767948ac75 @@ -77,7 +77,7 @@ pyyaml==6.0 \ s3cmd==2.1.0 \ --hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \ --hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03 - # via -r requirements.in + # via -r ./requirements.in s3transfer==0.3.7 \ --hash=sha256:35627b86af8ff97e7ac27975fe0a98a312814b46c6333d8a6b889627bcd80994 \ --hash=sha256:efa5bd92a897b6a8d5c1383828dca3d52d0790e0756d49740563a3fb6ed03246 @@ -89,14 +89,14 @@ six==1.16.0 \ tree-sitter==0.20.0 ; sys_platform != "win32" \ --hash=sha256:1940f64be1e8c9c3c0e34a2258f1e4c324207534d5b1eefc5ab2960a9d98f668 \ --hash=sha256:51a609a7c1bd9d9e75d92ee128c12c7852ae70a482900fbbccf3d13a79e0378c - # via -r requirements.in + # via -r ./requirements.in urllib3==1.25.11 \ --hash=sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2 \ --hash=sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e # via botocore yamllint==1.26.3 \ --hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e - # via -r requirements.in + # via -r ./requirements.in # The following packages are considered to be unsafe in a requirements file: setuptools==59.6.0 \ diff --git a/examples/pip_install/requirements_windows.txt b/examples/pip_install/requirements_windows.txt index 26de1adaac..09a6a83c5d 100644 --- a/examples/pip_install/requirements_windows.txt +++ b/examples/pip_install/requirements_windows.txt @@ -7,7 +7,7 @@ boto3==1.14.51 \ --hash=sha256:a6bdb808e948bd264af135af50efb76253e85732c451fa605b7a287faf022432 \ --hash=sha256:f9dbccbcec916051c6588adbccae86547308ac4cd154f1eb7cf6422f0e391a71 - # via -r requirements.in + # via -r ./requirements.in botocore==1.17.63 \ --hash=sha256:40f13f6c9c29c307a9dc5982739e537ddce55b29787b90c3447b507e3283bcd6 \ --hash=sha256:aa88eafc6295132f4bc606f1df32b3248e0fa611724c0a216aceda767948ac75 @@ -77,7 +77,7 @@ pyyaml==6.0 \ s3cmd==2.1.0 \ --hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \ --hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03 - # via -r requirements.in + # via -r ./requirements.in s3transfer==0.3.7 \ --hash=sha256:35627b86af8ff97e7ac27975fe0a98a312814b46c6333d8a6b889627bcd80994 \ --hash=sha256:efa5bd92a897b6a8d5c1383828dca3d52d0790e0756d49740563a3fb6ed03246 @@ -92,7 +92,7 @@ urllib3==1.25.11 \ # via botocore yamllint==1.26.3 \ --hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e - # via -r requirements.in + # via -r ./requirements.in # The following packages are considered to be unsafe in a requirements file: setuptools==59.6.0 \ diff --git a/examples/pip_parse/requirements_lock.txt b/examples/pip_parse/requirements_lock.txt index d3cb1f5bc9..a54d912d6a 100644 --- a/examples/pip_parse/requirements_lock.txt +++ b/examples/pip_parse/requirements_lock.txt @@ -66,11 +66,11 @@ pyyaml==6.0 \ requests==2.25.1 \ --hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \ --hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e - # via -r requirements.in + # via -r ./requirements.in s3cmd==2.1.0 \ --hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \ --hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03 - # via -r requirements.in + # via -r ./requirements.in six==1.16.0 \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 @@ -81,7 +81,7 @@ urllib3==1.26.7 \ # via requests yamllint==1.26.3 \ --hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e - # via -r requirements.in + # via -r ./requirements.in # The following packages are considered to be unsafe in a requirements file: setuptools==59.6.0 \ diff --git a/examples/pip_parse_vendored/requirements.txt b/examples/pip_parse_vendored/requirements.txt index 81b56154c2..d2dfc20576 100644 --- a/examples/pip_parse_vendored/requirements.txt +++ b/examples/pip_parse_vendored/requirements.txt @@ -19,7 +19,7 @@ idna==3.3 \ requests==2.27.1 \ --hash=sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61 \ --hash=sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d - # via -r requirements.in + # via -r ./requirements.in urllib3==1.26.9 \ --hash=sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14 \ --hash=sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e diff --git a/examples/pip_repository_annotations/requirements.txt b/examples/pip_repository_annotations/requirements.txt index e1c53c27e3..a2f161392a 100644 --- a/examples/pip_repository_annotations/requirements.txt +++ b/examples/pip_repository_annotations/requirements.txt @@ -9,4 +9,4 @@ wheel==0.37.1 \ --hash=sha256:4bdcd7d840138086126cd09254dc6195fb4fc6f01c050a1d7236f2630db1d22a \ --hash=sha256:e9a504e793efbca1b8e0e9cb979a249cf4a0a7b5b8c9e8b65a5e39d49529c1c4 - # via -r requirements.in + # via -r ./requirements.in diff --git a/python/pip_install/pip_compile.py b/python/pip_install/pip_compile.py index 09b3c9b035..09f07fefd5 100644 --- a/python/pip_install/pip_compile.py +++ b/python/pip_install/pip_compile.py @@ -35,20 +35,11 @@ def _select_golden_requirements_file( parse_str_none = lambda s: None if s == "None" else s - requirements_in = os.path.relpath(sys.argv.pop(1)) - requirements_txt = os.path.relpath(sys.argv.pop(1)) + requirements_in = sys.argv.pop(1) + requirements_txt = sys.argv.pop(1) requirements_linux = parse_str_none(sys.argv.pop(1)) requirements_darwin = parse_str_none(sys.argv.pop(1)) requirements_windows = parse_str_none(sys.argv.pop(1)) - parts = requirements_in.split(os.path.sep, 2) - if parts[0] == "external": - requirements_in = parts[2] - requirements_txt = ( - requirements_txt - if "BUILD_WORKSPACE_DIRECTORY" in os.environ - else os.path.join("..", "..", requirements_txt) - ) - os.chdir(os.path.join(parts[0], parts[1])) update_target_label = sys.argv.pop(1) # Before loading click, set the locale for its parser. @@ -83,9 +74,7 @@ def _select_golden_requirements_file( # # Changing to the WORKSPACE root avoids 'file not found' errors when the `.update` target is run # from different directories within the WORKSPACE. - requirements_txt = os.path.join( - os.environ["BUILD_WORKSPACE_DIRECTORY"], requirements_txt - ) + os.chdir(os.environ["BUILD_WORKSPACE_DIRECTORY"]) else: err_msg = ( "Expected to find BUILD_WORKSPACE_DIRECTORY (running under `bazel run`) or " diff --git a/tests/BUILD b/tests/BUILD index 46d8739622..b37a5a4232 100644 --- a/tests/BUILD +++ b/tests/BUILD @@ -8,8 +8,3 @@ bazel_integration_test( name = "pip_repository_entry_points_example", timeout = "long", ) - -bazel_integration_test( - name = "pip_deps_example", - timeout = "long", -) diff --git a/tests/pip_deps/BUILD b/tests/pip_deps/BUILD deleted file mode 100644 index 6a0412c718..0000000000 --- a/tests/pip_deps/BUILD +++ /dev/null @@ -1,19 +0,0 @@ -filegroup( - name = "requirements_txt", - srcs = ["requirements.txt"], - visibility = ["//visibility:public"], -) - -test_suite( - name = "external_tests", - tests = [ - "@unpinned_pip//:pin_test", - ], -) - -sh_test( - name = "no_external_test", - srcs = ["test.sh"], - args = ["$(rootpath :requirements_txt)"], - data = [":requirements_txt"], -) diff --git a/tests/pip_deps/README.md b/tests/pip_deps/README.md deleted file mode 100644 index d9151baf11..0000000000 --- a/tests/pip_deps/README.md +++ /dev/null @@ -1 +0,0 @@ -Run `bazel run @unpinned_pip//:pin.update` to keep `PIP_PACKAGES` in `//:WORKSPACE` in sync with `//:requirements.txt`. diff --git a/tests/pip_deps/WORKSPACE b/tests/pip_deps/WORKSPACE deleted file mode 100644 index 83ecf85e37..0000000000 --- a/tests/pip_deps/WORKSPACE +++ /dev/null @@ -1,26 +0,0 @@ -workspace(name = "pip_deps") - -local_repository( - name = "rules_python", - path = "../..", -) - -load("@rules_python//python:repositories.bzl", "python_register_toolchains") - -# This toolchain is explicitly 3.10 while `rules_python` is 3.9 to act as -# a regression test, ensuring 3.10 is functional -python_register_toolchains( - name = "python310", - python_version = "3.10", -) - -load("@python310//:defs.bzl", "interpreter") -load("//:pip_deps.bzl", "pip_deps") - -PIP_PACKAGES = {"sphinx": "4.5.0"} - -pip_deps( - name = "pip", - packages = PIP_PACKAGES, - python_interpreter_target = interpreter, -) diff --git a/tests/pip_deps/pip_deps.bzl b/tests/pip_deps/pip_deps.bzl deleted file mode 100644 index 93426a6911..0000000000 --- a/tests/pip_deps/pip_deps.bzl +++ /dev/null @@ -1,55 +0,0 @@ -""" A demo implementation for pip_deps which provides @unpinned_pip//:pin. """ - -load("@rules_python//python:pip.bzl", "pip_parse") - -def _requirements_in_impl(repository_ctx): - repository_ctx.file( - "requirements.in", - content = "".join(["{package} == {version}\n".format( - package = package, - version = version, - ) for (package, version) in repository_ctx.attr.packages.items()]), - ) - repository_ctx.file("WORKSPACE", content = "") - repository_ctx.file("BUILD", content = """ -load("@rules_python//python:pip.bzl", "compile_pip_requirements") - -compile_pip_requirements( - name = "pin", - extra_args = ["--allow-unsafe"], - requirements_in = "requirements.in", - requirements_txt = "@{workspace_name}//{package}:{name}", -) -""".format( - workspace_name = repository_ctx.attr.requirements_lock.workspace_name, - package = repository_ctx.attr.requirements_lock.package, - name = repository_ctx.attr.requirements_lock.name, - )) - -_requirements_in = repository_rule( - implementation = _requirements_in_impl, - attrs = { - "packages": attr.string_dict(), - "requirements_lock": attr.label(allow_single_file = True), - }, -) - -def pip_deps( - *, - name = "pip", - packages = {}, - requirements_lock_target = Label("//:requirements_txt"), - requirements_lock_file = Label("//:requirements.txt"), - python_interpreter_target = None, - **kwargs): - _requirements_in( - name = "unpinned_" + name, - packages = packages, - requirements_lock = requirements_lock_target, - ) - pip_parse( - name = name, - requirements_lock = requirements_lock_file, - python_interpreter_target = python_interpreter_target, - **kwargs - ) diff --git a/tests/pip_deps/requirements.txt b/tests/pip_deps/requirements.txt deleted file mode 100644 index d5fa9e7254..0000000000 --- a/tests/pip_deps/requirements.txt +++ /dev/null @@ -1,136 +0,0 @@ -# -# This file is autogenerated by pip-compile with python 3.10 -# To update, run: -# -# bazel run //:pin.update -# -alabaster==0.7.12 \ - --hash=sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359 \ - --hash=sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02 - # via sphinx -babel==2.10.1 \ - --hash=sha256:3f349e85ad3154559ac4930c3918247d319f21910d5ce4b25d439ed8693b98d2 \ - --hash=sha256:98aeaca086133efb3e1e2aad0396987490c8425929ddbcfe0550184fdc54cd13 - # via sphinx -certifi==2021.10.8 \ - --hash=sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872 \ - --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569 - # via requests -charset-normalizer==2.0.12 \ - --hash=sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597 \ - --hash=sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df - # via requests -docutils==0.17.1 \ - --hash=sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125 \ - --hash=sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61 - # via sphinx -idna==3.3 \ - --hash=sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff \ - --hash=sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d - # via requests -imagesize==1.3.0 \ - --hash=sha256:1db2f82529e53c3e929e8926a1fa9235aa82d0bd0c580359c67ec31b2fddaa8c \ - --hash=sha256:cd1750d452385ca327479d45b64d9c7729ecf0b3969a58148298c77092261f9d - # via sphinx -jinja2==3.1.2 \ - --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \ - --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61 - # via sphinx -markupsafe==2.1.1 \ - --hash=sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003 \ - --hash=sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88 \ - --hash=sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5 \ - --hash=sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7 \ - --hash=sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a \ - --hash=sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603 \ - --hash=sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1 \ - --hash=sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135 \ - --hash=sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247 \ - --hash=sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6 \ - --hash=sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601 \ - --hash=sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77 \ - --hash=sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02 \ - --hash=sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e \ - --hash=sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63 \ - --hash=sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f \ - --hash=sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980 \ - --hash=sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b \ - --hash=sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812 \ - --hash=sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff \ - --hash=sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96 \ - --hash=sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1 \ - --hash=sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925 \ - --hash=sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a \ - --hash=sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6 \ - --hash=sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e \ - --hash=sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f \ - --hash=sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4 \ - --hash=sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f \ - --hash=sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3 \ - --hash=sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c \ - --hash=sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a \ - --hash=sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417 \ - --hash=sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a \ - --hash=sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a \ - --hash=sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37 \ - --hash=sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452 \ - --hash=sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933 \ - --hash=sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a \ - --hash=sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7 - # via jinja2 -packaging==21.3 \ - --hash=sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb \ - --hash=sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522 - # via sphinx -pygments==2.12.0 \ - --hash=sha256:5eb116118f9612ff1ee89ac96437bb6b49e8f04d8a13b514ba26f620208e26eb \ - --hash=sha256:dc9c10fb40944260f6ed4c688ece0cd2048414940f1cea51b8b226318411c519 - # via sphinx -pyparsing==3.0.8 \ - --hash=sha256:7bf433498c016c4314268d95df76c81b842a4cb2b276fa3312cfb1e1d85f6954 \ - --hash=sha256:ef7b523f6356f763771559412c0d7134753f037822dad1b16945b7b846f7ad06 - # via packaging -pytz==2022.1 \ - --hash=sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7 \ - --hash=sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c - # via babel -requests==2.27.1 \ - --hash=sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61 \ - --hash=sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d - # via sphinx -snowballstemmer==2.2.0 \ - --hash=sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1 \ - --hash=sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a - # via sphinx -sphinx==4.5.0 \ - --hash=sha256:7bf8ca9637a4ee15af412d1a1d9689fec70523a68ca9bb9127c2f3eeb344e2e6 \ - --hash=sha256:ebf612653238bcc8f4359627a9b7ce44ede6fdd75d9d30f68255c7383d3a6226 - # via -r requirements.in -sphinxcontrib-applehelp==1.0.2 \ - --hash=sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a \ - --hash=sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58 - # via sphinx -sphinxcontrib-devhelp==1.0.2 \ - --hash=sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e \ - --hash=sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4 - # via sphinx -sphinxcontrib-htmlhelp==2.0.0 \ - --hash=sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07 \ - --hash=sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2 - # via sphinx -sphinxcontrib-jsmath==1.0.1 \ - --hash=sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178 \ - --hash=sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8 - # via sphinx -sphinxcontrib-qthelp==1.0.3 \ - --hash=sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72 \ - --hash=sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6 - # via sphinx -sphinxcontrib-serializinghtml==1.1.5 \ - --hash=sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd \ - --hash=sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952 - # via sphinx -urllib3==1.26.9 \ - --hash=sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14 \ - --hash=sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e - # via requests diff --git a/tests/pip_deps/test.sh b/tests/pip_deps/test.sh deleted file mode 100755 index 5c356fd500..0000000000 --- a/tests/pip_deps/test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -set -euo pipefail - -! grep external "$1" diff --git a/tests/pip_repository_entry_points/requirements.txt b/tests/pip_repository_entry_points/requirements.txt index 02bc8751b0..279aed0e80 100644 --- a/tests/pip_repository_entry_points/requirements.txt +++ b/tests/pip_repository_entry_points/requirements.txt @@ -173,7 +173,7 @@ snowballstemmer==2.2.0 \ sphinx==4.3.2 \ --hash=sha256:0a8836751a68306b3fe97ecbe44db786f8479c3bf4b80e3a7f5c838657b4698c \ --hash=sha256:6a11ea5dd0bdb197f9c2abc2e0ce73e01340464feaece525e64036546d24c851 - # via -r requirements.in + # via -r ./requirements.in sphinxcontrib-applehelp==1.0.2 \ --hash=sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a \ --hash=sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58 @@ -204,13 +204,13 @@ urllib3==1.26.7 \ # via requests yamllint==1.26.3 \ --hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e - # via -r requirements.in + # via -r ./requirements.in # The following packages are considered to be unsafe in a requirements file: setuptools==59.6.0 \ --hash=sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373 \ --hash=sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e # via - # -r requirements.in + # -r ./requirements.in # sphinx # yamllint From cf6542d4f668544eb7f75978a170400ea1950317 Mon Sep 17 00:00:00 2001 From: Greg Roodt Date: Mon, 29 Aug 2022 12:55:30 +1000 Subject: [PATCH 027/234] =?UTF-8?q?Revert=20"Revert=20"Add=20option=20to?= =?UTF-8?q?=20use=20"pip=20download"=20instead=20of=20"pip=20wheel"=20to?= =?UTF-8?q?=20do=E2=80=A6"=20(#811)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/pip_repository.md | 16 +++++++++------- examples/pip_parse_vendored/requirements.bzl | 2 +- python/pip_install/extract_wheels/arguments.py | 6 ++++++ .../extract_wheels/extract_single_wheel.py | 2 +- .../pip_install/extract_wheels/extract_wheels.py | 2 +- python/pip_install/pip_repository.bzl | 10 ++++++++++ 6 files changed, 28 insertions(+), 10 deletions(-) diff --git a/docs/pip_repository.md b/docs/pip_repository.md index ef7f72bcd2..c66d8bfd91 100644 --- a/docs/pip_repository.md +++ b/docs/pip_repository.md @@ -5,10 +5,10 @@ ## pip_repository
-pip_repository(name, annotations, enable_implicit_namespace_pkgs, environment, extra_pip_args,
-               incremental, isolated, pip_data_exclude, python_interpreter, python_interpreter_target,
-               quiet, repo_prefix, requirements, requirements_darwin, requirements_linux,
-               requirements_lock, requirements_windows, timeout)
+pip_repository(name, annotations, download_only, enable_implicit_namespace_pkgs, environment,
+               extra_pip_args, incremental, isolated, pip_data_exclude, python_interpreter,
+               python_interpreter_target, quiet, repo_prefix, requirements, requirements_darwin,
+               requirements_linux, requirements_lock, requirements_windows, timeout)
 
A rule for importing `requirements.txt` dependencies into Bazel. @@ -58,6 +58,7 @@ py_binary( | :-------------: | :-------------: | :-------------: | :-------------: | :-------------: | | name | A unique name for this repository. | Name | required | | | annotations | Optional annotations to apply to packages | Dictionary: String -> String | optional | {} | +| download_only | Whether to use "pip download" instead of "pip wheel". Disables building wheels from source, but allows use of --platform, --python-version, --implementation, and --abi in --extra_pip_args to download wheels for a different platform from the host platform. | Boolean | optional | False | | enable_implicit_namespace_pkgs | If true, disables conversion of native namespace packages into pkg-util style namespace packages. When set all py_binary and py_test targets must specify either legacy_create_init=False or the global Bazel option --incompatible_default_to_explicit_init_py to prevent __init__.py being automatically generated in every directory.

This option is required to support some packages which cannot handle the conversion to pkg-util style. | Boolean | optional | False | | environment | Environment variables to set in the pip subprocess. Can be used to set common variables such as http_proxy, https_proxy and no_proxy Note that pip is run with "--isolated" on the CLI so PIP_<VAR>_<NAME> style env vars are ignored, but env vars that control requests and urllib3 can be passed. | Dictionary: String -> String | optional | {} | | extra_pip_args | Extra arguments to pass on to pip. Must not contain spaces. | List of strings | optional | [] | @@ -81,9 +82,9 @@ py_binary( ## whl_library
-whl_library(name, annotation, enable_implicit_namespace_pkgs, environment, extra_pip_args, isolated,
-            pip_data_exclude, python_interpreter, python_interpreter_target, quiet, repo, repo_prefix,
-            requirement, timeout)
+whl_library(name, annotation, download_only, enable_implicit_namespace_pkgs, environment,
+            extra_pip_args, isolated, pip_data_exclude, python_interpreter, python_interpreter_target,
+            quiet, repo, repo_prefix, requirement, timeout)
 
@@ -97,6 +98,7 @@ Instantiated from pip_repository and inherits config options from there. | :-------------: | :-------------: | :-------------: | :-------------: | :-------------: | | name | A unique name for this repository. | Name | required | | | annotation | Optional json encoded file containing annotation to apply to the extracted wheel. See package_annotation | Label | optional | None | +| download_only | Whether to use "pip download" instead of "pip wheel". Disables building wheels from source, but allows use of --platform, --python-version, --implementation, and --abi in --extra_pip_args to download wheels for a different platform from the host platform. | Boolean | optional | False | | enable_implicit_namespace_pkgs | If true, disables conversion of native namespace packages into pkg-util style namespace packages. When set all py_binary and py_test targets must specify either legacy_create_init=False or the global Bazel option --incompatible_default_to_explicit_init_py to prevent __init__.py being automatically generated in every directory.

This option is required to support some packages which cannot handle the conversion to pkg-util style. | Boolean | optional | False | | environment | Environment variables to set in the pip subprocess. Can be used to set common variables such as http_proxy, https_proxy and no_proxy Note that pip is run with "--isolated" on the CLI so PIP_<VAR>_<NAME> style env vars are ignored, but env vars that control requests and urllib3 can be passed. | Dictionary: String -> String | optional | {} | | extra_pip_args | Extra arguments to pass on to pip. Must not contain spaces. | List of strings | optional | [] | diff --git a/examples/pip_parse_vendored/requirements.bzl b/examples/pip_parse_vendored/requirements.bzl index 038b612309..58c6e7bad1 100644 --- a/examples/pip_parse_vendored/requirements.bzl +++ b/examples/pip_parse_vendored/requirements.bzl @@ -12,7 +12,7 @@ all_requirements = ["@pip_certifi//:pkg", "@pip_charset_normalizer//:pkg", "@pip all_whl_requirements = ["@pip_certifi//:whl", "@pip_charset_normalizer//:whl", "@pip_idna//:whl", "@pip_requests//:whl", "@pip_urllib3//:whl"] _packages = [("pip_certifi", "certifi==2021.10.8 --hash=sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872 --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"), ("pip_charset_normalizer", "charset-normalizer==2.0.12 --hash=sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597 --hash=sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"), ("pip_idna", "idna==3.3 --hash=sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff --hash=sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"), ("pip_requests", "requests==2.27.1 --hash=sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61 --hash=sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"), ("pip_urllib3", "urllib3==1.26.9 --hash=sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14 --hash=sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e")] -_config = {"enable_implicit_namespace_pkgs": False, "environment": {}, "extra_pip_args": [], "isolated": True, "pip_data_exclude": [], "python_interpreter": "python3", "python_interpreter_target": interpreter, "quiet": True, "repo": "pip", "repo_prefix": "pip_", "timeout": 600} +_config = {"download_only": False, "enable_implicit_namespace_pkgs": False, "environment": {}, "extra_pip_args": [], "isolated": True, "pip_data_exclude": [], "python_interpreter": "python3", "python_interpreter_target": interpreter, "quiet": True, "repo": "pip", "repo_prefix": "pip_", "timeout": 600} _annotations = {} def _clean_name(name): diff --git a/python/pip_install/extract_wheels/arguments.py b/python/pip_install/extract_wheels/arguments.py index d7d34523a7..ce77bb028e 100644 --- a/python/pip_install/extract_wheels/arguments.py +++ b/python/pip_install/extract_wheels/arguments.py @@ -39,6 +39,12 @@ def parse_common_args(parser: ArgumentParser) -> ArgumentParser: required=True, help="Prefix to prepend to packages", ) + parser.add_argument( + "--download_only", + action="store_true", + help="Use 'pip download' instead of 'pip wheel'. Disables building wheels from source, but allows use of " + "--platform, --python-version, --implementation, and --abi in --extra_pip_args.", + ) return parser diff --git a/python/pip_install/extract_wheels/extract_single_wheel.py b/python/pip_install/extract_wheels/extract_single_wheel.py index 27f29ac838..a7cc672a76 100644 --- a/python/pip_install/extract_wheels/extract_single_wheel.py +++ b/python/pip_install/extract_wheels/extract_single_wheel.py @@ -38,7 +38,7 @@ def main() -> None: pip_args = ( [sys.executable, "-m", "pip"] + (["--isolated"] if args.isolated else []) - + ["wheel", "--no-deps"] + + ["download" if args.download_only else "wheel", "--no-deps"] + deserialized_args["extra_pip_args"] ) diff --git a/python/pip_install/extract_wheels/extract_wheels.py b/python/pip_install/extract_wheels/extract_wheels.py index 7e583eb442..2addaf89fd 100644 --- a/python/pip_install/extract_wheels/extract_wheels.py +++ b/python/pip_install/extract_wheels/extract_wheels.py @@ -80,7 +80,7 @@ def main() -> None: pip_args = ( [sys.executable, "-m", "pip"] + (["--isolated"] if args.isolated else []) - + ["wheel", "-r", args.requirements] + + ["download" if args.download_only else "wheel", "-r", args.requirements] + ["--wheel-dir", os.getcwd()] + deserialized_args["extra_pip_args"] ) diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl index 6395bc5d3f..d729ae91b5 100644 --- a/python/pip_install/pip_repository.bzl +++ b/python/pip_install/pip_repository.bzl @@ -163,6 +163,9 @@ def _parse_optional_attrs(rctx, args): struct(arg = rctx.attr.extra_pip_args).to_json(), ] + if rctx.attr.download_only: + args.append("--download_only") + if rctx.attr.pip_data_exclude != None: args += [ "--pip_data_exclude", @@ -293,6 +296,13 @@ common_env = [ ] common_attrs = { + "download_only": attr.bool( + doc = """ +Whether to use "pip download" instead of "pip wheel". Disables building wheels from source, but allows use of +--platform, --python-version, --implementation, and --abi in --extra_pip_args to download wheels for a different +platform from the host platform. + """, + ), "enable_implicit_namespace_pkgs": attr.bool( default = False, doc = """ From 0dfc546a65ba5676866dac316456edcf3d3caaab Mon Sep 17 00:00:00 2001 From: Abhishek Shivanna Date: Tue, 30 Aug 2022 15:19:10 -0700 Subject: [PATCH 028/234] Make gazelle_python_manifest output deterministic (#813) * Make gazelle_python_manifest output deterministic Fixes 812 * address review comments Co-authored-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- gazelle/manifest/BUILD.bazel | 5 ++++- gazelle/manifest/manifest.go | 23 ++++++++++++++++++++++- gazelle/manifest/manifest_test.go | 4 ++-- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/gazelle/manifest/BUILD.bazel b/gazelle/manifest/BUILD.bazel index 2e5b6b8e99..281bcd29cf 100644 --- a/gazelle/manifest/BUILD.bazel +++ b/gazelle/manifest/BUILD.bazel @@ -5,7 +5,10 @@ go_library( srcs = ["manifest.go"], importpath = "github.com/bazelbuild/rules_python/gazelle/manifest", visibility = ["//visibility:public"], - deps = ["@in_gopkg_yaml_v2//:yaml_v2"], + deps = [ + "@com_github_emirpasic_gods//sets/treeset", + "@in_gopkg_yaml_v2//:yaml_v2", + ], ) go_test( diff --git a/gazelle/manifest/manifest.go b/gazelle/manifest/manifest.go index b92706a230..e19162bd5d 100644 --- a/gazelle/manifest/manifest.go +++ b/gazelle/manifest/manifest.go @@ -6,6 +6,8 @@ import ( "io" "os" + "github.com/emirpasic/gods/sets/treeset" + yaml "gopkg.in/yaml.v2" ) @@ -94,11 +96,30 @@ func (f *File) Decode(manifestPath string) error { return nil } +// ModulesMapping is the type used to map from importable Python modules to +// the wheel names that provide these modules. +type ModulesMapping map[string]string + +// MarshalYAML makes sure that we sort the module names before marshaling +// the contents of `ModulesMapping` to a YAML file. This ensures that the +// file is deterministically generated from the map. +func (m ModulesMapping) MarshalYAML() (interface{}, error) { + var mapslice yaml.MapSlice + keySet := treeset.NewWithStringComparator() + for key := range m { + keySet.Add(key) + } + for _, key := range keySet.Values() { + mapslice = append(mapslice, yaml.MapItem{Key: key, Value: m[key.(string)]}) + } + return mapslice, nil +} + // Manifest represents the structure of the Gazelle manifest file. type Manifest struct { // ModulesMapping is the mapping from importable modules to which Python // wheel name provides these modules. - ModulesMapping map[string]string `yaml:"modules_mapping"` + ModulesMapping ModulesMapping `yaml:"modules_mapping"` // PipDepsRepositoryName is the name of the pip_install repository target. // DEPRECATED PipDepsRepositoryName string `yaml:"pip_deps_repository_name,omitempty"` diff --git a/gazelle/manifest/manifest_test.go b/gazelle/manifest/manifest_test.go index 40a231f2bd..3b50fd1b3e 100644 --- a/gazelle/manifest/manifest_test.go +++ b/gazelle/manifest/manifest_test.go @@ -10,7 +10,7 @@ import ( "github.com/bazelbuild/rules_python/gazelle/manifest" ) -var modulesMapping = map[string]string{ +var modulesMapping = manifest.ModulesMapping{ "arrow": "arrow", "arrow.__init__": "arrow", "arrow.api": "arrow", @@ -76,4 +76,4 @@ func TestFile(t *testing.T) { t.FailNow() } }) -} \ No newline at end of file +} From ad0b8f8c80516e49f3871164da7aba927b222133 Mon Sep 17 00:00:00 2001 From: Gary Miguel Date: Tue, 30 Aug 2022 15:34:31 -0700 Subject: [PATCH 029/234] specify timeout for gazelle manifest test (#817) Fixes https://github.com/bazelbuild/rules_python/issues/802 Co-authored-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- gazelle/manifest/defs.bzl | 1 + 1 file changed, 1 insertion(+) diff --git a/gazelle/manifest/defs.bzl b/gazelle/manifest/defs.bzl index bbcda72fc1..8439319238 100644 --- a/gazelle/manifest/defs.bzl +++ b/gazelle/manifest/defs.bzl @@ -88,6 +88,7 @@ def gazelle_python_manifest( "_TEST_REQUIREMENTS": "$(rootpath {})".format(requirements), }, visibility = ["//visibility:private"], + timeout = "short", ) native.filegroup( From ccbb05e35552d7a5b36df39e1a1e7723677d4b39 Mon Sep 17 00:00:00 2001 From: Jeremy Volkman Date: Wed, 7 Sep 2022 14:55:28 -0700 Subject: [PATCH 030/234] Allow overriding config attrs in pip_parse-generated install_deps (#751) --- examples/pip_parse_vendored/README.md | 20 +++++++++++++++++++ examples/pip_parse_vendored/requirements.bzl | 6 ++++-- .../parse_requirements_to_bzl.py | 6 ++++-- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/examples/pip_parse_vendored/README.md b/examples/pip_parse_vendored/README.md index 616e291409..f53260a175 100644 --- a/examples/pip_parse_vendored/README.md +++ b/examples/pip_parse_vendored/README.md @@ -9,3 +9,23 @@ The requirements now form a triple: - requirements.in - human editable, expresses only direct dependencies and load-bearing version constraints - requirements.txt - lockfile produced by pip-compile or other means - requirements.bzl - the "parsed" version of the lockfile readable by Bazel downloader + +The `requirements.bzl` file contains baked-in attributes such as `python_interpreter_target` as they were specified in the original `pip_parse` rule. These can be overridden at install time by passing arguments to `install_deps`. For example: + +```python +# Register a hermetic toolchain +load("@rules_python//python:repositories.bzl", "python_register_toolchains") + +python_register_toolchains( + name = "python39", + python_version = "3.9", +) +load("@python39//:defs.bzl", "interpreter") + +# Load dependencies vendored by some other ruleset. +load("@some_rules//:py_deps.bzl", "install_deps") + +install_deps( + python_interpreter_target = interpreter, +) +``` diff --git a/examples/pip_parse_vendored/requirements.bzl b/examples/pip_parse_vendored/requirements.bzl index 58c6e7bad1..33199b07aa 100644 --- a/examples/pip_parse_vendored/requirements.bzl +++ b/examples/pip_parse_vendored/requirements.bzl @@ -41,11 +41,13 @@ def _get_annotation(requirement): name = requirement.split(" ")[0].split("=")[0] return _annotations.get(name) -def install_deps(): +def install_deps(**whl_library_kwargs): + whl_config = dict(_config) + whl_config.update(whl_library_kwargs) for name, requirement in _packages: whl_library( name = name, requirement = requirement, annotation = _get_annotation(requirement), - **_config + **whl_config ) diff --git a/python/pip_install/extract_wheels/parse_requirements_to_bzl.py b/python/pip_install/extract_wheels/parse_requirements_to_bzl.py index 5762cf542c..d0abcac891 100644 --- a/python/pip_install/extract_wheels/parse_requirements_to_bzl.py +++ b/python/pip_install/extract_wheels/parse_requirements_to_bzl.py @@ -158,13 +158,15 @@ def _get_annotation(requirement): name = requirement.split(" ")[0].split("=")[0] return _annotations.get(name) - def install_deps(): + def install_deps(**whl_library_kwargs): + whl_config = dict(_config) + whl_config.update(whl_library_kwargs) for name, requirement in _packages: whl_library( name = name, requirement = requirement, annotation = _get_annotation(requirement), - **_config + **whl_config ) """.format( all_requirements=all_requirements, From 03dc1373cd38c9794cdee48a659c2c0f629dc907 Mon Sep 17 00:00:00 2001 From: lripoche Date: Mon, 12 Sep 2022 22:14:02 +0200 Subject: [PATCH 031/234] fix pip_compile pip_compile select_golden_requirements_file invocation arguments (#826) fix arguments order --- python/pip_install/pip_compile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/pip_install/pip_compile.py b/python/pip_install/pip_compile.py index 09f07fefd5..9258c17ffd 100644 --- a/python/pip_install/pip_compile.py +++ b/python/pip_install/pip_compile.py @@ -120,8 +120,8 @@ def _select_golden_requirements_file( elif e.code == 0: golden_filename = _select_golden_requirements_file( requirements_txt, - requirements_darwin, requirements_linux, + requirements_darwin, requirements_windows, ) golden = open(golden_filename).readlines() From a364fcac97b7ccadb5c5a703ec8ce2f2ecef0d97 Mon Sep 17 00:00:00 2001 From: Yun Peng Date: Fri, 16 Sep 2022 15:02:04 +0200 Subject: [PATCH 032/234] =?UTF-8?q?Disable=20`//python/tests/toolchains:py?= =?UTF-8?q?thon=5F3=5F8=5F10=5Fx86=5F64-apple-darwin=5F=E2=80=A6=20(#830)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bazelci/presubmit.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 1cc121a4e7..666654998b 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -12,7 +12,10 @@ all_targets: &all_targets # We control Bazel version in integration tests, so we don't need USE_BAZEL_VERSION for tests. skip_use_bazel_version_for_test: true test_targets: + - "--" - "..." + # Disabled due to https://github.com/bazelbuild/rules_python/issues/827 + - "-//python/tests/toolchains:python_3_8_10_x86_64-apple-darwin_test" platforms: ubuntu1804: <<: *all_targets @@ -37,4 +40,4 @@ platforms: # The dependencies needed for this test are not cross-platform: https://github.com/bazelbuild/rules_python/issues/260 - "-//tests:pip_repository_entry_points_example" test_flags: - - "--test_tag_filters=-fix-windows" \ No newline at end of file + - "--test_tag_filters=-fix-windows" From f0efec5cf8c0ae16483ee677a09ec70737a01bf5 Mon Sep 17 00:00:00 2001 From: Greg Roodt Date: Sun, 25 Sep 2022 06:04:15 +1000 Subject: [PATCH 033/234] Standardise on pip_parse (#807) --- README.md | 81 ++++------- docs/pip.md | 67 ++------- docs/pip_repository.md | 12 +- examples/BUILD | 5 - examples/pip_install/BUILD | 6 +- examples/pip_install/WORKSPACE | 5 + examples/pip_install/pip_install_test.py | 24 ++-- examples/pip_repository_annotations/BUILD | 2 +- examples/pip_repository_annotations/WORKSPACE | 8 +- examples/relative_requirements/BUILD | 10 -- examples/relative_requirements/README.md | 4 - examples/relative_requirements/WORKSPACE | 21 --- examples/relative_requirements/main.py | 5 - .../relative_package_name/__init__.py | 2 - .../relative_package/setup.py | 7 - .../relative_requirements/requirements.txt | 1 - python/pip.bzl | 85 +++-------- python/pip_install/extract_wheels/BUILD | 9 -- .../extract_wheels/extract_single_wheel.py | 27 +++- .../extract_wheels/extract_wheels.py | 132 ------------------ python/pip_install/pip_repository.bzl | 72 +++------- python/pip_install/private/srcs.bzl | 1 - tests/pip_repository_entry_points/WORKSPACE | 8 +- 23 files changed, 139 insertions(+), 455 deletions(-) delete mode 100644 examples/relative_requirements/BUILD delete mode 100644 examples/relative_requirements/README.md delete mode 100644 examples/relative_requirements/WORKSPACE delete mode 100644 examples/relative_requirements/main.py delete mode 100644 examples/relative_requirements/relative_package/relative_package_name/__init__.py delete mode 100644 examples/relative_requirements/relative_package/setup.py delete mode 100644 examples/relative_requirements/requirements.txt delete mode 100644 python/pip_install/extract_wheels/extract_wheels.py diff --git a/README.md b/README.md index 7359a2ae4e..944493c6a9 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,7 @@ This repository is the home of the core Python rules -- `py_library`, `py_binary`, `py_test`, and related symbols that provide the basis for Python -support in Bazel. It also contains packaging rules for integrating with PyPI -(`pip`). Documentation lives in the +support in Bazel. It also contains package installation rules for integrating with PyPI and other package indices. Documentation lives in the [`docs/`](https://github.com/bazelbuild/rules_python/tree/main/docs) directory and in the [Bazel Build Encyclopedia](https://docs.bazel.build/versions/master/be/python.html). @@ -24,7 +23,7 @@ Once they are fully migrated to rules_python, they may evolve at a different rate, but this repository will still follow [semantic versioning](https://semver.org). -The packaging rules (`pip_install`, etc.) are less stable. We may make breaking +The package installation rules (`pip_install`, `pip_parse` etc.) are less stable. We may make breaking changes as they evolve. This repository is maintained by the Bazel community. Neither Google, nor the @@ -101,14 +100,14 @@ py_binary( ) ``` -## Using the packaging rules +## Using the package installation rules Usage of the packaging rules involves two main steps. -1. [Installing `pip` dependencies](#installing-pip-dependencies) -2. [Consuming `pip` dependencies](#consuming-pip-dependencies) +1. [Installing third_party packages](#installing-third_party-packages) +2. [Using third_party packages as dependencies](#using-third_party-packages-as-dependencies) -The packaging rules create two kinds of repositories: A central external repo that holds +The package installation rules create two kinds of repositories: A central external repo that holds downloaded wheel files, and individual external repos for each wheel's extracted contents. Users only need to interact with the central external repo; the wheel repos are essentially an implementation detail. The central external repo provides a @@ -116,55 +115,12 @@ are essentially an implementation detail. The central external repo provides a `BUILD` files that translates a pip package name into the label of a `py_library` target in the appropriate wheel repo. -### Installing `pip` dependencies +### Installing third_party packages To add pip dependencies to your `WORKSPACE`, load the `pip_install` function, and call it to create the central external repo and individual wheel external repos. -```python -load("@rules_python//python:pip.bzl", "pip_install") - -# Create a central external repo, @my_deps, that contains Bazel targets for all the -# third-party packages specified in the requirements.txt file. -pip_install( - name = "my_deps", - requirements = "//path/to:requirements.txt", -) -``` - -Note that since `pip_install` is a repository rule and therefore executes pip at WORKSPACE-evaluation time, Bazel has no -information about the Python toolchain and cannot enforce that the interpreter -used to invoke pip matches the interpreter used to run `py_binary` targets. By -default, `pip_install` uses the system command `"python3"`. This can be overridden by passing the -`python_interpreter` attribute or `python_interpreter_target` attribute to `pip_install`. - -You can have multiple `pip_install`s in the same workspace. This will create multiple external repos that have no relation to -one another, and may result in downloading the same wheels multiple times. - -As with any repository rule, if you would like to ensure that `pip_install` is -re-executed in order to pick up a non-hermetic change to your environment (e.g., -updating your system `python` interpreter), you can force it to re-execute by running -`bazel sync --only [pip_install name]`. - -### Fetch `pip` dependencies lazily - -One pain point with `pip_install` is the need to download all dependencies resolved by -your requirements.txt before the bazel analysis phase can start. For large python monorepos -this can take a long time, especially on slow connections. - -`pip_parse` provides a solution to this problem. If you can provide a lock -file of all your python dependencies `pip_parse` will translate each requirement into its own external repository. -Bazel will only fetch/build wheels for the requirements in the subgraph of your build target. - -There are API differences between `pip_parse` and `pip_install`: -1. `pip_parse` requires a fully resolved lock file of your python dependencies. You can generate this by using the `compile_pip_requirements` rule, - running `pip-compile` directly, or using virtualenv and `pip freeze`. `pip_parse` uses a label argument called `requirements_lock` instead of - `requirements` to make this distinction clear. -2. `pip_parse` translates your requirements into a starlark macro called `install_deps`. You must call this macro in your WORKSPACE to - declare your dependencies. - - ```python load("@rules_python//python:pip.bzl", "pip_parse") @@ -174,14 +130,33 @@ pip_parse( name = "my_deps", requirements_lock = "//path/to:requirements_lock.txt", ) - # Load the starlark macro which will define your dependencies. load("@my_deps//:requirements.bzl", "install_deps") # Call it to define repos for your requirements. install_deps() ``` -### Consuming `pip` dependencies +Note that since `pip_parse` is a repository rule and therefore executes pip at WORKSPACE-evaluation time, Bazel has no +information about the Python toolchain and cannot enforce that the interpreter +used to invoke pip matches the interpreter used to run `py_binary` targets. By +default, `pip_parse` uses the system command `"python3"`. This can be overridden by passing the +`python_interpreter` attribute or `python_interpreter_target` attribute to `pip_parse`. + +You can have multiple `pip_parse`s in the same workspace. This will create multiple external repos that have no relation to +one another, and may result in downloading the same wheels multiple times. + +As with any repository rule, if you would like to ensure that `pip_parse` is +re-executed in order to pick up a non-hermetic change to your environment (e.g., +updating your system `python` interpreter), you can force it to re-execute by running +`bazel sync --only [pip_parse name]`. + +Note: The `pip_install` rule is deprecated. `pip_parse` offers identical functionality and both `pip_install` +and `pip_parse` now have the same implementation. The name `pip_install` may be removed in a future version of the rules. +The maintainers have taken all reasonable efforts to faciliate a smooth transition, but some users of `pip_install` will +need to replace their existing `requirements.txt` with a fully resolved set of dependencies using a tool such as +`pip-tools` or the `compile_pip_requirements` repository rule. + +### Using third_party packages as dependencies Each extracted wheel repo contains a `py_library` target representing the wheel's contents. There are two ways to access this library. The diff --git a/docs/pip.md b/docs/pip.md index 4853e5252d..f6d8430adc 100644 --- a/docs/pip.md +++ b/docs/pip.md @@ -73,69 +73,19 @@ Annotations to apply to the BUILD file content from package generated from a `pi pip_install(requirements, name, kwargs) -Accepts a `requirements.txt` file and installs the dependencies listed within. - -Those dependencies become available in a generated `requirements.bzl` file. - -This macro wraps the [`pip_repository`](./pip_repository.md) rule that invokes `pip`. -In your WORKSPACE file: +Accepts a locked/compiled requirements file and installs the dependencies listed within. ```python +load("@rules_python//python:pip.bzl", "pip_install") + pip_install( + name = "pip_deps", requirements = ":requirements.txt", ) -``` - -You can then reference installed dependencies from a `BUILD` file with: -```python -load("@pip//:requirements.bzl", "requirement") -py_library( - name = "bar", - ... - deps = [ - "//my/other:dep", - requirement("requests"), - requirement("numpy"), - ], -) -``` - -> Note that this convenience comes with a cost. -> Analysis of any BUILD file which loads the requirements helper in this way will -> cause an eager-fetch of all the pip dependencies, -> even if no python targets are requested to be built. -> In a multi-language repo, this may cause developers to fetch dependencies they don't need, -> so consider using the long form for dependencies if this happens. - -In addition to the `requirement` macro, which is used to access the `py_library` -target generated from a package's wheel, the generated `requirements.bzl` file contains -functionality for exposing [entry points][whl_ep] as `py_binary` targets. - -[whl_ep]: https://packaging.python.org/specifications/entry-points/ - -```python -load("@pip_deps//:requirements.bzl", "entry_point") - -alias( - name = "pip-compile", - actual = entry_point( - pkg = "pip-tools", - script = "pip-compile", - ), -) -``` - -Note that for packages whose name and script are the same, only the name of the package -is needed when calling the `entry_point` macro. - -```python -load("@pip_deps//:requirements.bzl", "entry_point") +load("@pip_deps//:requirements.bzl", "install_deps") -alias( - name = "flake8", - actual = entry_point("flake8"), -) +install_deps() ``` @@ -154,7 +104,7 @@ alias( ## pip_parse
-pip_parse(requirements_lock, name, kwargs)
+pip_parse(requirements, requirements_lock, name, kwargs)
 
Accepts a locked/compiled requirements file and installs the dependencies listed within. @@ -247,7 +197,8 @@ See the example in rules_python/examples/pip_parse_vendored. | Name | Description | Default Value | | :-------------: | :-------------: | :-------------: | -| requirements_lock | A fully resolved 'requirements.txt' pip requirement file containing the transitive set of your dependencies. If this file is passed instead of 'requirements' no resolve will take place and pip_repository will create individual repositories for each of your dependencies so that wheels are fetched/built only for the targets specified by 'build/run/test'. Note that if your lockfile is platform-dependent, you can use the requirements_[platform] attributes. | none | +| requirements | Deprecated. See requirements_lock. | None | +| requirements_lock | A fully resolved 'requirements.txt' pip requirement file containing the transitive set of your dependencies. If this file is passed instead of 'requirements' no resolve will take place and pip_repository will create individual repositories for each of your dependencies so that wheels are fetched/built only for the targets specified by 'build/run/test'. Note that if your lockfile is platform-dependent, you can use the requirements_[platform] attributes. | None | | name | The name of the generated repository. The generated repositories containing each requirement will be of the form <name>_<requirement-name>. | "pip_parsed_deps" | | kwargs | Additional arguments to the [pip_repository](./pip_repository.md) repository rule. | none | diff --git a/docs/pip_repository.md b/docs/pip_repository.md index c66d8bfd91..875ea117f0 100644 --- a/docs/pip_repository.md +++ b/docs/pip_repository.md @@ -6,9 +6,9 @@
 pip_repository(name, annotations, download_only, enable_implicit_namespace_pkgs, environment,
-               extra_pip_args, incremental, isolated, pip_data_exclude, python_interpreter,
-               python_interpreter_target, quiet, repo_prefix, requirements, requirements_darwin,
-               requirements_linux, requirements_lock, requirements_windows, timeout)
+               extra_pip_args, isolated, pip_data_exclude, python_interpreter,
+               python_interpreter_target, quiet, repo_prefix, requirements_darwin, requirements_linux,
+               requirements_lock, requirements_windows, timeout)
 
A rule for importing `requirements.txt` dependencies into Bazel. @@ -62,14 +62,12 @@ py_binary( | enable_implicit_namespace_pkgs | If true, disables conversion of native namespace packages into pkg-util style namespace packages. When set all py_binary and py_test targets must specify either legacy_create_init=False or the global Bazel option --incompatible_default_to_explicit_init_py to prevent __init__.py being automatically generated in every directory.

This option is required to support some packages which cannot handle the conversion to pkg-util style. | Boolean | optional | False | | environment | Environment variables to set in the pip subprocess. Can be used to set common variables such as http_proxy, https_proxy and no_proxy Note that pip is run with "--isolated" on the CLI so PIP_<VAR>_<NAME> style env vars are ignored, but env vars that control requests and urllib3 can be passed. | Dictionary: String -> String | optional | {} | | extra_pip_args | Extra arguments to pass on to pip. Must not contain spaces. | List of strings | optional | [] | -| incremental | Create the repository in incremental mode. | Boolean | optional | False | | isolated | Whether or not to pass the [--isolated](https://pip.pypa.io/en/stable/cli/pip/#cmdoption-isolated) flag to the underlying pip command. Alternatively, the RULES_PYTHON_PIP_ISOLATED enviornment varaible can be used to control this flag. | Boolean | optional | True | | pip_data_exclude | Additional data exclusion parameters to add to the pip packages BUILD file. | List of strings | optional | [] | | python_interpreter | The python interpreter to use. This can either be an absolute path or the name of a binary found on the host's PATH environment variable. If no value is set python3 is defaulted for Unix systems and python.exe for Windows. | String | optional | "" | | python_interpreter_target | If you are using a custom python interpreter built by another repository rule, use this attribute to specify its BUILD target. This allows pip_repository to invoke pip using the same interpreter as your toolchain. If set, takes precedence over python_interpreter. | Label | optional | None | | quiet | If True, suppress printing stdout and stderr output to the terminal. | Boolean | optional | True | -| repo_prefix | Prefix for the generated packages. For non-incremental mode the packages will be of the form

@<name>//<prefix><sanitized-package-name>/...

For incremental mode the packages will be of the form

@<prefix><sanitized-package-name>//... | String | optional | "" | -| requirements | A 'requirements.txt' pip requirements file. | Label | optional | None | +| repo_prefix | Prefix for the generated packages will be of the form

@<prefix><sanitized-package-name>//... | String | optional | "" | | requirements_darwin | Override the requirements_lock attribute when the host platform is Mac OS | Label | optional | None | | requirements_linux | Override the requirements_lock attribute when the host platform is Linux | Label | optional | None | | requirements_lock | A fully resolved 'requirements.txt' pip requirement file containing the transitive set of your dependencies. If this file is passed instead of 'requirements' no resolve will take place and pip_repository will create individual repositories for each of your dependencies so that wheels are fetched/built only for the targets specified by 'build/run/test'. | Label | optional | None | @@ -108,7 +106,7 @@ Instantiated from pip_repository and inherits config options from there. | python_interpreter_target | If you are using a custom python interpreter built by another repository rule, use this attribute to specify its BUILD target. This allows pip_repository to invoke pip using the same interpreter as your toolchain. If set, takes precedence over python_interpreter. | Label | optional | None | | quiet | If True, suppress printing stdout and stderr output to the terminal. | Boolean | optional | True | | repo | Pointer to parent repo name. Used to make these rules rerun if the parent repo changes. | String | required | | -| repo_prefix | Prefix for the generated packages. For non-incremental mode the packages will be of the form

@<name>//<prefix><sanitized-package-name>/...

For incremental mode the packages will be of the form

@<prefix><sanitized-package-name>//... | String | optional | "" | +| repo_prefix | Prefix for the generated packages will be of the form

@<prefix><sanitized-package-name>//... | String | optional | "" | | requirement | Python requirement string describing the package to make available | String | required | | | timeout | Timeout (in seconds) on the rule's execution duration. | Integer | optional | 600 | diff --git a/examples/BUILD b/examples/BUILD index 41dd87505a..ee4d7e4861 100644 --- a/examples/BUILD +++ b/examples/BUILD @@ -38,11 +38,6 @@ bazel_integration_test( timeout = "long", ) -bazel_integration_test( - name = "relative_requirements_example", - timeout = "long", -) - bazel_integration_test( name = "bzlmod_example", ) diff --git a/examples/pip_install/BUILD b/examples/pip_install/BUILD index ad983b2f54..35f5a9338a 100644 --- a/examples/pip_install/BUILD +++ b/examples/pip_install/BUILD @@ -88,9 +88,9 @@ py_test( genquery( name = "yamllint_lib_by_version", expression = """ - attr("tags", "\\bpypi_version=1.26.3\\b", "@pip//pypi__yamllint") + attr("tags", "\\bpypi_version=1.26.3\\b", "@pip_yamllint//:pkg") intersect - attr("tags", "\\bpypi_name=yamllint\\b", "@pip//pypi__yamllint") + attr("tags", "\\bpypi_name=yamllint\\b", "@pip_yamllint//:pkg") """, scope = [requirement("yamllint")], ) @@ -99,7 +99,7 @@ write_file( name = "write_expected", out = "expected", content = [ - "@pip//pypi__yamllint:pypi__yamllint", + "@pip_yamllint//:pkg", "", ], ) diff --git a/examples/pip_install/WORKSPACE b/examples/pip_install/WORKSPACE index 0b33a2b390..f63d928013 100644 --- a/examples/pip_install/WORKSPACE +++ b/examples/pip_install/WORKSPACE @@ -57,6 +57,11 @@ pip_install( requirements = "//:requirements.txt", ) +load("@pip//:requirements.bzl", "install_deps") + +# Initialize repositories for all packages in requirements.txt. +install_deps() + # You could optionally use an in-build, compiled python interpreter as a toolchain, # and also use it to execute pip. # diff --git a/examples/pip_install/pip_install_test.py b/examples/pip_install/pip_install_test.py index 6092768da6..9fe51fa3a4 100644 --- a/examples/pip_install/pip_install_test.py +++ b/examples/pip_install/pip_install_test.py @@ -37,11 +37,11 @@ def test_data(self): self.assertListEqual( env.split(" "), [ - "external/pip/pypi__s3cmd/data/share/doc/packages/s3cmd/INSTALL.md", - "external/pip/pypi__s3cmd/data/share/doc/packages/s3cmd/LICENSE", - "external/pip/pypi__s3cmd/data/share/doc/packages/s3cmd/NEWS", - "external/pip/pypi__s3cmd/data/share/doc/packages/s3cmd/README.md", - "external/pip/pypi__s3cmd/data/share/man/man1/s3cmd.1", + "external/pip_s3cmd/data/share/doc/packages/s3cmd/INSTALL.md", + "external/pip_s3cmd/data/share/doc/packages/s3cmd/LICENSE", + "external/pip_s3cmd/data/share/doc/packages/s3cmd/NEWS", + "external/pip_s3cmd/data/share/doc/packages/s3cmd/README.md", + "external/pip_s3cmd/data/share/man/man1/s3cmd.1", ], ) @@ -51,13 +51,13 @@ def test_dist_info(self): self.assertListEqual( env.split(" "), [ - "external/pip/pypi__boto3/site-packages/boto3-1.14.51.dist-info/DESCRIPTION.rst", - "external/pip/pypi__boto3/site-packages/boto3-1.14.51.dist-info/INSTALLER", - "external/pip/pypi__boto3/site-packages/boto3-1.14.51.dist-info/METADATA", - "external/pip/pypi__boto3/site-packages/boto3-1.14.51.dist-info/RECORD", - "external/pip/pypi__boto3/site-packages/boto3-1.14.51.dist-info/WHEEL", - "external/pip/pypi__boto3/site-packages/boto3-1.14.51.dist-info/metadata.json", - "external/pip/pypi__boto3/site-packages/boto3-1.14.51.dist-info/top_level.txt", + "external/pip_boto3/site-packages/boto3-1.14.51.dist-info/DESCRIPTION.rst", + "external/pip_boto3/site-packages/boto3-1.14.51.dist-info/INSTALLER", + "external/pip_boto3/site-packages/boto3-1.14.51.dist-info/METADATA", + "external/pip_boto3/site-packages/boto3-1.14.51.dist-info/RECORD", + "external/pip_boto3/site-packages/boto3-1.14.51.dist-info/WHEEL", + "external/pip_boto3/site-packages/boto3-1.14.51.dist-info/metadata.json", + "external/pip_boto3/site-packages/boto3-1.14.51.dist-info/top_level.txt", ], ) diff --git a/examples/pip_repository_annotations/BUILD b/examples/pip_repository_annotations/BUILD index 8c69c40aff..4fd124e6c7 100644 --- a/examples/pip_repository_annotations/BUILD +++ b/examples/pip_repository_annotations/BUILD @@ -27,7 +27,7 @@ py_test( py_test( name = "pip_install_annotations_test", srcs = ["pip_repository_annotations_test.py"], - env = {"WHEEL_PKG_DIR": "pip_installed/pypi__wheel"}, + env = {"WHEEL_PKG_DIR": "pip_installed_wheel"}, main = "pip_repository_annotations_test.py", deps = [ requirement("wheel"), diff --git a/examples/pip_repository_annotations/WORKSPACE b/examples/pip_repository_annotations/WORKSPACE index 8ee885d468..aeea84207c 100644 --- a/examples/pip_repository_annotations/WORKSPACE +++ b/examples/pip_repository_annotations/WORKSPACE @@ -54,9 +54,9 @@ pip_parse( requirements_lock = "//:requirements.txt", ) -load("@pip_parsed//:requirements.bzl", "install_deps") +load("@pip_parsed//:requirements.bzl", install_pip_parse_deps = "install_deps") -install_deps() +install_pip_parse_deps() # For a more thorough example of `pip_install`. See `@rules_python//examples/pip_install` pip_install( @@ -65,3 +65,7 @@ pip_install( python_interpreter_target = interpreter, requirements = "//:requirements.txt", ) + +load("@pip_installed//:requirements.bzl", install_pip_install_deps = "install_deps") + +install_pip_install_deps() diff --git a/examples/relative_requirements/BUILD b/examples/relative_requirements/BUILD deleted file mode 100644 index d24ee5f72b..0000000000 --- a/examples/relative_requirements/BUILD +++ /dev/null @@ -1,10 +0,0 @@ -load("@pip//:requirements.bzl", "requirement") -load("@rules_python//python:defs.bzl", "py_test") - -py_test( - name = "main", - srcs = ["main.py"], - deps = [ - requirement("relative_package_name"), - ], -) diff --git a/examples/relative_requirements/README.md b/examples/relative_requirements/README.md deleted file mode 100644 index 4b9258e370..0000000000 --- a/examples/relative_requirements/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# relative_requirements example - -This example shows how to use pip to fetch relative dependencies from a requirements.txt file, -then use them in BUILD files as dependencies of Bazel targets. diff --git a/examples/relative_requirements/WORKSPACE b/examples/relative_requirements/WORKSPACE deleted file mode 100644 index 4ae91c39d8..0000000000 --- a/examples/relative_requirements/WORKSPACE +++ /dev/null @@ -1,21 +0,0 @@ -workspace(name = "example_repo") - -local_repository( - name = "rules_python", - path = "../..", -) - -load("@rules_python//python:repositories.bzl", "python_register_toolchains") - -python_register_toolchains( - name = "python39", - python_version = "3.9", -) - -load("@python39//:defs.bzl", "interpreter") -load("@rules_python//python:pip.bzl", "pip_install") - -pip_install( - python_interpreter_target = interpreter, - requirements = "//:requirements.txt", -) diff --git a/examples/relative_requirements/main.py b/examples/relative_requirements/main.py deleted file mode 100644 index b8ac021e90..0000000000 --- a/examples/relative_requirements/main.py +++ /dev/null @@ -1,5 +0,0 @@ -import relative_package_name - -if __name__ == "__main__": - # Run a function from the relative package - print(relative_package_name.test()) diff --git a/examples/relative_requirements/relative_package/relative_package_name/__init__.py b/examples/relative_requirements/relative_package/relative_package_name/__init__.py deleted file mode 100644 index c031192907..0000000000 --- a/examples/relative_requirements/relative_package/relative_package_name/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -def test(): - return True diff --git a/examples/relative_requirements/relative_package/setup.py b/examples/relative_requirements/relative_package/setup.py deleted file mode 100644 index 052b519345..0000000000 --- a/examples/relative_requirements/relative_package/setup.py +++ /dev/null @@ -1,7 +0,0 @@ -from setuptools import setup - -setup( - name="relative_package_name", - version="1.0.0", - packages=["relative_package_name"], -) diff --git a/examples/relative_requirements/requirements.txt b/examples/relative_requirements/requirements.txt deleted file mode 100644 index 9a81317e1e..0000000000 --- a/examples/relative_requirements/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -./relative_package diff --git a/python/pip.bzl b/python/pip.bzl index 954317f4b7..dfafefe38d 100644 --- a/python/pip.bzl +++ b/python/pip.bzl @@ -21,69 +21,19 @@ compile_pip_requirements = _compile_pip_requirements package_annotation = _package_annotation def pip_install(requirements = None, name = "pip", **kwargs): - """Accepts a `requirements.txt` file and installs the dependencies listed within. - - Those dependencies become available in a generated `requirements.bzl` file. - - This macro wraps the [`pip_repository`](./pip_repository.md) rule that invokes `pip`. - In your WORKSPACE file: + """Accepts a locked/compiled requirements file and installs the dependencies listed within. ```python + load("@rules_python//python:pip.bzl", "pip_install") + pip_install( + name = "pip_deps", requirements = ":requirements.txt", ) - ``` - - You can then reference installed dependencies from a `BUILD` file with: - - ```python - load("@pip//:requirements.bzl", "requirement") - py_library( - name = "bar", - ... - deps = [ - "//my/other:dep", - requirement("requests"), - requirement("numpy"), - ], - ) - ``` - - > Note that this convenience comes with a cost. - > Analysis of any BUILD file which loads the requirements helper in this way will - > cause an eager-fetch of all the pip dependencies, - > even if no python targets are requested to be built. - > In a multi-language repo, this may cause developers to fetch dependencies they don't need, - > so consider using the long form for dependencies if this happens. - - In addition to the `requirement` macro, which is used to access the `py_library` - target generated from a package's wheel, the generated `requirements.bzl` file contains - functionality for exposing [entry points][whl_ep] as `py_binary` targets. - - [whl_ep]: https://packaging.python.org/specifications/entry-points/ - - ```python - load("@pip_deps//:requirements.bzl", "entry_point") - alias( - name = "pip-compile", - actual = entry_point( - pkg = "pip-tools", - script = "pip-compile", - ), - ) - ``` - - Note that for packages whose name and script are the same, only the name of the package - is needed when calling the `entry_point` macro. - - ```python - load("@pip_deps//:requirements.bzl", "entry_point") + load("@pip_deps//:requirements.bzl", "install_deps") - alias( - name = "flake8", - actual = entry_point("flake8"), - ) + install_deps() ``` Args: @@ -92,17 +42,11 @@ def pip_install(requirements = None, name = "pip", **kwargs): **kwargs (dict): Additional arguments to the [`pip_repository`](./pip_repository.md) repository rule. """ - # Just in case our dependencies weren't already fetched - pip_install_dependencies() - - pip_repository( - name = name, - requirements = requirements, - repo_prefix = "pypi__", - **kwargs - ) + # buildifier: disable=print + print("pip_install is deprecated. Please switch to pip_parse. pip_install will be removed in a future release.") + pip_parse(requirements = requirements, name = name, **kwargs) -def pip_parse(requirements_lock, name = "pip_parsed_deps", **kwargs): +def pip_parse(requirements = None, requirements_lock = None, name = "pip_parsed_deps", **kwargs): """Accepts a locked/compiled requirements file and installs the dependencies listed within. Those dependencies become available in a generated `requirements.bzl` file. @@ -195,6 +139,7 @@ def pip_parse(requirements_lock, name = "pip_parsed_deps", **kwargs): fetched/built only for the targets specified by 'build/run/test'. Note that if your lockfile is platform-dependent, you can use the `requirements_[platform]` attributes. + requirements (Label): Deprecated. See requirements_lock. name (str, optional): The name of the generated repository. The generated repositories containing each requirement will be of the form _. **kwargs (dict): Additional arguments to the [`pip_repository`](./pip_repository.md) repository rule. @@ -203,10 +148,14 @@ def pip_parse(requirements_lock, name = "pip_parsed_deps", **kwargs): # Just in case our dependencies weren't already fetched pip_install_dependencies() + # Temporary compatibility shim. + # pip_install was previously document to use requirements while pip_parse was using requirements_lock. + # We would prefer everyone move to using requirements_lock, but we maintain a temporary shim. + reqs_to_use = requirements_lock if requirements_lock else requirements + pip_repository( name = name, - requirements_lock = requirements_lock, + requirements_lock = reqs_to_use, repo_prefix = "{}_".format(name), - incremental = True, **kwargs ) diff --git a/python/pip_install/extract_wheels/BUILD b/python/pip_install/extract_wheels/BUILD index 158d34ba27..bc11885026 100644 --- a/python/pip_install/extract_wheels/BUILD +++ b/python/pip_install/extract_wheels/BUILD @@ -9,7 +9,6 @@ py_library( "arguments.py", "bazel.py", "extract_single_wheel.py", - "extract_wheels.py", "namespace_pkgs.py", "parse_requirements_to_bzl.py", "requirements.py", @@ -21,14 +20,6 @@ py_library( ], ) -py_binary( - name = "extract_wheels", - srcs = [ - "extract_wheels.py", - ], - deps = [":lib"], -) - py_binary( name = "extract_single_wheel", srcs = [ diff --git a/python/pip_install/extract_wheels/extract_single_wheel.py b/python/pip_install/extract_wheels/extract_single_wheel.py index a7cc672a76..9c44effdd7 100644 --- a/python/pip_install/extract_wheels/extract_single_wheel.py +++ b/python/pip_install/extract_wheels/extract_single_wheel.py @@ -8,11 +8,32 @@ from python.pip_install.extract_wheels import arguments, bazel, requirements from python.pip_install.extract_wheels.annotation import annotation_from_str_path -from python.pip_install.extract_wheels.extract_wheels import ( - configure_reproducible_wheels, -) +def configure_reproducible_wheels() -> None: + """Modifies the environment to make wheel building reproducible. + Wheels created from sdists are not reproducible by default. We can however workaround this by + patching in some configuration with environment variables. + """ + + # wheel, by default, enables debug symbols in GCC. This incidentally captures the build path in the .so file + # We can override this behavior by disabling debug symbols entirely. + # https://github.com/pypa/pip/issues/6505 + if "CFLAGS" in os.environ: + os.environ["CFLAGS"] += " -g0" + else: + os.environ["CFLAGS"] = "-g0" + + # set SOURCE_DATE_EPOCH to 1980 so that we can use python wheels + # https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/python.section.md#python-setuppy-bdist_wheel-cannot-create-whl + if "SOURCE_DATE_EPOCH" not in os.environ: + os.environ["SOURCE_DATE_EPOCH"] = "315532800" + + # Python wheel metadata files can be unstable. + # See https://bitbucket.org/pypa/wheel/pull-requests/74/make-the-output-of-metadata-files/diff + if "PYTHONHASHSEED" not in os.environ: + os.environ["PYTHONHASHSEED"] = "0" + def main() -> None: parser = argparse.ArgumentParser( description="Build and/or fetch a single wheel based on the requirement passed in" diff --git a/python/pip_install/extract_wheels/extract_wheels.py b/python/pip_install/extract_wheels/extract_wheels.py deleted file mode 100644 index 2addaf89fd..0000000000 --- a/python/pip_install/extract_wheels/extract_wheels.py +++ /dev/null @@ -1,132 +0,0 @@ -"""extract_wheels - -extract_wheels resolves and fetches artifacts transitively from the Python Package Index (PyPI) based on a -requirements.txt. It generates the required BUILD files to consume these packages as Python libraries. - -Under the hood, it depends on the `pip wheel` command to do resolution, download, and compilation into wheels. -""" -import argparse -import glob -import os -import pathlib -import subprocess -import sys - -from python.pip_install.extract_wheels import ( - annotation, - arguments, - bazel, - requirements, - wheel, -) - - -def configure_reproducible_wheels() -> None: - """Modifies the environment to make wheel building reproducible. - - Wheels created from sdists are not reproducible by default. We can however workaround this by - patching in some configuration with environment variables. - """ - - # wheel, by default, enables debug symbols in GCC. This incidentally captures the build path in the .so file - # We can override this behavior by disabling debug symbols entirely. - # https://github.com/pypa/pip/issues/6505 - if "CFLAGS" in os.environ: - os.environ["CFLAGS"] += " -g0" - else: - os.environ["CFLAGS"] = "-g0" - - # set SOURCE_DATE_EPOCH to 1980 so that we can use python wheels - # https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/python.section.md#python-setuppy-bdist_wheel-cannot-create-whl - if "SOURCE_DATE_EPOCH" not in os.environ: - os.environ["SOURCE_DATE_EPOCH"] = "315532800" - - # Python wheel metadata files can be unstable. - # See https://bitbucket.org/pypa/wheel/pull-requests/74/make-the-output-of-metadata-files/diff - if "PYTHONHASHSEED" not in os.environ: - os.environ["PYTHONHASHSEED"] = "0" - - -def main() -> None: - """Main program. - - Exits zero on successful program termination, non-zero otherwise. - """ - - configure_reproducible_wheels() - - parser = argparse.ArgumentParser( - description="Resolve and fetch artifacts transitively from PyPI" - ) - parser.add_argument( - "--requirements", - action="store", - required=True, - help="Path to requirements.txt from where to install dependencies", - ) - parser.add_argument( - "--annotations", - type=annotation.annotations_map_from_str_path, - help="A json encoded file containing annotations for rendered packages.", - ) - arguments.parse_common_args(parser) - args = parser.parse_args() - deserialized_args = dict(vars(args)) - arguments.deserialize_structured_args(deserialized_args) - - # Pip is run with the working directory changed to the folder containing the requirements.txt file, to allow for - # relative requirements to be correctly resolved. The --wheel-dir is therefore required to be repointed back to the - # current calling working directory (the repo root in .../external/name), where the wheel files should be written to - pip_args = ( - [sys.executable, "-m", "pip"] - + (["--isolated"] if args.isolated else []) - + ["download" if args.download_only else "wheel", "-r", args.requirements] - + ["--wheel-dir", os.getcwd()] - + deserialized_args["extra_pip_args"] - ) - - env = os.environ.copy() - env.update(deserialized_args["environment"]) - - # Assumes any errors are logged by pip so do nothing. This command will fail if pip fails - subprocess.run( - pip_args, - check=True, - env=env, - cwd=str(pathlib.Path(args.requirements).parent.resolve()), - ) - - extras = requirements.parse_extras(args.requirements) - - repo_label = "@%s" % args.repo - - # Locate all wheels - wheels = [whl for whl in glob.glob("*.whl")] - - # Collect all annotations - reqs = {whl: wheel.Wheel(whl).name for whl in wheels} - annotations = args.annotations.collect(reqs.values()) - - targets = [ - '"{}{}"'.format( - repo_label, - bazel.extract_wheel( - wheel_file=whl, - extras=extras, - pip_data_exclude=deserialized_args["pip_data_exclude"], - enable_implicit_namespace_pkgs=args.enable_implicit_namespace_pkgs, - repo_prefix=args.repo_prefix, - annotation=annotations.get(name), - ), - ) - for whl, name in reqs.items() - ] - - with open("requirements.bzl", "w") as requirement_file: - requirement_file.write( - bazel.generate_requirements_file_contents(repo_label, targets) - ) - - -if __name__ == "__main__": - main() diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl index d729ae91b5..bc7da738ad 100644 --- a/python/pip_install/pip_repository.bzl +++ b/python/pip_install/pip_repository.bzl @@ -222,8 +222,7 @@ def _locked_requirements(rctx): requirements_txt = rctx.attr.requirements_windows if not requirements_txt: fail("""\ -Incremental mode requires a requirements_lock attribute be specified, -or a platform-specific lockfile using one of the requirements_* attributes. +A requirements_lock attribute must be specified, or a platform-specific lockfile using one of the requirements_* attributes. """) return requirements_txt @@ -235,40 +234,28 @@ def _pip_repository_impl(rctx): annotations_file = rctx.path("annotations.json") rctx.file(annotations_file, json.encode_indent(annotations, indent = " " * 4)) - if rctx.attr.incremental: - requirements_txt = _locked_requirements(rctx) - args = [ - python_interpreter, - "-m", - "python.pip_install.extract_wheels.parse_requirements_to_bzl", - "--requirements_lock", - rctx.path(requirements_txt), - "--requirements_lock_label", - str(requirements_txt), - # pass quiet and timeout args through to child repos. - "--quiet", - str(rctx.attr.quiet), - "--timeout", - str(rctx.attr.timeout), - "--annotations", - annotations_file, - ] + requirements_txt = _locked_requirements(rctx) + args = [ + python_interpreter, + "-m", + "python.pip_install.extract_wheels.parse_requirements_to_bzl", + "--requirements_lock", + rctx.path(requirements_txt), + "--requirements_lock_label", + str(requirements_txt), + # pass quiet and timeout args through to child repos. + "--quiet", + str(rctx.attr.quiet), + "--timeout", + str(rctx.attr.timeout), + "--annotations", + annotations_file, + ] - args += ["--python_interpreter", _get_python_interpreter_attr(rctx)] - if rctx.attr.python_interpreter_target: - args += ["--python_interpreter_target", str(rctx.attr.python_interpreter_target)] - progress_message = "Parsing requirements to starlark" - else: - args = [ - python_interpreter, - "-m", - "python.pip_install.extract_wheels.extract_wheels", - "--requirements", - rctx.path(rctx.attr.requirements), - "--annotations", - annotations_file, - ] - progress_message = "Extracting wheels" + args += ["--python_interpreter", _get_python_interpreter_attr(rctx)] + if rctx.attr.python_interpreter_target: + args += ["--python_interpreter_target", str(rctx.attr.python_interpreter_target)] + progress_message = "Parsing requirements to starlark" args += ["--repo", rctx.attr.name, "--repo-prefix", rctx.attr.repo_prefix] args = _parse_optional_attrs(rctx, args) @@ -361,12 +348,7 @@ python_interpreter. ), "repo_prefix": attr.string( doc = """ -Prefix for the generated packages. For non-incremental mode the -packages will be of the form - -@///... - -For incremental mode the packages will be of the form +Prefix for the generated packages will be of the form @//... """, @@ -387,14 +369,6 @@ pip_repository_attrs = { "annotations": attr.string_dict( doc = "Optional annotations to apply to packages", ), - "incremental": attr.bool( - default = False, - doc = "Create the repository in incremental mode.", - ), - "requirements": attr.label( - allow_single_file = True, - doc = "A 'requirements.txt' pip requirements file.", - ), "requirements_darwin": attr.label( allow_single_file = True, doc = "Override the requirements_lock attribute when the host platform is Mac OS", diff --git a/python/pip_install/private/srcs.bzl b/python/pip_install/private/srcs.bzl index bdd76b17d4..e42bb8e5ed 100644 --- a/python/pip_install/private/srcs.bzl +++ b/python/pip_install/private/srcs.bzl @@ -12,7 +12,6 @@ PIP_INSTALL_PY_SRCS = [ "@rules_python//python/pip_install/extract_wheels:arguments.py", "@rules_python//python/pip_install/extract_wheels:bazel.py", "@rules_python//python/pip_install/extract_wheels:extract_single_wheel.py", - "@rules_python//python/pip_install/extract_wheels:extract_wheels.py", "@rules_python//python/pip_install/extract_wheels:namespace_pkgs.py", "@rules_python//python/pip_install/extract_wheels:parse_requirements_to_bzl.py", "@rules_python//python/pip_install/extract_wheels:requirements.py", diff --git a/tests/pip_repository_entry_points/WORKSPACE b/tests/pip_repository_entry_points/WORKSPACE index 07a5d3aad0..dd80db47fa 100644 --- a/tests/pip_repository_entry_points/WORKSPACE +++ b/tests/pip_repository_entry_points/WORKSPACE @@ -24,9 +24,9 @@ pip_parse( requirements_lock = "//:requirements.txt", ) -load("@pip_parsed//:requirements.bzl", "install_deps") +load("@pip_parsed//:requirements.bzl", install_pip_parse_deps = "install_deps") -install_deps() +install_pip_parse_deps() # For a more thorough example of `pip_install`. See `@rules_python//examples/pip_install` pip_install( @@ -34,3 +34,7 @@ pip_install( python_interpreter_target = interpreter, requirements = "//:requirements.txt", ) + +load("@pip_installed//:requirements.bzl", install_pip_install_deps = "install_deps") + +install_pip_install_deps() From b8d6b2f8584d7c4be633563c9e46bb5006275abb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20K=C3=A4ufler?= Date: Sun, 25 Sep 2022 13:09:21 +0200 Subject: [PATCH 034/234] Use bazel 5.3.1 (#837) --- .bazelversion | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bazelversion b/.bazelversion index 91ff57278e..c7cb1311a6 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1 +1 @@ -5.2.0 +5.3.1 From 62a4249ef4c3ab9908b6c9e11c2f91711bcde337 Mon Sep 17 00:00:00 2001 From: Greg Roodt Date: Mon, 26 Sep 2022 22:08:54 +1000 Subject: [PATCH 035/234] Use json.encode() (#838) --- python/pip_install/pip_repository.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl index bc7da738ad..97109460fc 100644 --- a/python/pip_install/pip_repository.bzl +++ b/python/pip_install/pip_repository.bzl @@ -160,7 +160,7 @@ def _parse_optional_attrs(rctx, args): if rctx.attr.extra_pip_args != None: args += [ "--extra_pip_args", - struct(arg = rctx.attr.extra_pip_args).to_json(), + json.encode(struct(arg = rctx.attr.extra_pip_args)), ] if rctx.attr.download_only: @@ -169,7 +169,7 @@ def _parse_optional_attrs(rctx, args): if rctx.attr.pip_data_exclude != None: args += [ "--pip_data_exclude", - struct(arg = rctx.attr.pip_data_exclude).to_json(), + json.encode(struct(arg = rctx.attr.pip_data_exclude)), ] if rctx.attr.enable_implicit_namespace_pkgs: @@ -178,7 +178,7 @@ def _parse_optional_attrs(rctx, args): if rctx.attr.environment != None: args += [ "--environment", - struct(arg = rctx.attr.environment).to_json(), + json.encode(struct(arg = rctx.attr.environment)), ] return args From cdd275856d513b017606312622767a873eae6d13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20K=C3=A4ufler?= Date: Mon, 26 Sep 2022 21:37:07 +0200 Subject: [PATCH 036/234] Revert "Use bazel 5.3.1" (#842) --- .bazelversion | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bazelversion b/.bazelversion index c7cb1311a6..91ff57278e 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1 +1 @@ -5.3.1 +5.2.0 From 0e44ffa17b096cbda07878f98adfbd7000728046 Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Tue, 30 Aug 2022 20:41:57 -0700 Subject: [PATCH 037/234] Fixed unsound issue in wheel examples --- examples/wheel/BUILD | 13 ++++--- examples/wheel/private/BUILD | 7 ++++ examples/wheel/private/directory_writer.py | 44 ++++++++++++++++++++++ examples/wheel/private/wheel_utils.bzl | 42 +++++++++++++++++++++ 4 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 examples/wheel/private/BUILD create mode 100644 examples/wheel/private/directory_writer.py create mode 100644 examples/wheel/private/wheel_utils.bzl diff --git a/examples/wheel/BUILD b/examples/wheel/BUILD index f745dc31ca..28268b53de 100644 --- a/examples/wheel/BUILD +++ b/examples/wheel/BUILD @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +load("//examples/wheel/private:wheel_utils.bzl", "directory_writer") load("//python:defs.bzl", "py_library", "py_test") load("//python:packaging.bzl", "py_package", "py_wheel") load("//python:versions.bzl", "gen_python_config_settings") @@ -40,10 +41,10 @@ py_library( ], ) -genrule( +directory_writer( name = "gen_dir", - outs = ["someDir"], - cmd = "mkdir -p $@ && touch $@/foo.py", + out = "someDir", + files = {"foo.py": ""}, ) # Package just a specific py_libraries, without their dependencies @@ -188,8 +189,8 @@ py_wheel( ) py_wheel( - name = "use_genrule_with_dir_in_outs", - distribution = "use_genrule_with_dir_in_outs", + name = "use_rule_with_dir_in_outs", + distribution = "use_rule_with_dir_in_outs", python_tag = "py3", version = "0.0.1", deps = [ @@ -240,6 +241,6 @@ py_test( ":minimal_with_py_package", ":python_abi3_binary_wheel", ":python_requires_in_a_package", - ":use_genrule_with_dir_in_outs", + ":use_rule_with_dir_in_outs", ], ) diff --git a/examples/wheel/private/BUILD b/examples/wheel/private/BUILD new file mode 100644 index 0000000000..3462d354d4 --- /dev/null +++ b/examples/wheel/private/BUILD @@ -0,0 +1,7 @@ +load("@rules_python//python:defs.bzl", "py_binary") + +py_binary( + name = "directory_writer", + srcs = ["directory_writer.py"], + visibility = ["//:__subpackages__"], +) diff --git a/examples/wheel/private/directory_writer.py b/examples/wheel/private/directory_writer.py new file mode 100644 index 0000000000..dd604c671e --- /dev/null +++ b/examples/wheel/private/directory_writer.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +"""The action executable of the `@rules_python//examples/wheel/private:wheel_utils.bzl%directory_writer` rule.""" + +import argparse +import json +from pathlib import Path +from typing import Tuple + + +def _file_input(value) -> Tuple[Path, str]: + path, content = value.split("=", maxsplit=1) + return (Path(path), json.loads(content)) + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser() + + parser.add_argument( + "--output", type=Path, required=True, help="The output directory to create." + ) + parser.add_argument( + "--file", + dest="files", + type=_file_input, + action="append", + help="Files to create within the `output` directory.", + ) + + return parser.parse_args() + + +def main() -> None: + args = parse_args() + + args.output.mkdir(parents=True, exist_ok=True) + + for (path, content) in args.files: + new_file = args.output / path + new_file.parent.mkdir(parents=True, exist_ok=True) + new_file.write_text(content) + + +if __name__ == "__main__": + main() diff --git a/examples/wheel/private/wheel_utils.bzl b/examples/wheel/private/wheel_utils.bzl new file mode 100644 index 0000000000..25ef9b4d8f --- /dev/null +++ b/examples/wheel/private/wheel_utils.bzl @@ -0,0 +1,42 @@ +"""Helper rules for demonstrating `py_wheel` examples""" + +def _directory_writer_impl(ctx): + output = ctx.actions.declare_directory(ctx.attr.out) + + args = ctx.actions.args() + args.add("--output", output.path) + + for path, content in ctx.attr.files.items(): + args.add("--file={}={}".format( + path, + json.encode(content), + )) + + ctx.actions.run( + outputs = [output], + arguments = [args], + executable = ctx.executable._writer, + ) + + return [DefaultInfo( + files = depset([output]), + runfiles = ctx.runfiles(files = [output]), + )] + +directory_writer = rule( + implementation = _directory_writer_impl, + doc = "A rule for generating a directory with the requested content.", + attrs = { + "files": attr.string_dict( + doc = "A mapping of file name to content to create relative to the generated `out` directory.", + ), + "out": attr.string( + doc = "The name of the directory to create", + ), + "_writer": attr.label( + executable = True, + cfg = "exec", + default = Label("//examples/wheel/private:directory_writer"), + ), + }, +) From f0e4743a828d0a41a1a8f99c590fad13df66ac46 Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Tue, 30 Aug 2022 20:42:22 -0700 Subject: [PATCH 038/234] Fixed deprecation warnings in //examples/wheel tests --- examples/wheel/wheel_test.py | 42 ++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/examples/wheel/wheel_test.py b/examples/wheel/wheel_test.py index 8200e54cfd..d17cdef3f3 100644 --- a/examples/wheel/wheel_test.py +++ b/examples/wheel/wheel_test.py @@ -29,7 +29,7 @@ def test_py_library_wheel(self): "example_minimal_library-0.0.1-py3-none-any.whl", ) with zipfile.ZipFile(filename) as zf: - self.assertEquals( + self.assertEqual( zf.namelist(), [ "examples/wheel/lib/module_with_data.py", @@ -49,7 +49,7 @@ def test_py_package_wheel(self): "example_minimal_package-0.0.1-py3-none-any.whl", ) with zipfile.ZipFile(filename) as zf: - self.assertEquals( + self.assertEqual( zf.namelist(), [ "examples/wheel/lib/data.txt", @@ -71,7 +71,7 @@ def test_customized_wheel(self): "example_customized-0.0.1-py3-none-any.whl", ) with zipfile.ZipFile(filename) as zf: - self.assertEquals( + self.assertEqual( zf.namelist(), [ "examples/wheel/lib/data.txt", @@ -92,7 +92,7 @@ def test_customized_wheel(self): ) # The entries are guaranteed to be sorted. if platform.system() == "Windows": - self.assertEquals( + self.assertEqual( record_contents, b"""\ example_customized-0.0.1.dist-info/METADATA,sha256=pzE96o3Sp63TDzxAZgl0F42EFevm8x15vpDLqDVp_EQ,378 @@ -106,7 +106,7 @@ def test_customized_wheel(self): """, ) else: - self.assertEquals( + self.assertEqual( record_contents, b"""\ example_customized-0.0.1.dist-info/METADATA,sha256=TeeEmokHE2NWjkaMcVJuSAq4_AXUoIad2-SLuquRmbg,372 @@ -119,7 +119,7 @@ def test_customized_wheel(self): examples/wheel/main.py,sha256=sgg5iWN_9inYBjm6_Zw27hYdmo-l24fA-2rfphT-IlY,909 """, ) - self.assertEquals( + self.assertEqual( wheel_contents, b"""\ Wheel-Version: 1.0 @@ -129,7 +129,7 @@ def test_customized_wheel(self): """, ) if platform.system() == "Windows": - self.assertEquals( + self.assertEqual( metadata_contents, b"""\ Metadata-Version: 2.1 @@ -147,7 +147,7 @@ def test_customized_wheel(self): """, ) else: - self.assertEquals( + self.assertEqual( metadata_contents, b"""\ Metadata-Version: 2.1 @@ -164,7 +164,7 @@ def test_customized_wheel(self): This is a sample description of a wheel. """, ) - self.assertEquals( + self.assertEqual( entry_point_contents, b"""\ [console_scripts] @@ -185,7 +185,7 @@ def test_filename_escaping(self): "file_name_escaping-0.0.1_r7-py3-none-any.whl", ) with zipfile.ZipFile(filename) as zf: - self.assertEquals( + self.assertEqual( zf.namelist(), [ "examples/wheel/lib/data.txt", @@ -203,7 +203,7 @@ def test_filename_escaping(self): metadata_contents = zf.read( "file_name_escaping-0.0.1_r7.dist-info/METADATA" ) - self.assertEquals( + self.assertEqual( metadata_contents, b"""\ Metadata-Version: 2.1 @@ -224,7 +224,7 @@ def test_custom_package_root_wheel(self): ) with zipfile.ZipFile(filename) as zf: - self.assertEquals( + self.assertEqual( zf.namelist(), [ "wheel/lib/data.txt", @@ -256,7 +256,7 @@ def test_custom_package_root_multi_prefix_wheel(self): ) with zipfile.ZipFile(filename) as zf: - self.assertEquals( + self.assertEqual( zf.namelist(), [ "data.txt", @@ -287,7 +287,7 @@ def test_custom_package_root_multi_prefix_reverse_order_wheel(self): ) with zipfile.ZipFile(filename) as zf: - self.assertEquals( + self.assertEqual( zf.namelist(), [ "lib/data.txt", @@ -321,7 +321,7 @@ def test_python_requires_wheel(self): "example_python_requires_in_a_package-0.0.1.dist-info/METADATA" ) # The entries are guaranteed to be sorted. - self.assertEquals( + self.assertEqual( metadata_contents, b"""\ Metadata-Version: 2.1 @@ -380,24 +380,24 @@ def test_python_abi3_binary_wheel(self): """, ) - def test_genrule_creates_directory_and_is_included_in_wheel(self): + def test_rule_creates_directory_and_is_included_in_wheel(self): filename = os.path.join( os.environ["TEST_SRCDIR"], "rules_python", "examples", "wheel", - "use_genrule_with_dir_in_outs-0.0.1-py3-none-any.whl", + "use_rule_with_dir_in_outs-0.0.1-py3-none-any.whl", ) with zipfile.ZipFile(filename) as zf: - self.assertEquals( + self.assertEqual( zf.namelist(), [ "examples/wheel/main.py", "examples/wheel/someDir/foo.py", - "use_genrule_with_dir_in_outs-0.0.1.dist-info/WHEEL", - "use_genrule_with_dir_in_outs-0.0.1.dist-info/METADATA", - "use_genrule_with_dir_in_outs-0.0.1.dist-info/RECORD", + "use_rule_with_dir_in_outs-0.0.1.dist-info/WHEEL", + "use_rule_with_dir_in_outs-0.0.1.dist-info/METADATA", + "use_rule_with_dir_in_outs-0.0.1.dist-info/RECORD", ], ) From 2f764ce1bdf11cc571643c1a145471890e4b2aa0 Mon Sep 17 00:00:00 2001 From: UebelAndre Date: Tue, 30 Aug 2022 09:22:09 -0700 Subject: [PATCH 039/234] Add CI job for RBE. --- .bazelci/presubmit.yml | 21 +++++++++++++ WORKSPACE | 20 +++++++++++++ examples/wheel/wheel_test.py | 58 +++++++++++++++++++++++++++++++----- 3 files changed, 91 insertions(+), 8 deletions(-) diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 666654998b..e950d02c69 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -9,6 +9,8 @@ all_targets: &all_targets # As a regression test for #225, check that wheel targets still build when # their package path is qualified with the repo name. - "@rules_python//examples/wheel/..." + build_flags: + - "--keep_going" # We control Bazel version in integration tests, so we don't need USE_BAZEL_VERSION for tests. skip_use_bazel_version_for_test: true test_targets: @@ -41,3 +43,22 @@ platforms: - "-//tests:pip_repository_entry_points_example" test_flags: - "--test_tag_filters=-fix-windows" + rbe_ubuntu1604: + build_targets: + - "--" # Allows negative patterns; hack for https://github.com/bazelbuild/continuous-integration/pull/245 + - "..." + # We control Bazel version in integration tests, so we don't need USE_BAZEL_VERSION for tests. + skip_use_bazel_version_for_test: true + test_targets: + - "--" # Allows negative patterns; hack for https://github.com/bazelbuild/continuous-integration/pull/245 + - "..." + # TODO: The toolchain tests do not currently work in RBE + - "-//python/tests/toolchains/..." + # TODO: The integration tests do not currently work on RBE + # This list is the result of `bazel query 'filter(".*_example$", attr(generator_function, bazel_integration_test, //...))'` + - "-//examples:bzlmod_example" + - "-//examples:pip_install_example" + - "-//examples:pip_parse_example" + - "-//examples:pip_parse_vendored_example" + - "-//examples:pip_repository_annotations_example" + - "-//tests:pip_repository_entry_points_example" diff --git a/WORKSPACE b/WORKSPACE index b43a8d8e1d..ff1b956534 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -38,3 +38,23 @@ load("//gazelle:deps.bzl", "gazelle_deps") # gazelle:repository_macro gazelle/deps.bzl%gazelle_deps gazelle_deps() + +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +# Used for Bazel CI +http_archive( + name = "bazelci_rules", + sha256 = "eca21884e6f66a88c358e580fd67a6b148d30ab57b1680f62a96c00f9bc6a07e", + strip_prefix = "bazelci_rules-1.0.0", + url = "https://github.com/bazelbuild/continuous-integration/releases/download/rules-1.0.0/bazelci_rules-1.0.0.tar.gz", +) + +load("@bazelci_rules//:rbe_repo.bzl", "rbe_preconfig") + +# Creates a default toolchain config for RBE. +# Use this as is if you are using the rbe_ubuntu16_04 container, +# otherwise refer to RBE docs. +rbe_preconfig( + name = "buildkite_config", + toolchain = "ubuntu1804-bazel-java11", +) diff --git a/examples/wheel/wheel_test.py b/examples/wheel/wheel_test.py index d17cdef3f3..da217e954c 100644 --- a/examples/wheel/wheel_test.py +++ b/examples/wheel/wheel_test.py @@ -20,6 +20,8 @@ class WheelTest(unittest.TestCase): + maxDiff = None + def test_py_library_wheel(self): filename = os.path.join( os.environ["TEST_SRCDIR"], @@ -106,9 +108,20 @@ def test_customized_wheel(self): """, ) else: - self.assertEqual( - record_contents, - b"""\ + # TODO: The non-ascii characters in the METADATA file are interpreted differently on the + # ubuntu16_rbe hosts in comparison to other unix platforms. This should not be the case + # and the code should be updated to account for this. + rbe_expected_contents = b"""\ +example_customized-0.0.1.dist-info/METADATA,sha256=pzE96o3Sp63TDzxAZgl0F42EFevm8x15vpDLqDVp_EQ,378 +example_customized-0.0.1.dist-info/RECORD,, +example_customized-0.0.1.dist-info/WHEEL,sha256=sobxWSyDDkdg_rinUth-jxhXHqoNqlmNMJY3aTZn2Us,91 +example_customized-0.0.1.dist-info/entry_points.txt,sha256=pqzpbQ8MMorrJ3Jp0ntmpZcuvfByyqzMXXi2UujuXD0,137 +examples/wheel/lib/data.txt,sha256=9vJKEdfLu8bZRArKLroPZJh1XKkK3qFMXiM79MBL2Sg,12 +examples/wheel/lib/module_with_data.py,sha256=8s0Khhcqz3yVsBKv2IB5u4l4TMKh7-c_V6p65WVHPms,637 +examples/wheel/lib/simple_module.py,sha256=z2hwciab_XPNIBNH8B1Q5fYgnJvQTeYf0ZQJpY8yLLY,637 +examples/wheel/main.py,sha256=sgg5iWN_9inYBjm6_Zw27hYdmo-l24fA-2rfphT-IlY,909 +""" + unix_expected_contents = b"""\ example_customized-0.0.1.dist-info/METADATA,sha256=TeeEmokHE2NWjkaMcVJuSAq4_AXUoIad2-SLuquRmbg,372 example_customized-0.0.1.dist-info/RECORD,, example_customized-0.0.1.dist-info/WHEEL,sha256=sobxWSyDDkdg_rinUth-jxhXHqoNqlmNMJY3aTZn2Us,91 @@ -117,8 +130,15 @@ def test_customized_wheel(self): examples/wheel/lib/module_with_data.py,sha256=8s0Khhcqz3yVsBKv2IB5u4l4TMKh7-c_V6p65WVHPms,637 examples/wheel/lib/simple_module.py,sha256=z2hwciab_XPNIBNH8B1Q5fYgnJvQTeYf0ZQJpY8yLLY,637 examples/wheel/main.py,sha256=sgg5iWN_9inYBjm6_Zw27hYdmo-l24fA-2rfphT-IlY,909 -""", +""" + self.assertIn( + record_contents, + [ + rbe_expected_contents, + unix_expected_contents, + ], ) + self.assertEqual( wheel_contents, b"""\ @@ -147,9 +167,25 @@ def test_customized_wheel(self): """, ) else: - self.assertEqual( - metadata_contents, - b"""\ + # TODO: The non-ascii characters in the METADATA file are interpreted differently on the + # ubuntu16_rbe hosts in comparison to other unix platforms. This should not be the case + # and the code should be updated to account for this. + rbe_expected_contents = b"""\ +Metadata-Version: 2.1 +Name: example_customized +Version: 0.0.1 +Author: Example Author with non-ascii characters: \xc3\x85\xc2\xbc\xc3\x83\xc2\xb3\xc3\x85\xc2\x82w +Author-email: example@example.com +Home-page: www.example.com +License: Apache 2.0 +Classifier: License :: OSI Approved :: Apache Software License +Classifier: Intended Audience :: Developers +Requires-Dist: pytest + +This is a sample description of a wheel. +""" + + unix_expected_contents = b"""\ Metadata-Version: 2.1 Name: example_customized Version: 0.0.1 @@ -162,7 +198,13 @@ def test_customized_wheel(self): Requires-Dist: pytest This is a sample description of a wheel. -""", +""" + self.assertIn( + metadata_contents, + [ + rbe_expected_contents, + unix_expected_contents, + ], ) self.assertEqual( entry_point_contents, From 369074e3e5db5628c7e4ea8552e617f433258b6b Mon Sep 17 00:00:00 2001 From: James Fish Date: Wed, 28 Sep 2022 14:01:34 -0400 Subject: [PATCH 040/234] Add .bzl files explicitly to toolchain tests to detect .bzl file changes (#815) Co-authored-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- BUILD | 1 + python/tests/toolchains/defs.bzl | 10 +++++----- python/tests/toolchains/run_acceptance_test.py.tmpl | 7 +------ 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/BUILD b/BUILD index ebdf74e788..7ea2aa4070 100644 --- a/BUILD +++ b/BUILD @@ -39,6 +39,7 @@ filegroup( ], visibility = [ "//examples:__pkg__", + "//python/tests/toolchains:__pkg__", "//tests:__pkg__", ], ) diff --git a/python/tests/toolchains/defs.bzl b/python/tests/toolchains/defs.bzl index 8c07d23885..2abc1ed149 100644 --- a/python/tests/toolchains/defs.bzl +++ b/python/tests/toolchains/defs.bzl @@ -39,10 +39,6 @@ def _acceptance_test_impl(ctx): ) python_version_test = ctx.actions.declare_file("/".join([ctx.attr.python_version, "python_version_test.py"])) - - # With the current approach in the run_acceptance_test.sh, we use this - # symlink to find the absolute path to the rules_python to be passed to the - # --override_repository rules_python=. ctx.actions.symlink( target_file = ctx.file._python_version_test, output = python_version_test, @@ -92,7 +88,7 @@ def _acceptance_test_impl(ctx): python_version_test, run_acceptance_test_py, workspace, - ] + ] + ctx.files._distribution return [DefaultInfo( executable = executable, files = depset( @@ -126,6 +122,10 @@ _acceptance_test = rule( allow_single_file = True, default = Label("//python/tests/toolchains/workspace_template:BUILD.bazel.tmpl"), ), + "_distribution": attr.label( + doc = "The rules_python source distribution.", + default = Label("//:distribution"), + ), "_python_version_test": attr.label( doc = "The python_version_test.py used to test the Python version.", allow_single_file = True, diff --git a/python/tests/toolchains/run_acceptance_test.py.tmpl b/python/tests/toolchains/run_acceptance_test.py.tmpl index 51eba3da3f..b3071a7b3c 100644 --- a/python/tests/toolchains/run_acceptance_test.py.tmpl +++ b/python/tests/toolchains/run_acceptance_test.py.tmpl @@ -21,12 +21,7 @@ class TestPythonVersion(unittest.TestCase): @classmethod def setUpClass(cls): os.chdir("%test_location%") - python_version_test_dirname = os.path.dirname( - os.path.realpath("python_version_test.py") - ) - rules_python_path = os.path.normpath( - os.path.join(python_version_test_dirname, "..", "..", "..", "..") - ) + rules_python_path = os.path.join(os.environ["TEST_SRCDIR"], "rules_python") if %is_windows%: test_tmpdir = os.environ["TEST_TMPDIR"] From 301704b3dbc39f217ba469296dc9a695af2c760b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Stradomski?= <44680433+pstradomski@users.noreply.github.com> Date: Sat, 1 Oct 2022 18:20:47 +0200 Subject: [PATCH 041/234] Allow extra files to be added to distinfo directory within the wheel. (#831) * Allow extra files to be added to distinfo directory within the wheel. That would typically be LICENSE or similar files. Fixes issue #828. Co-authored-by: Greg Roodt --- docs/packaging.md | 5 +++-- examples/wheel/BUILD | 5 +++++ examples/wheel/NOTICE | 1 + examples/wheel/wheel_test.py | 8 ++++++++ python/packaging.bzl | 17 +++++++++++++++++ tools/wheelmaker.py | 29 +++++++++++++++++++++++++---- 6 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 examples/wheel/NOTICE diff --git a/docs/packaging.md b/docs/packaging.md index d3595c46be..6d063edbff 100755 --- a/docs/packaging.md +++ b/docs/packaging.md @@ -30,8 +30,8 @@ This rule is intended to be used as data dependency to py_wheel rule
 py_wheel(name, abi, author, author_email, classifiers, console_scripts, deps, description_file,
-         distribution, entry_points, extra_requires, homepage, license, platform, python_requires,
-         python_tag, requires, stamp, strip_path_prefixes, version)
+         distribution, entry_points, extra_distinfo_files, extra_requires, homepage, license,
+         platform, python_requires, python_tag, requires, stamp, strip_path_prefixes, version)
 
@@ -94,6 +94,7 @@ py_wheel( | description_file | A file containing text describing the package in a single line. | Label | optional | None | | distribution | Name of the distribution.

This should match the project name onm PyPI. It's also the name that is used to refer to the package in other packages' dependencies. | String | required | | | entry_points | entry_points, e.g. {'console_scripts': ['main = examples.wheel.main:main']}. | Dictionary: String -> List of strings | optional | {} | +| extra_distinfo_files | Extra files to add to distinfo directory in the archive. | Dictionary: Label -> String | optional | {} | | extra_requires | List of optional requirements for this package | Dictionary: String -> List of strings | optional | {} | | homepage | A string specifying the URL for the package homepage. | String | optional | "" | | license | A string specifying the license of the package. | String | optional | "" | diff --git a/examples/wheel/BUILD b/examples/wheel/BUILD index 28268b53de..2c572761cf 100644 --- a/examples/wheel/BUILD +++ b/examples/wheel/BUILD @@ -120,6 +120,11 @@ py_wheel( "first = first.main:f", ], }, + extra_distinfo_files = { + "//examples/wheel:NOTICE": "NOTICE", + # Rename the file when packaging to show we can. + "//examples/wheel:README.md": "README", + }, homepage = "www.example.com", license = "Apache 2.0", python_tag = "py3", diff --git a/examples/wheel/NOTICE b/examples/wheel/NOTICE new file mode 100644 index 0000000000..700336b8cf --- /dev/null +++ b/examples/wheel/NOTICE @@ -0,0 +1 @@ +This is a test "NOTICE" file to be packaged into distribtion dist-info dir. diff --git a/examples/wheel/wheel_test.py b/examples/wheel/wheel_test.py index da217e954c..0e495eb236 100644 --- a/examples/wheel/wheel_test.py +++ b/examples/wheel/wheel_test.py @@ -83,6 +83,8 @@ def test_customized_wheel(self): "example_customized-0.0.1.dist-info/WHEEL", "example_customized-0.0.1.dist-info/METADATA", "example_customized-0.0.1.dist-info/entry_points.txt", + "example_customized-0.0.1.dist-info/NOTICE", + "example_customized-0.0.1.dist-info/README", "example_customized-0.0.1.dist-info/RECORD", ], ) @@ -98,6 +100,8 @@ def test_customized_wheel(self): record_contents, b"""\ example_customized-0.0.1.dist-info/METADATA,sha256=pzE96o3Sp63TDzxAZgl0F42EFevm8x15vpDLqDVp_EQ,378 +example_customized-0.0.1.dist-info/NOTICE,sha256=Xpdw-FXET1IRgZ_wTkx1YQfo1-alET0FVf6V1LXO4js,76 +example_customized-0.0.1.dist-info/README,sha256=WmOFwZ3Jga1bHG3JiGRsUheb4UbLffUxyTdHczS27-o,40 example_customized-0.0.1.dist-info/RECORD,, example_customized-0.0.1.dist-info/WHEEL,sha256=sobxWSyDDkdg_rinUth-jxhXHqoNqlmNMJY3aTZn2Us,91 example_customized-0.0.1.dist-info/entry_points.txt,sha256=pqzpbQ8MMorrJ3Jp0ntmpZcuvfByyqzMXXi2UujuXD0,137 @@ -113,6 +117,8 @@ def test_customized_wheel(self): # and the code should be updated to account for this. rbe_expected_contents = b"""\ example_customized-0.0.1.dist-info/METADATA,sha256=pzE96o3Sp63TDzxAZgl0F42EFevm8x15vpDLqDVp_EQ,378 +example_customized-0.0.1.dist-info/NOTICE,sha256=Xpdw-FXET1IRgZ_wTkx1YQfo1-alET0FVf6V1LXO4js,76 +example_customized-0.0.1.dist-info/README,sha256=WmOFwZ3Jga1bHG3JiGRsUheb4UbLffUxyTdHczS27-o,40 example_customized-0.0.1.dist-info/RECORD,, example_customized-0.0.1.dist-info/WHEEL,sha256=sobxWSyDDkdg_rinUth-jxhXHqoNqlmNMJY3aTZn2Us,91 example_customized-0.0.1.dist-info/entry_points.txt,sha256=pqzpbQ8MMorrJ3Jp0ntmpZcuvfByyqzMXXi2UujuXD0,137 @@ -123,6 +129,8 @@ def test_customized_wheel(self): """ unix_expected_contents = b"""\ example_customized-0.0.1.dist-info/METADATA,sha256=TeeEmokHE2NWjkaMcVJuSAq4_AXUoIad2-SLuquRmbg,372 +example_customized-0.0.1.dist-info/NOTICE,sha256=Xpdw-FXET1IRgZ_wTkx1YQfo1-alET0FVf6V1LXO4js,76 +example_customized-0.0.1.dist-info/README,sha256=WmOFwZ3Jga1bHG3JiGRsUheb4UbLffUxyTdHczS27-o,40 example_customized-0.0.1.dist-info/RECORD,, example_customized-0.0.1.dist-info/WHEEL,sha256=sobxWSyDDkdg_rinUth-jxhXHqoNqlmNMJY3aTZn2Us,91 example_customized-0.0.1.dist-info/entry_points.txt,sha256=pqzpbQ8MMorrJ3Jp0ntmpZcuvfByyqzMXXi2UujuXD0,137 diff --git a/python/packaging.bzl b/python/packaging.bzl index 19b5894e2a..22d1f5bc4d 100644 --- a/python/packaging.bzl +++ b/python/packaging.bzl @@ -221,6 +221,19 @@ def _py_wheel_impl(ctx): args.add("--description_file", description_file) other_inputs.append(description_file) + for target, filename in ctx.attr.extra_distinfo_files.items(): + target_files = target.files.to_list() + if len(target_files) != 1: + fail( + "Multi-file target listed in extra_distinfo_files %s", + filename, + ) + other_inputs.extend(target_files) + args.add( + "--extra_distinfo_file", + filename + ";" + target_files[0].path, + ) + ctx.actions.run( inputs = depset(direct = other_inputs, transitive = [inputs_to_package]), outputs = [outfile, name_file], @@ -356,6 +369,10 @@ _other_attrs = { doc = "A file containing text describing the package in a single line.", allow_single_file = True, ), + "extra_distinfo_files": attr.label_keyed_string_dict( + doc = "Extra files to add to distinfo directory in the archive.", + allow_files = True, + ), "homepage": attr.string( doc = "A string specifying the URL for the package homepage.", default = "", diff --git a/tools/wheelmaker.py b/tools/wheelmaker.py index fb8e37b5a9..85b97bb44f 100644 --- a/tools/wheelmaker.py +++ b/tools/wheelmaker.py @@ -336,13 +336,20 @@ def parse_args() -> argparse.Namespace: "--input_file", action="append", help="'package_path;real_path' pairs listing " - "files to be included in the wheel. " - "Can be supplied multiple times.", + "files to be included in the wheel. " + "Can be supplied multiple times.", ) contents_group.add_argument( "--input_file_list", action="append", - help="A file that has all the input files defined as a list to avoid the long command", + help="A file that has all the input files defined as a list to avoid " + "the long command", + ) + contents_group.add_argument( + "--extra_distinfo_file", + action="append", + help="'filename;real_path' pairs listing extra files to include in" + "dist-info directory. Can be supplied multiple times.", ) requirements_group = parser.add_argument_group("Package requirements") @@ -383,6 +390,12 @@ def main() -> None: else: input_files = [] + if arguments.extra_distinfo_file: + extra_distinfo_file = [i.split(";") for i in + arguments.extra_distinfo_file] + else: + extra_distinfo_file = [] + if arguments.input_file_list: for input_file in arguments.input_file_list: with open(input_file) as _file: @@ -451,7 +464,15 @@ def main() -> None: if arguments.entry_points_file: maker.add_file( - maker.distinfo_path("entry_points.txt"), arguments.entry_points_file + maker.distinfo_path("entry_points.txt"), + arguments.entry_points_file + ) + + # Sort the files for reproducible order in the archive. + for filename, real_path in sorted(extra_distinfo_file): + maker.add_file( + maker.distinfo_path(filename), + real_path ) maker.add_recordfile() From 7f301132ca1446b6f252532c584ec8fd2c62de58 Mon Sep 17 00:00:00 2001 From: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Date: Wed, 5 Oct 2022 12:42:44 -0700 Subject: [PATCH 042/234] fix: assert expected bazel version (#847) Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- BUILD | 28 ++++++++++++++++++++++++++++ version.bzl | 1 - 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/BUILD b/BUILD index 7ea2aa4070..3385ee4914 100644 --- a/BUILD +++ b/BUILD @@ -11,7 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + load("@bazel_gazelle//:def.bzl", "gazelle") +load(":version.bzl", "BAZEL_VERSION") package(default_visibility = ["//visibility:public"]) @@ -76,3 +78,29 @@ gazelle( ], command = "update-repos", ) + +genrule( + name = "assert_bazelversion", + srcs = [".bazelversion"], + outs = ["assert_bazelversion_test.sh"], + cmd = """\ +set -o errexit -o nounset -o pipefail +current=$$(cat "$(execpath .bazelversion)") +cat > "$@" <&2 echo "ERROR: current bazel version '$${{current}}' is not the expected '{expected}'" + exit 1 +fi +EOF +""".format( + expected = BAZEL_VERSION, + ), + executable = True, +) + +sh_test( + name = "assert_bazelversion_test", + srcs = [":assert_bazelversion_test.sh"], +) diff --git a/version.bzl b/version.bzl index ac1dabb473..829762a577 100644 --- a/version.bzl +++ b/version.bzl @@ -17,7 +17,6 @@ # against. # This version should be updated together with the version of Bazel # in .bazelversion. -# TODO(alexeagle): assert this is the case in a test BAZEL_VERSION = "5.2.0" # Versions of Bazel which users should be able to use. From 2aeff3b5e65492b815544f6d33750cc788918863 Mon Sep 17 00:00:00 2001 From: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Date: Wed, 5 Oct 2022 12:50:29 -0700 Subject: [PATCH 043/234] bump: pre-commit linters (#848) Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- .../pip_install/extract_wheels/arguments.py | 2 +- .../extract_wheels/extract_single_wheel.py | 1 + python/runfiles/runfiles.py | 1 + tools/wheelmaker.py | 19 +++++++------------ 5 files changed, 12 insertions(+), 15 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d84dec87af..a84d531488 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,7 +3,7 @@ # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/keith/pre-commit-buildifier - rev: 4.0.1.1 + rev: 5.1.0.1 hooks: - id: buildifier args: &args @@ -20,6 +20,6 @@ repos: - --profile - black - repo: https://github.com/psf/black - rev: 21.12b0 + rev: 22.8.0 hooks: - id: black diff --git a/python/pip_install/extract_wheels/arguments.py b/python/pip_install/extract_wheels/arguments.py index ce77bb028e..0612a94f50 100644 --- a/python/pip_install/extract_wheels/arguments.py +++ b/python/pip_install/extract_wheels/arguments.py @@ -43,7 +43,7 @@ def parse_common_args(parser: ArgumentParser) -> ArgumentParser: "--download_only", action="store_true", help="Use 'pip download' instead of 'pip wheel'. Disables building wheels from source, but allows use of " - "--platform, --python-version, --implementation, and --abi in --extra_pip_args.", + "--platform, --python-version, --implementation, and --abi in --extra_pip_args.", ) return parser diff --git a/python/pip_install/extract_wheels/extract_single_wheel.py b/python/pip_install/extract_wheels/extract_single_wheel.py index 9c44effdd7..ff64291024 100644 --- a/python/pip_install/extract_wheels/extract_single_wheel.py +++ b/python/pip_install/extract_wheels/extract_single_wheel.py @@ -34,6 +34,7 @@ def configure_reproducible_wheels() -> None: if "PYTHONHASHSEED" not in os.environ: os.environ["PYTHONHASHSEED"] = "0" + def main() -> None: parser = argparse.ArgumentParser( description="Build and/or fetch a single wheel based on the requirement passed in" diff --git a/python/runfiles/runfiles.py b/python/runfiles/runfiles.py index 4449c711ad..d7417ec7d1 100644 --- a/python/runfiles/runfiles.py +++ b/python/runfiles/runfiles.py @@ -73,6 +73,7 @@ # this import may fail at runtime. Luckily mypy can follow this conditional import. from typing import Callable, Dict, Optional, Tuple, Union + def CreateManifestBased(manifest_path): # type: (str) -> _Runfiles return _Runfiles(_ManifestBased(manifest_path)) diff --git a/tools/wheelmaker.py b/tools/wheelmaker.py index 85b97bb44f..4e03680345 100644 --- a/tools/wheelmaker.py +++ b/tools/wheelmaker.py @@ -336,20 +336,20 @@ def parse_args() -> argparse.Namespace: "--input_file", action="append", help="'package_path;real_path' pairs listing " - "files to be included in the wheel. " - "Can be supplied multiple times.", + "files to be included in the wheel. " + "Can be supplied multiple times.", ) contents_group.add_argument( "--input_file_list", action="append", help="A file that has all the input files defined as a list to avoid " - "the long command", + "the long command", ) contents_group.add_argument( "--extra_distinfo_file", action="append", help="'filename;real_path' pairs listing extra files to include in" - "dist-info directory. Can be supplied multiple times.", + "dist-info directory. Can be supplied multiple times.", ) requirements_group = parser.add_argument_group("Package requirements") @@ -391,8 +391,7 @@ def main() -> None: input_files = [] if arguments.extra_distinfo_file: - extra_distinfo_file = [i.split(";") for i in - arguments.extra_distinfo_file] + extra_distinfo_file = [i.split(";") for i in arguments.extra_distinfo_file] else: extra_distinfo_file = [] @@ -464,16 +463,12 @@ def main() -> None: if arguments.entry_points_file: maker.add_file( - maker.distinfo_path("entry_points.txt"), - arguments.entry_points_file + maker.distinfo_path("entry_points.txt"), arguments.entry_points_file ) # Sort the files for reproducible order in the archive. for filename, real_path in sorted(extra_distinfo_file): - maker.add_file( - maker.distinfo_path(filename), - real_path - ) + maker.add_file(maker.distinfo_path(filename), real_path) maker.add_recordfile() From fa4c40886dc032fbd4ec7126eeb6317c0699b23a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Stradomski?= <44680433+pstradomski@users.noreply.github.com> Date: Thu, 6 Oct 2022 00:58:19 +0200 Subject: [PATCH 044/234] Move construction of the METADATA file from wheelmaker to .bzl (#844) * Move construction of the METADATA file (except for appending description) from wheelmaker to .bzl to avoid passing possibly unicode data on the commandline, which causes issues on windows an RBE due to UTF-16 vs UTF-8 confusion. Also fix some wrong attribute descriptions. * Regenerated docs. Buildifier fixes. * Another missing docs update. * Fix tests: all platforms should produce identical wheels. Co-authored-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- docs/packaging.md | 6 +- examples/wheel/wheel_test.py | 99 ++++----------------------------- python/packaging.bzl | 58 ++++++++++++-------- tools/wheelmaker.py | 103 +++++++---------------------------- 4 files changed, 69 insertions(+), 197 deletions(-) diff --git a/docs/packaging.md b/docs/packaging.md index 6d063edbff..af822b07eb 100755 --- a/docs/packaging.md +++ b/docs/packaging.md @@ -91,7 +91,7 @@ py_wheel( | classifiers | A list of strings describing the categories for the package. For valid classifiers see https://pypi.org/classifiers | List of strings | optional | [] | | console_scripts | Deprecated console_script entry points, e.g. {'main': 'examples.wheel.main:main'}.

Deprecated: prefer the entry_points attribute, which supports console_scripts as well as other entry points. | Dictionary: String -> String | optional | {} | | deps | Targets to be included in the distribution.

The targets to package are usually py_library rules or filesets (for packaging data files).

Note it's usually better to package py_library targets and use entry_points attribute to specify console_scripts than to package py_binary rules. py_binary targets would wrap a executable script that tries to locate .runfiles directory which is not packaged in the wheel. | List of labels | optional | [] | -| description_file | A file containing text describing the package in a single line. | Label | optional | None | +| description_file | A file containing text describing the package. | Label | optional | None | | distribution | Name of the distribution.

This should match the project name onm PyPI. It's also the name that is used to refer to the package in other packages' dependencies. | String | required | | | entry_points | entry_points, e.g. {'console_scripts': ['main = examples.wheel.main:main']}. | Dictionary: String -> List of strings | optional | {} | | extra_distinfo_files | Extra files to add to distinfo directory in the archive. | Dictionary: Label -> String | optional | {} | @@ -99,9 +99,9 @@ py_wheel( | homepage | A string specifying the URL for the package homepage. | String | optional | "" | | license | A string specifying the license of the package. | String | optional | "" | | platform | Supported platform. Use 'any' for pure-Python wheel.

If you have included platform-specific data, such as a .pyd or .so extension module, you will need to specify the platform in standard pip format. If you support multiple platforms, you can define platform constraints, then use a select() to specify the appropriate specifier, eg:

platform = select({ "//platforms:windows_x86_64": "win_amd64", "//platforms:macos_x86_64": "macosx_10_7_x86_64", "//platforms:linux_x86_64": "manylinux2014_x86_64", }) | String | optional | "any" | -| python_requires | A string specifying what other distributions need to be installed when this one is. See the section on [Declaring required dependency](https://setuptools.readthedocs.io/en/latest/userguide/dependency_management.html#declaring-dependencies) for details and examples of the format of this argument. | String | optional | "" | +| python_requires | Python versions required by this distribution, e.g. '>=3.5,<3.7' | String | optional | "" | | python_tag | Supported Python version(s), eg py3, cp35.cp36, etc | String | optional | "py3" | -| requires | List of requirements for this package | List of strings | optional | [] | +| requires | List of requirements for this package. See the section on [Declaring required dependency](https://setuptools.readthedocs.io/en/latest/userguide/dependency_management.html#declaring-dependencies) for details and examples of the format of this argument. | List of strings | optional | [] | | stamp | Whether to encode build information into the wheel. Possible values:

- stamp = 1: Always stamp the build information into the wheel, even in [--nostamp](https://docs.bazel.build/versions/main/user-manual.html#flag--stamp) builds. This setting should be avoided, since it potentially kills remote caching for the target and any downstream actions that depend on it.

- stamp = 0: Always replace build information by constant values. This gives good build result caching.

- stamp = -1: Embedding of build information is controlled by the [--[no]stamp](https://docs.bazel.build/versions/main/user-manual.html#flag--stamp) flag.

Stamped targets are not rebuilt unless their dependencies change. | Integer | optional | -1 | | strip_path_prefixes | path prefixes to strip from files added to the generated package | List of strings | optional | [] | | version | Version number of the package. Note that this attribute supports stamp format strings (eg. 1.2.3-{BUILD_TIMESTAMP}) as well as 'make variables' (e.g. 1.2.3-$(VERSION)). | String | required | | diff --git a/examples/wheel/wheel_test.py b/examples/wheel/wheel_test.py index 0e495eb236..cbca0927c3 100644 --- a/examples/wheel/wheel_test.py +++ b/examples/wheel/wheel_test.py @@ -94,40 +94,11 @@ def test_customized_wheel(self): entry_point_contents = zf.read( "example_customized-0.0.1.dist-info/entry_points.txt" ) - # The entries are guaranteed to be sorted. - if platform.system() == "Windows": - self.assertEqual( - record_contents, - b"""\ -example_customized-0.0.1.dist-info/METADATA,sha256=pzE96o3Sp63TDzxAZgl0F42EFevm8x15vpDLqDVp_EQ,378 -example_customized-0.0.1.dist-info/NOTICE,sha256=Xpdw-FXET1IRgZ_wTkx1YQfo1-alET0FVf6V1LXO4js,76 -example_customized-0.0.1.dist-info/README,sha256=WmOFwZ3Jga1bHG3JiGRsUheb4UbLffUxyTdHczS27-o,40 -example_customized-0.0.1.dist-info/RECORD,, -example_customized-0.0.1.dist-info/WHEEL,sha256=sobxWSyDDkdg_rinUth-jxhXHqoNqlmNMJY3aTZn2Us,91 -example_customized-0.0.1.dist-info/entry_points.txt,sha256=pqzpbQ8MMorrJ3Jp0ntmpZcuvfByyqzMXXi2UujuXD0,137 -examples/wheel/lib/data.txt,sha256=9vJKEdfLu8bZRArKLroPZJh1XKkK3qFMXiM79MBL2Sg,12 -examples/wheel/lib/module_with_data.py,sha256=8s0Khhcqz3yVsBKv2IB5u4l4TMKh7-c_V6p65WVHPms,637 -examples/wheel/lib/simple_module.py,sha256=z2hwciab_XPNIBNH8B1Q5fYgnJvQTeYf0ZQJpY8yLLY,637 -examples/wheel/main.py,sha256=sgg5iWN_9inYBjm6_Zw27hYdmo-l24fA-2rfphT-IlY,909 -""", - ) - else: - # TODO: The non-ascii characters in the METADATA file are interpreted differently on the - # ubuntu16_rbe hosts in comparison to other unix platforms. This should not be the case - # and the code should be updated to account for this. - rbe_expected_contents = b"""\ -example_customized-0.0.1.dist-info/METADATA,sha256=pzE96o3Sp63TDzxAZgl0F42EFevm8x15vpDLqDVp_EQ,378 -example_customized-0.0.1.dist-info/NOTICE,sha256=Xpdw-FXET1IRgZ_wTkx1YQfo1-alET0FVf6V1LXO4js,76 -example_customized-0.0.1.dist-info/README,sha256=WmOFwZ3Jga1bHG3JiGRsUheb4UbLffUxyTdHczS27-o,40 -example_customized-0.0.1.dist-info/RECORD,, -example_customized-0.0.1.dist-info/WHEEL,sha256=sobxWSyDDkdg_rinUth-jxhXHqoNqlmNMJY3aTZn2Us,91 -example_customized-0.0.1.dist-info/entry_points.txt,sha256=pqzpbQ8MMorrJ3Jp0ntmpZcuvfByyqzMXXi2UujuXD0,137 -examples/wheel/lib/data.txt,sha256=9vJKEdfLu8bZRArKLroPZJh1XKkK3qFMXiM79MBL2Sg,12 -examples/wheel/lib/module_with_data.py,sha256=8s0Khhcqz3yVsBKv2IB5u4l4TMKh7-c_V6p65WVHPms,637 -examples/wheel/lib/simple_module.py,sha256=z2hwciab_XPNIBNH8B1Q5fYgnJvQTeYf0ZQJpY8yLLY,637 -examples/wheel/main.py,sha256=sgg5iWN_9inYBjm6_Zw27hYdmo-l24fA-2rfphT-IlY,909 -""" - unix_expected_contents = b"""\ + + self.assertEqual( + record_contents, + # The entries are guaranteed to be sorted. + b"""\ example_customized-0.0.1.dist-info/METADATA,sha256=TeeEmokHE2NWjkaMcVJuSAq4_AXUoIad2-SLuquRmbg,372 example_customized-0.0.1.dist-info/NOTICE,sha256=Xpdw-FXET1IRgZ_wTkx1YQfo1-alET0FVf6V1LXO4js,76 example_customized-0.0.1.dist-info/README,sha256=WmOFwZ3Jga1bHG3JiGRsUheb4UbLffUxyTdHczS27-o,40 @@ -138,15 +109,7 @@ def test_customized_wheel(self): examples/wheel/lib/module_with_data.py,sha256=8s0Khhcqz3yVsBKv2IB5u4l4TMKh7-c_V6p65WVHPms,637 examples/wheel/lib/simple_module.py,sha256=z2hwciab_XPNIBNH8B1Q5fYgnJvQTeYf0ZQJpY8yLLY,637 examples/wheel/main.py,sha256=sgg5iWN_9inYBjm6_Zw27hYdmo-l24fA-2rfphT-IlY,909 -""" - self.assertIn( - record_contents, - [ - rbe_expected_contents, - unix_expected_contents, - ], - ) - +""") self.assertEqual( wheel_contents, b"""\ @@ -156,44 +119,9 @@ def test_customized_wheel(self): Tag: py3-none-any """, ) - if platform.system() == "Windows": - self.assertEqual( - metadata_contents, - b"""\ -Metadata-Version: 2.1 -Name: example_customized -Version: 0.0.1 -Author: Example Author with non-ascii characters: \xc3\x85\xc2\xbc\xc3\x83\xc2\xb3\xc3\x85\xc2\x82w -Author-email: example@example.com -Home-page: www.example.com -License: Apache 2.0 -Classifier: License :: OSI Approved :: Apache Software License -Classifier: Intended Audience :: Developers -Requires-Dist: pytest - -This is a sample description of a wheel. -""", - ) - else: - # TODO: The non-ascii characters in the METADATA file are interpreted differently on the - # ubuntu16_rbe hosts in comparison to other unix platforms. This should not be the case - # and the code should be updated to account for this. - rbe_expected_contents = b"""\ -Metadata-Version: 2.1 -Name: example_customized -Version: 0.0.1 -Author: Example Author with non-ascii characters: \xc3\x85\xc2\xbc\xc3\x83\xc2\xb3\xc3\x85\xc2\x82w -Author-email: example@example.com -Home-page: www.example.com -License: Apache 2.0 -Classifier: License :: OSI Approved :: Apache Software License -Classifier: Intended Audience :: Developers -Requires-Dist: pytest - -This is a sample description of a wheel. -""" - - unix_expected_contents = b"""\ + self.assertEqual( + metadata_contents, + b"""\ Metadata-Version: 2.1 Name: example_customized Version: 0.0.1 @@ -206,14 +134,7 @@ def test_customized_wheel(self): Requires-Dist: pytest This is a sample description of a wheel. -""" - self.assertIn( - metadata_contents, - [ - rbe_expected_contents, - unix_expected_contents, - ], - ) +""") self.assertEqual( entry_point_contents, b"""\ diff --git a/python/packaging.bzl b/python/packaging.bzl index 22d1f5bc4d..6d7a901f53 100644 --- a/python/packaging.bzl +++ b/python/packaging.bzl @@ -153,7 +153,6 @@ def _py_wheel_impl(ctx): args.add("--name", ctx.attr.distribution) args.add("--version", version) args.add("--python_tag", ctx.attr.python_tag) - args.add("--python_requires", ctx.attr.python_requires) args.add("--abi", ctx.attr.abi) args.add("--platform", ctx.attr.platform) args.add("--out", outfile) @@ -168,28 +167,42 @@ def _py_wheel_impl(ctx): args.add("--input_file_list", packageinputfile) - extra_headers = [] + # Note: Description file is not embedded into metadata.txt yet, + # it will be done later by wheelmaker script. + metadata_file = ctx.actions.declare_file(ctx.attr.name + ".metadata.txt") + metadata_contents = ["Metadata-Version: 2.1"] + metadata_contents.append("Name: %s" % ctx.attr.distribution) + metadata_contents.append("Version: %s" % version) + if ctx.attr.author: - extra_headers.append("Author: %s" % ctx.attr.author) + metadata_contents.append("Author: %s" % ctx.attr.author) if ctx.attr.author_email: - extra_headers.append("Author-email: %s" % ctx.attr.author_email) + metadata_contents.append("Author-email: %s" % ctx.attr.author_email) if ctx.attr.homepage: - extra_headers.append("Home-page: %s" % ctx.attr.homepage) + metadata_contents.append("Home-page: %s" % ctx.attr.homepage) if ctx.attr.license: - extra_headers.append("License: %s" % ctx.attr.license) - - for h in extra_headers: - args.add("--header", h) + metadata_contents.append("License: %s" % ctx.attr.license) for c in ctx.attr.classifiers: - args.add("--classifier", c) - - for r in ctx.attr.requires: - args.add("--requires", r) - - for option, requirements in ctx.attr.extra_requires.items(): - for r in requirements: - args.add("--extra_requires", r + ";" + option) + metadata_contents.append("Classifier: %s" % c) + + if ctx.attr.python_requires: + metadata_contents.append("Requires-Python: %s" % ctx.attr.python_requires) + for requirement in ctx.attr.requires: + metadata_contents.append("Requires-Dist: %s" % requirement) + + for option, option_requirements in sorted(ctx.attr.extra_requires.items()): + metadata_contents.append("Provides-Extra: %s" % option) + for requirement in option_requirements: + metadata_contents.append( + "Requires-Dist: %s; extra == '%s'" % (requirement, option), + ) + ctx.actions.write( + output = metadata_file, + content = "\n".join(metadata_contents) + "\n", + ) + other_inputs.append(metadata_file) + args.add("--metadata_file", metadata_file) # Merge console_scripts into entry_points. entrypoints = dict(ctx.attr.entry_points) # Copy so we can mutate it @@ -334,7 +347,9 @@ _requirement_attrs = { doc = "List of optional requirements for this package", ), "requires": attr.string_list( - doc = "List of requirements for this package", + doc = ("List of requirements for this package. See the section on " + + "[Declaring required dependency](https://setuptools.readthedocs.io/en/latest/userguide/dependency_management.html#declaring-dependencies) " + + "for details and examples of the format of this argument."), ), } @@ -366,7 +381,7 @@ _other_attrs = { doc = "A list of strings describing the categories for the package. For valid classifiers see https://pypi.org/classifiers", ), "description_file": attr.label( - doc = "A file containing text describing the package in a single line.", + doc = "A file containing text describing the package.", allow_single_file = True, ), "extra_distinfo_files": attr.label_keyed_string_dict( @@ -383,10 +398,7 @@ _other_attrs = { ), "python_requires": attr.string( doc = ( - "A string specifying what other distributions need to be installed " + - "when this one is. See the section on " + - "[Declaring required dependency](https://setuptools.readthedocs.io/en/latest/userguide/dependency_management.html#declaring-dependencies) " + - "for details and examples of the format of this argument." + "Python versions required by this distribution, e.g. '>=3.5,<3.7'" ), default = "", ), diff --git a/tools/wheelmaker.py b/tools/wheelmaker.py index 4e03680345..d5179001a6 100644 --- a/tools/wheelmaker.py +++ b/tools/wheelmaker.py @@ -167,39 +167,11 @@ def add_wheelfile(self): wheel_contents += "Tag: %s\n" % tag self.add_string(self.distinfo_path("WHEEL"), wheel_contents) - def add_metadata( - self, - extra_headers, - description, - classifiers, - python_requires, - requires, - extra_requires, - ): + def add_metadata(self, metadata, description): """Write METADATA file to the distribution.""" # https://www.python.org/dev/peps/pep-0566/ # https://packaging.python.org/specifications/core-metadata/ - metadata = [] - metadata.append("Metadata-Version: 2.1") - metadata.append("Name: %s" % self._name) - metadata.append("Version: %s" % self._version) - metadata.extend(extra_headers) - for classifier in classifiers: - metadata.append("Classifier: %s" % classifier) - if python_requires: - metadata.append("Requires-Python: %s" % python_requires) - for requirement in requires: - metadata.append("Requires-Dist: %s" % requirement) - - extra_requires = sorted(extra_requires.items()) - for option, option_requires in extra_requires: - metadata.append("Provides-Extra: %s" % option) - for requirement in option_requires: - metadata.append( - "Requires-Dist: %s; extra == '%s'" % (requirement, option) - ) - - metadata = "\n".join(metadata) + "\n\n" + metadata += "\n" # setuptools seems to insert UNKNOWN as description when none is # provided. metadata += description if description else "UNKNOWN" @@ -303,25 +275,15 @@ def parse_args() -> argparse.Namespace: action="append", default=[], help="Path prefix to be stripped from input package files' path. " - "Can be supplied multiple times. " - "Evaluated in order.", + "Can be supplied multiple times. Evaluated in order.", ) wheel_group = parser.add_argument_group("Wheel metadata") wheel_group.add_argument( - "--header", - action="append", - help="Additional headers to be embedded in the package metadata. " - "Can be supplied multiple times.", - ) - wheel_group.add_argument( - "--classifier", - action="append", - help="Classifiers to embed in package metadata. " - "Can be supplied multiple times", - ) - wheel_group.add_argument( - "--python_requires", help="Version of python that the wheel will work with" + "--metadata_file", + type=Path, + help="Contents of the METADATA file (before appending contents of " + "--description_file)", ) wheel_group.add_argument( "--description_file", help="Path to the file with package description" @@ -352,21 +314,6 @@ def parse_args() -> argparse.Namespace: "dist-info directory. Can be supplied multiple times.", ) - requirements_group = parser.add_argument_group("Package requirements") - requirements_group.add_argument( - "--requires", - type=str, - action="append", - help="List of package requirements. Can be supplied multiple times.", - ) - requirements_group.add_argument( - "--extra_requires", - type=str, - action="append", - help="List of optional requirements in a 'requirement;option name'. " - "Can be supplied multiple times.", - ) - build_group = parser.add_argument_group("Building requirements") build_group.add_argument( "--volatile_status_file", @@ -434,32 +381,24 @@ def main() -> None: description = None if arguments.description_file: if sys.version_info[0] == 2: - with open(arguments.description_file, "rt") as description_file: + with open(arguments.description_file, + "rt") as description_file: description = description_file.read() else: - with open( - arguments.description_file, "rt", encoding="utf-8" - ) as description_file: + with open(arguments.description_file, "rt", + encoding="utf-8") as description_file: description = description_file.read() - extra_requires = collections.defaultdict(list) - if arguments.extra_requires: - for extra in arguments.extra_requires: - req, option = extra.rsplit(";", 1) - extra_requires[option].append(req) - classifiers = arguments.classifier or [] - python_requires = arguments.python_requires or "" - requires = arguments.requires or [] - extra_headers = arguments.header or [] - - maker.add_metadata( - extra_headers=extra_headers, - description=description, - classifiers=classifiers, - python_requires=python_requires, - requires=requires, - extra_requires=extra_requires, - ) + metadata = None + if sys.version_info[0] == 2: + with open(arguments.metadata_file, "rt") as metadata_file: + metadata = metadata_file.read() + else: + with open(arguments.metadata_file, "rt", + encoding="utf-8") as metadata_file: + metadata = metadata_file.read() + + maker.add_metadata(metadata=metadata, description=description) if arguments.entry_points_file: maker.add_file( From 44d41ee992bd412bd9e4f8663e2e090894232be9 Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Wed, 5 Oct 2022 16:04:53 -0700 Subject: [PATCH 045/234] Include ignore_root_user_error in repository_rule keys (#835) Otherwise you can see this warning: ``` DEBUG: Rule 'python3_9_aarch64-apple-darwin' indicated that a canonical reproducible form can be obtained by dropping arguments ["ignore_root_user_error"] DEBUG: Repository python3_9_aarch64-apple-darwin instantiated at: /Users/ksmiley/dev/lyft/ios4/WORKSPACE:113:27: in /private/var/tmp/_bazel_ksmiley/c921e5b09fe02de914188528345349ce/external/rules_python/python/repositories.bzl:366:26: in python_register_toolchains Repository rule python_repository defined at: /private/var/tmp/_bazel_ksmiley/c921e5b09fe02de914188528345349ce/external/rules_python/python/repositories.bzl:269:36: in ``` Co-authored-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- python/repositories.bzl | 1 + 1 file changed, 1 insertion(+) diff --git a/python/repositories.bzl b/python/repositories.bzl index dc2c49e722..bf27af93b2 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -257,6 +257,7 @@ py_runtime_pair( return { "distutils": rctx.attr.distutils, "distutils_content": rctx.attr.distutils_content, + "ignore_root_user_error": rctx.attr.ignore_root_user_error, "name": rctx.attr.name, "platform": platform, "python_version": python_version, From b15e15fb95d584df80339a5f3bdfd253fcdff2dc Mon Sep 17 00:00:00 2001 From: Philipp Schrader Date: Wed, 5 Oct 2022 19:41:36 -0400 Subject: [PATCH 046/234] Allow requirements_in to be generated (#829) * Allow requirements_in to be generated We generate the `requirements_in` file from various input files roughly like so: genrule( name = "generate_3.7_x86_requirements", srcs = [ "requirements_base.in.txt", "requirements_extra_37.in.txt", ], outs = ["requirements_3.7_x86.txt"], cmd = "cat $(SRCS) > $(OUTS)", ) compile_pip_requirements( name = "compile_requirements_3.7_x86", requirements_in = ":requirements_3.7_x86.txt", requirements_txt = "requirements_3.7_x86.lock.txt", ) The current code errors out with a message like this: Updating common/python/requirements_3.7_x86.lock.txt Usage: pip_compile.py [OPTIONS] [SRC_FILES]... Try 'pip_compile.py -h' for help. Error: Invalid value for '[SRC_FILES]...': Path 'common/python/requirements_3.7_x86.txt' does not exist. This patch here fixes the issue by resolving the `requirements_in` path before the tool `cd`s into the workspace directory. * Make tests pass * Run black * Fix some runtime problems Co-authored-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- examples/pip_parse/BUILD | 10 ++++++ ...quirements.in => requirements.in.template} | 0 python/pip_install/pip_compile.py | 34 +++++++++++++++++-- 3 files changed, 42 insertions(+), 2 deletions(-) rename examples/pip_parse/{requirements.in => requirements.in.template} (100%) diff --git a/examples/pip_parse/BUILD b/examples/pip_parse/BUILD index 653f75ce2b..1b6ba55f5e 100644 --- a/examples/pip_parse/BUILD +++ b/examples/pip_parse/BUILD @@ -55,6 +55,16 @@ alias( actual = entry_point("yamllint"), ) +# The requirements.in file can be checked in to the source tree or it can be +# generated. Pretend that we do some generating of the file. For this example, +# the "template" is already the file we want. +genrule( + name = "generate_requirements_in", + srcs = ["requirements.in.template"], + outs = ["requirements.in"], + cmd = "cp $(SRCS) $(OUTS)", +) + # This rule adds a convenient way to update the requirements file. compile_pip_requirements( name = "requirements", diff --git a/examples/pip_parse/requirements.in b/examples/pip_parse/requirements.in.template similarity index 100% rename from examples/pip_parse/requirements.in rename to examples/pip_parse/requirements.in.template diff --git a/python/pip_install/pip_compile.py b/python/pip_install/pip_compile.py index 9258c17ffd..c9bcf32115 100644 --- a/python/pip_install/pip_compile.py +++ b/python/pip_install/pip_compile.py @@ -2,6 +2,7 @@ import os import sys +from pathlib import Path from shutil import copyfile from piptools.scripts.compile import cli @@ -25,6 +26,21 @@ def _select_golden_requirements_file( return requirements_txt +def _fix_up_requirements_in_path( + resolved_requirements_in, requirements_in, output_file +): + """Fix up references to the input file inside of the generated requirements file. + + We don't want fully resolved, absolute paths in the generated requirements file. + The paths could differ for every invocation. Replace them with a predictable path. + """ + output_file = Path(output_file) + fixed_requirements_text = output_file.read_text().replace( + resolved_requirements_in, requirements_in + ) + output_file.write_text(fixed_requirements_text) + + if __name__ == "__main__": if len(sys.argv) < 4: print( @@ -42,6 +58,10 @@ def _select_golden_requirements_file( requirements_windows = parse_str_none(sys.argv.pop(1)) update_target_label = sys.argv.pop(1) + # The requirements_in file could be generated. We need to get the path to it before we change + # directory into the workspace directory. + resolved_requirements_in = str(Path(requirements_in).resolve()) + # Before loading click, set the locale for its parser. # If it leaks through to the system setting, it may fail: # RuntimeError: Click will abort further execution because Python 3 was configured to use ASCII @@ -96,11 +116,18 @@ def _select_golden_requirements_file( sys.argv.append("--generate-hashes") sys.argv.append("--output-file") sys.argv.append(requirements_txt if UPDATE else requirements_out) - sys.argv.append(requirements_in) + sys.argv.append(resolved_requirements_in) if UPDATE: print("Updating " + requirements_txt) - cli() + try: + cli() + except SystemExit as e: + if e.code == 0: + _fix_up_requirements_in_path( + resolved_requirements_in, requirements_in, requirements_txt + ) + raise else: # cli will exit(0) on success try: @@ -118,6 +145,9 @@ def _select_golden_requirements_file( ) sys.exit(1) elif e.code == 0: + _fix_up_requirements_in_path( + resolved_requirements_in, requirements_in, requirements_out + ) golden_filename = _select_golden_requirements_file( requirements_txt, requirements_linux, From a523bfe17f3b5d77b290cddafda41b1d3ce40143 Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Fri, 7 Oct 2022 10:58:20 -0700 Subject: [PATCH 047/234] Clarify location of gazelle_python.yaml I had a client yesterday who tripped on this since their requirements were in some unrelated location, so Gazelle wasn't finding the modules manifest. --- gazelle/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/gazelle/README.md b/gazelle/README.md index fe3fb2d0c9..e622db991a 100644 --- a/gazelle/README.md +++ b/gazelle/README.md @@ -31,10 +31,12 @@ by the `modules_mapping` rule. We'll make a target for consuming this This is checked into the repo for speed, as it takes some time to calculate in a large monorepo. -Create a file `gazelle_python.yaml` next to your `requirements.txt` -file. (You can just use `touch` at this point, it just needs to exist.) +Gazelle will walk up the filesystem from a Python file to find this metadata, +looking for a file called `gazelle_python.yaml` in an ancestor folder of the Python code. +Create an empty file with this name. It might be next to your `requirements.txt` file. +(You can just use `touch` at this point, it just needs to exist.) -Then put this in your `BUILD.bazel` file next to the `requirements.txt`: +To keep the metadata updated, put this in your `BUILD.bazel` file next to `gazelle_python.yaml`: ```starlark load("@pip//:requirements.bzl", "all_whl_requirements") From d98357728f45e10b0c5e67389e65e6f4b688bdfc Mon Sep 17 00:00:00 2001 From: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Date: Fri, 7 Oct 2022 14:37:26 -0700 Subject: [PATCH 048/234] bump: ubuntu version on CI Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- .bazelci/presubmit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index e950d02c69..b7badf0500 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -19,7 +19,7 @@ all_targets: &all_targets # Disabled due to https://github.com/bazelbuild/rules_python/issues/827 - "-//python/tests/toolchains:python_3_8_10_x86_64-apple-darwin_test" platforms: - ubuntu1804: + ubuntu2004: <<: *all_targets macos: <<: *all_targets From 85c81867e705e00cfa28d62aa016ca31526bfce2 Mon Sep 17 00:00:00 2001 From: Steven Casagrande Date: Sun, 9 Oct 2022 21:53:42 -0400 Subject: [PATCH 049/234] fix: replace cc_import with cc_library for libpython (#820) Replace cc_import with cc_library for libpython Co-authored-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- python/repositories.bzl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/python/repositories.bzl b/python/repositories.bzl index bf27af93b2..8b59b5d412 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -221,13 +221,13 @@ cc_library( ], ) -cc_import( +cc_library( name = "libpython", hdrs = [":includes"], - shared_library = select({{ - "@platforms//os:windows": "python3.dll", - "@platforms//os:macos": "lib/libpython{python_version}.dylib", - "@platforms//os:linux": "lib/libpython{python_version}.so.1.0", + srcs = select({{ + "@platforms//os:windows": ["python3.dll"], + "@platforms//os:macos": ["lib/libpython{python_version}.dylib"], + "@platforms//os:linux": ["lib/libpython{python_version}.so", "lib/libpython{python_version}.so.1.0"], }}), ) From 2cdad9e18eda451e486737ff3cddc25ddd579c8e Mon Sep 17 00:00:00 2001 From: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Date: Mon, 10 Oct 2022 08:02:32 -0700 Subject: [PATCH 050/234] fix: re-enable python_3_8_10_x86_64-apple-darwin_test (#851) --- .bazelci/presubmit.yml | 2 -- python/repositories.bzl | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index b7badf0500..9dd6d9675b 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -16,8 +16,6 @@ all_targets: &all_targets test_targets: - "--" - "..." - # Disabled due to https://github.com/bazelbuild/rules_python/issues/827 - - "-//python/tests/toolchains:python_3_8_10_x86_64-apple-darwin_test" platforms: ubuntu2004: <<: *all_targets diff --git a/python/repositories.bzl b/python/repositories.bzl index 8b59b5d412..efde00a4e7 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -250,6 +250,7 @@ py_runtime_pair( python_path = python_bin, python_version = python_short_version, ) + rctx.delete("python") rctx.symlink(python_bin, "python") rctx.file(STANDALONE_INTERPRETER_FILENAME, "# File intentionally left blank. Indicates that this is an interpreter repo created by rules_python.") rctx.file("BUILD.bazel", build_content) From 26526a501f5ee67b370744a76a3aa3cf98d212f4 Mon Sep 17 00:00:00 2001 From: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Date: Wed, 12 Oct 2022 09:05:24 -0700 Subject: [PATCH 051/234] refactor: ci with multiple tasks (#855) * refactor: ci with multiple tasks Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: tags Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: add missing integration test to CI Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: comment about Gazelle and Windows Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- .bazelci/presubmit.yml | 198 ++++++++++++++---- examples/build_file_generation/.bazelrc | 5 + examples/build_file_generation/WORKSPACE | 9 + .../build_file_generation/gazelle_python.yaml | 2 +- examples/pip_parse_vendored/.bazelrc | 5 + python/tests/toolchains/defs.bzl | 1 + tests/BUILD | 2 + .../bazel_integration_test.bzl | 4 + 8 files changed, 180 insertions(+), 46 deletions(-) create mode 100644 examples/build_file_generation/.bazelrc create mode 100644 examples/pip_parse_vendored/.bazelrc diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 9dd6d9675b..d7ca8ef05b 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -3,60 +3,168 @@ buildifier: version: latest # keep this argument in sync with .pre-commit-config.yaml warnings: "all" -all_targets: &all_targets +.reusable_config: &reusable_config build_targets: + - "--" - "..." # As a regression test for #225, check that wheel targets still build when # their package path is qualified with the repo name. - "@rules_python//examples/wheel/..." + - "-//gazelle/..." build_flags: - - "--keep_going" - # We control Bazel version in integration tests, so we don't need USE_BAZEL_VERSION for tests. - skip_use_bazel_version_for_test: true + - "--keep_going" test_targets: - "--" - "..." -platforms: - ubuntu2004: - <<: *all_targets + # The gazelle tests are not compatible with Windows, so we only test them + # on Linux. The build file generation, which uses this Gazelle extension, + # runs on all platforms, and is asserted by the build_file_generation + # integration tests below. + - "-//gazelle/..." + test_flags: + - "--test_tag_filters=-integration-test" +.reusable_build_test_all: &reusable_build_test_all + build_targets: ["..."] + test_targets: ["..."] +tasks: + gazelle_extension: + name: Test the Gazelle extension + platform: ubuntu2004 + build_targets: ["//gazelle/..."] + test_targets: ["//gazelle/..."] + linux: + <<: *reusable_config + name: Default test on Linux + platform: ubuntu2004 macos: - <<: *all_targets + <<: *reusable_config + name: Default test on macOS + platform: macos windows: - build_targets: - - "--" # Allows negative patterns; hack for https://github.com/bazelbuild/continuous-integration/pull/245 - - "..." - # Gazelle is not fully Windows compatible: https://github.com/bazelbuild/bazel-gazelle/issues/1122 - - "-//gazelle/..." - # As a regression test for #225, check that wheel targets still build when - # their package path is qualified with the repo name. - - "@rules_python//examples/wheel/..." - # We control Bazel version in integration tests, so we don't need USE_BAZEL_VERSION for tests. - skip_use_bazel_version_for_test: true - test_targets: - - "--" # Allows negative patterns; hack for https://github.com/bazelbuild/continuous-integration/pull/245 - - "..." - # Gazelle is not fully Windows compatible: https://github.com/bazelbuild/bazel-gazelle/issues/1122 - - "-//gazelle/..." - # The dependencies needed for this test are not cross-platform: https://github.com/bazelbuild/rules_python/issues/260 - - "-//tests:pip_repository_entry_points_example" + <<: *reusable_config + name: Default test on Windows + platform: windows + test_flags: + - "--test_tag_filters=-integration-test,-fix-windows" + rbe: + <<: *reusable_config + name: Test on RBE + platform: rbe_ubuntu1604 test_flags: - - "--test_tag_filters=-fix-windows" - rbe_ubuntu1604: - build_targets: - - "--" # Allows negative patterns; hack for https://github.com/bazelbuild/continuous-integration/pull/245 - - "..." - # We control Bazel version in integration tests, so we don't need USE_BAZEL_VERSION for tests. - skip_use_bazel_version_for_test: true - test_targets: - - "--" # Allows negative patterns; hack for https://github.com/bazelbuild/continuous-integration/pull/245 - - "..." - # TODO: The toolchain tests do not currently work in RBE - - "-//python/tests/toolchains/..." - # TODO: The integration tests do not currently work on RBE - # This list is the result of `bazel query 'filter(".*_example$", attr(generator_function, bazel_integration_test, //...))'` - - "-//examples:bzlmod_example" - - "-//examples:pip_install_example" - - "-//examples:pip_parse_example" - - "-//examples:pip_parse_vendored_example" - - "-//examples:pip_repository_annotations_example" - - "-//tests:pip_repository_entry_points_example" + - "--test_tag_filters=-integration-test,-acceptance-test" + + integration_test_build_file_generation_linux: + <<: *reusable_build_test_all + name: build_file_generation integration tests on Linux + working_directory: examples/build_file_generation + platform: ubuntu2004 + integration_test_build_file_generation_macos: + <<: *reusable_build_test_all + name: build_file_generation integration tests on macOS + working_directory: examples/build_file_generation + platform: macos + integration_test_build_file_generation_windows: + <<: *reusable_build_test_all + name: build_file_generation integration tests on Windows + working_directory: examples/build_file_generation + platform: windows + + integration_test_bzlmod_linux: + <<: *reusable_build_test_all + name: bzlmod integration tests on Linux + working_directory: examples/bzlmod + platform: ubuntu2004 + integration_test_bzlmod_macos: + <<: *reusable_build_test_all + name: bzlmod integration tests on macOS + working_directory: examples/bzlmod + platform: macos + integration_test_bzlmod_windows: + <<: *reusable_build_test_all + name: bzlmod integration tests on Windows + working_directory: examples/bzlmod + platform: windows + + integration_test_pip_install_linux: + <<: *reusable_build_test_all + name: pip_install integration tests on Linux + working_directory: examples/pip_install + platform: ubuntu2004 + integration_test_pip_install_macos: + <<: *reusable_build_test_all + name: pip_install integration tests on macOS + working_directory: examples/pip_install + platform: macos + integration_test_pip_install_windows: + <<: *reusable_build_test_all + name: pip_install integration tests on Windows + working_directory: examples/pip_install + platform: windows + + integration_test_pip_parse_linux: + <<: *reusable_build_test_all + name: pip_parse integration tests on Linux + working_directory: examples/pip_parse + platform: ubuntu2004 + integration_test_pip_parse_macos: + <<: *reusable_build_test_all + name: pip_parse integration tests on macOS + working_directory: examples/pip_parse + platform: macos + integration_test_pip_parse_windows: + <<: *reusable_build_test_all + name: pip_parse integration tests on Windows + working_directory: examples/pip_parse + platform: windows + + integration_test_pip_parse_vendored_linux: + <<: *reusable_build_test_all + name: pip_parse_vendored integration tests on Linux + working_directory: examples/pip_parse_vendored + platform: ubuntu2004 + integration_test_pip_parse_vendored_macos: + <<: *reusable_build_test_all + name: pip_parse_vendored integration tests on macOS + working_directory: examples/pip_parse_vendored + platform: macos + # TODO(f0rmiga): fix this test under Windows. It needs to be consistent on + # characters across all platforms. + # integration_test_pip_parse_vendored_windows: + # <<: *reusable_build_test_all + # name: pip_parse_vendored integration tests on Windows + # working_directory: examples/pip_parse_vendored + # platform: windows + + integration_test_pip_repository_annotations_linux: + <<: *reusable_build_test_all + name: pip_repository_annotations integration tests on Linux + working_directory: examples/pip_repository_annotations + platform: ubuntu2004 + integration_test_pip_repository_annotations_macos: + <<: *reusable_build_test_all + name: pip_repository_annotations integration tests on macOS + working_directory: examples/pip_repository_annotations + platform: macos + integration_test_pip_repository_annotations_windows: + <<: *reusable_build_test_all + name: pip_repository_annotations integration tests on Windows + working_directory: examples/pip_repository_annotations + platform: windows + + integration_test_pip_repository_entry_points_linux: + <<: *reusable_build_test_all + name: pip_repository_entry_points integration tests on Linux + working_directory: tests/pip_repository_entry_points + platform: ubuntu2004 + integration_test_pip_repository_entry_points_macos: + <<: *reusable_build_test_all + name: pip_repository_entry_points integration tests on macOS + working_directory: tests/pip_repository_entry_points + platform: macos + # TODO(f0rmiga): fix me. The dependencies needed for this test are not cross-platform: + # https://github.com/bazelbuild/rules_python/issues/260 + # integration_test_pip_repository_entry_points_windows: + # <<: *reusable_build_test_all + # name: pip_repository_entry_points integration tests on Windows + # working_directory: tests/pip_repository_entry_points + # platform: windows diff --git a/examples/build_file_generation/.bazelrc b/examples/build_file_generation/.bazelrc new file mode 100644 index 0000000000..f23315a7a1 --- /dev/null +++ b/examples/build_file_generation/.bazelrc @@ -0,0 +1,5 @@ +test --test_output=errors + +# Windows requires these for multi-python support: +build --enable_runfiles +startup --windows_enable_symlinks diff --git a/examples/build_file_generation/WORKSPACE b/examples/build_file_generation/WORKSPACE index 51c923f133..63ea962920 100644 --- a/examples/build_file_generation/WORKSPACE +++ b/examples/build_file_generation/WORKSPACE @@ -48,10 +48,19 @@ local_repository( path = "../..", ) +load("@rules_python//python:repositories.bzl", "python_register_toolchains") + +python_register_toolchains( + name = "python39", + python_version = "3.9", +) + +load("@python39//:defs.bzl", "interpreter") load("@rules_python//python:pip.bzl", "pip_parse") pip_parse( name = "pip", + python_interpreter_target = interpreter, requirements_lock = "//:requirements_lock.txt", ) diff --git a/examples/build_file_generation/gazelle_python.yaml b/examples/build_file_generation/gazelle_python.yaml index a005b43d0f..8e68c1ddd0 100644 --- a/examples/build_file_generation/gazelle_python.yaml +++ b/examples/build_file_generation/gazelle_python.yaml @@ -129,4 +129,4 @@ manifest: pip_repository: name: pip incremental: true -integrity: c47bf2ca0a185cf6b8815d4a61e26e7457564e931de76c70653277e4eccfadc8 +integrity: 4b3eed2cb51741419e11bd12a4533f285d059fda8029deaf6fedfe0fcda1b782 diff --git a/examples/pip_parse_vendored/.bazelrc b/examples/pip_parse_vendored/.bazelrc new file mode 100644 index 0000000000..f23315a7a1 --- /dev/null +++ b/examples/pip_parse_vendored/.bazelrc @@ -0,0 +1,5 @@ +test --test_output=errors + +# Windows requires these for multi-python support: +build --enable_runfiles +startup --windows_enable_symlinks diff --git a/python/tests/toolchains/defs.bzl b/python/tests/toolchains/defs.bzl index 2abc1ed149..653cde6657 100644 --- a/python/tests/toolchains/defs.bzl +++ b/python/tests/toolchains/defs.bzl @@ -172,4 +172,5 @@ def acceptance_tests(): ), python_version = python_version, target_compatible_with = meta.compatible_with, + tags = ["acceptance-test"], ) diff --git a/tests/BUILD b/tests/BUILD index b37a5a4232..ee9c5550e8 100644 --- a/tests/BUILD +++ b/tests/BUILD @@ -7,4 +7,6 @@ licenses(["notice"]) # Apache 2.0 bazel_integration_test( name = "pip_repository_entry_points_example", timeout = "long", + # The dependencies needed for this test are not cross-platform: https://github.com/bazelbuild/rules_python/issues/260 + tags = ["fix-windows"], ) diff --git a/tools/bazel_integration_test/bazel_integration_test.bzl b/tools/bazel_integration_test/bazel_integration_test.bzl index 92d64e5dfa..704a525adb 100644 --- a/tools/bazel_integration_test/bazel_integration_test.bzl +++ b/tools/bazel_integration_test/bazel_integration_test.bzl @@ -88,6 +88,9 @@ def bazel_integration_test(name, **kwargs): workspace_files = workspace_files, ) + tags = kwargs.pop("tags", []) + tags.append("integration-test") + py_test( name = name, srcs = [Label("//tools/bazel_integration_test:test_runner.py")], @@ -100,5 +103,6 @@ def bazel_integration_test(name, **kwargs): "_%s_config" % name, workspace_files, ], + tags = tags, **kwargs ) From d314e96aaab18f60df50400d61214f7c1d71b8e6 Mon Sep 17 00:00:00 2001 From: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Date: Wed, 12 Oct 2022 14:41:26 -0700 Subject: [PATCH 052/234] chore: update go dependencies (#854) --- BUILD | 3 +- gazelle/bazel_gazelle.pr1095.patch | 19 --- gazelle/deps.bzl | 232 +++++++++++++++++++++-------- go.mod | 20 ++- go.sum | 120 ++++++++++----- internal_deps.bzl | 15 +- internal_setup.bzl | 2 +- 7 files changed, 277 insertions(+), 134 deletions(-) delete mode 100644 gazelle/bazel_gazelle.pr1095.patch diff --git a/BUILD b/BUILD index 3385ee4914..31962d234d 100644 --- a/BUILD +++ b/BUILD @@ -67,10 +67,11 @@ filegroup( # See https://github.com/bazelbuild/bazel-gazelle#running-gazelle-with-bazel # gazelle:prefix github.com/bazelbuild/rules_python # gazelle:exclude bazel-out +# gazelle:exclude examples/** gazelle(name = "gazelle") gazelle( - name = "update_go_deps", + name = "gazelle_update_repos", args = [ "-from_file=go.mod", "-to_macro=gazelle/deps.bzl%gazelle_deps", diff --git a/gazelle/bazel_gazelle.pr1095.patch b/gazelle/bazel_gazelle.pr1095.patch deleted file mode 100644 index a417c94944..0000000000 --- a/gazelle/bazel_gazelle.pr1095.patch +++ /dev/null @@ -1,19 +0,0 @@ -commit b1c61c0b77648f7345a7c42cce941e32d87c84bf -Author: Alex Eagle -Date: Wed Aug 18 17:55:13 2021 -0700 - - Merge the private attribute - -diff --git a/rule/merge.go b/rule/merge.go -index d5fbe94..e13e547 100644 ---- a/rule/merge.go -+++ b/rule/merge.go -@@ -79,6 +79,8 @@ func MergeRules(src, dst *Rule, mergeable map[string]bool, filename string) { - } - } - } -+ -+ dst.private = src.private - } - - // mergeExprs combines information from src and dst and returns a merged diff --git a/gazelle/deps.bzl b/gazelle/deps.bzl index 1d53fdd99f..15150c9afb 100644 --- a/gazelle/deps.bzl +++ b/gazelle/deps.bzl @@ -8,30 +8,42 @@ def go_repository(name, **kwargs): def gazelle_deps(): "Fetch go dependencies" + go_repository( + name = "co_honnef_go_tools", + importpath = "honnef.co/go/tools", + sum = "h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs=", + version = "v0.0.0-20190523083050-ea95bdfd59fc", + ) go_repository( name = "com_github_bazelbuild_bazel_gazelle", importpath = "github.com/bazelbuild/bazel-gazelle", - sum = "h1:Ks6YN+WkOv2lYWlvf7ksxUpLvrDbBHPBXXUrBFQ3BZM=", - version = "v0.23.0", + sum = "h1:+/ZhUxlDy4XnyMIGeKkbRZoIGssy1eO51GijwIvvuwE=", + version = "v0.27.0", ) go_repository( name = "com_github_bazelbuild_buildtools", build_naming_convention = "go_default_library", importpath = "github.com/bazelbuild/buildtools", - sum = "h1:Et1IIXrXwhpDvR5wH9REPEZ0sUtzUoJSq19nfmBqzBY=", - version = "v0.0.0-20200718160251-b1667ff58f71", + sum = "h1:jhiMzJ+8unnLRtV8rpbWBFE9pFNzIqgUTyZU5aA++w8=", + version = "v0.0.0-20221004120235-7186f635531b", ) go_repository( name = "com_github_bazelbuild_rules_go", importpath = "github.com/bazelbuild/rules_go", - sum = "h1:wzbawlkLtl2ze9w/312NHZ84c7kpUCtlkD8HgFY27sw=", - version = "v0.0.0-20190719190356-6dae44dc5cab", + sum = "h1:ViPR65vOrg74JKntAUFY6qZkheBKGB6to7wFd8gCRU4=", + version = "v0.35.0", ) go_repository( name = "com_github_bmatcuk_doublestar", importpath = "github.com/bmatcuk/doublestar", - sum = "h1:oC24CykoSAB8zd7XgruHo33E0cHJf/WhQA/7BeXj+x0=", - version = "v1.2.2", + sum = "h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0=", + version = "v1.3.4", + ) + go_repository( + name = "com_github_bmatcuk_doublestar_v4", + importpath = "github.com/bmatcuk/doublestar/v4", + sum = "h1:Qu+u9wR3Vd89LnlLMHvnZ5coJMWKQamqdz9/p5GNthA=", + version = "v4.2.0", ) go_repository( name = "com_github_burntsushi_toml", @@ -40,22 +52,58 @@ def gazelle_deps(): version = "v0.3.1", ) go_repository( - name = "com_github_davecgh_go_spew", - importpath = "github.com/davecgh/go-spew", - sum = "h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=", - version = "v1.1.1", + name = "com_github_census_instrumentation_opencensus_proto", + importpath = "github.com/census-instrumentation/opencensus-proto", + sum = "h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=", + version = "v0.2.1", + ) + go_repository( + name = "com_github_chzyer_logex", + importpath = "github.com/chzyer/logex", + sum = "h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=", + version = "v1.1.10", + ) + go_repository( + name = "com_github_chzyer_readline", + importpath = "github.com/chzyer/readline", + sum = "h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=", + version = "v0.0.0-20180603132655-2972be24d48e", + ) + go_repository( + name = "com_github_chzyer_test", + importpath = "github.com/chzyer/test", + sum = "h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=", + version = "v0.0.0-20180213035817-a1ea475d72b1", + ) + go_repository( + name = "com_github_client9_misspell", + importpath = "github.com/client9/misspell", + sum = "h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=", + version = "v0.3.4", ) go_repository( name = "com_github_emirpasic_gods", importpath = "github.com/emirpasic/gods", - sum = "h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=", - version = "v1.12.0", + sum = "h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=", + version = "v1.18.1", + ) + go_repository( + name = "com_github_envoyproxy_go_control_plane", + importpath = "github.com/envoyproxy/go-control-plane", + sum = "h1:4cmBvAEBNJaGARUEs3/suWRyfyBfhf7I60WBZq+bv2w=", + version = "v0.9.1-0.20191026205805-5f8ba28d4473", + ) + go_repository( + name = "com_github_envoyproxy_protoc_gen_validate", + importpath = "github.com/envoyproxy/protoc-gen-validate", + sum = "h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=", + version = "v0.1.0", ) go_repository( name = "com_github_fsnotify_fsnotify", importpath = "github.com/fsnotify/fsnotify", - sum = "h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=", - version = "v1.4.7", + sum = "h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=", + version = "v1.5.4", ) go_repository( name = "com_github_ghodss_yaml", @@ -64,41 +112,40 @@ def gazelle_deps(): version = "v1.0.0", ) go_repository( - name = "com_github_google_go_cmp", - importpath = "github.com/google/go-cmp", - sum = "h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=", - version = "v0.5.4", + name = "com_github_golang_glog", + importpath = "github.com/golang/glog", + sum = "h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=", + version = "v0.0.0-20160126235308-23def4e6c14b", ) go_repository( - name = "com_github_google_uuid", - importpath = "github.com/google/uuid", - sum = "h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=", - version = "v1.3.0", + name = "com_github_golang_mock", + importpath = "github.com/golang/mock", + sum = "h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=", + version = "v1.6.0", ) - go_repository( - name = "com_github_kr_pretty", - importpath = "github.com/kr/pretty", - sum = "h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=", - version = "v0.1.0", + name = "com_github_golang_protobuf", + importpath = "github.com/golang/protobuf", + sum = "h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=", + version = "v1.5.2", ) go_repository( - name = "com_github_kr_pty", - importpath = "github.com/kr/pty", - sum = "h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=", - version = "v1.1.1", + name = "com_github_google_go_cmp", + importpath = "github.com/google/go-cmp", + sum = "h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=", + version = "v0.5.9", ) go_repository( - name = "com_github_kr_text", - importpath = "github.com/kr/text", - sum = "h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=", - version = "v0.1.0", + name = "com_github_google_uuid", + importpath = "github.com/google/uuid", + sum = "h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=", + version = "v1.3.0", ) go_repository( name = "com_github_pelletier_go_toml", importpath = "github.com/pelletier/go-toml", - sum = "h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=", - version = "v1.2.0", + sum = "h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=", + version = "v1.9.5", ) go_repository( name = "com_github_pmezard_go_difflib", @@ -106,54 +153,119 @@ def gazelle_deps(): sum = "h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=", version = "v1.0.0", ) - + go_repository( + name = "com_github_prometheus_client_model", + importpath = "github.com/prometheus/client_model", + sum = "h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=", + version = "v0.0.0-20190812154241-14fe0d1b01d4", + ) + go_repository( + name = "com_github_yuin_goldmark", + importpath = "github.com/yuin/goldmark", + sum = "h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=", + version = "v1.4.13", + ) + go_repository( + name = "com_google_cloud_go", + importpath = "cloud.google.com/go", + sum = "h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ=", + version = "v0.26.0", + ) go_repository( name = "in_gopkg_check_v1", importpath = "gopkg.in/check.v1", - sum = "h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=", - version = "v1.0.0-20180628173108-788fd7840127", + sum = "h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=", + version = "v0.0.0-20161208181325-20d25e280405", ) go_repository( name = "in_gopkg_yaml_v2", importpath = "gopkg.in/yaml.v2", - sum = "h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=", - version = "v2.2.2", + sum = "h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=", + version = "v2.4.0", + ) + go_repository( + name = "net_starlark_go", + importpath = "go.starlark.net", + sum = "h1:xwwDQW5We85NaTk2APgoN9202w/l0DVGp+GZMfsrh7s=", + version = "v0.0.0-20210223155950-e043a3d3c984", + ) + go_repository( + name = "org_golang_google_appengine", + importpath = "google.golang.org/appengine", + sum = "h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=", + version = "v1.4.0", + ) + go_repository( + name = "org_golang_google_genproto", + importpath = "google.golang.org/genproto", + sum = "h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=", + version = "v0.0.0-20200526211855-cb27e3aa2013", + ) + go_repository( + name = "org_golang_google_grpc", + importpath = "google.golang.org/grpc", + sum = "h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg=", + version = "v1.27.0", + ) + go_repository( + name = "org_golang_google_protobuf", + importpath = "google.golang.org/protobuf", + sum = "h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=", + version = "v1.28.0", ) go_repository( name = "org_golang_x_crypto", importpath = "golang.org/x/crypto", - sum = "h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=", - version = "v0.0.0-20191011191535-87dc89f01550", + sum = "h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=", + version = "v0.0.0-20190308221718-c2843e01d9a2", + ) + go_repository( + name = "org_golang_x_exp", + importpath = "golang.org/x/exp", + sum = "h1:c2HOrn5iMezYjSlGPncknSEr/8x5LELb/ilJbXi9DEA=", + version = "v0.0.0-20190121172915-509febef88a4", + ) + go_repository( + name = "org_golang_x_lint", + importpath = "golang.org/x/lint", + sum = "h1:XQyxROzUlZH+WIQwySDgnISgOivlhjIEwaQaJEJrrN0=", + version = "v0.0.0-20190313153728-d0100b6bd8b3", ) go_repository( name = "org_golang_x_mod", importpath = "golang.org/x/mod", - sum = "h1:Kvvh58BN8Y9/lBi7hTekvtMpm07eUZ0ck5pRHpsMWrY=", - version = "v0.4.1", + sum = "h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=", + version = "v0.6.0-dev.0.20220419223038-86c51ed26bb4", ) go_repository( name = "org_golang_x_net", importpath = "golang.org/x/net", - sum = "h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=", - version = "v0.0.0-20190620200207-3b0461eec859", + sum = "h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=", + version = "v0.0.0-20220722155237-a158d28d115b", + ) + go_repository( + name = "org_golang_x_oauth2", + importpath = "golang.org/x/oauth2", + sum = "h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=", + version = "v0.0.0-20180821212333-d2e6202438be", ) go_repository( name = "org_golang_x_sync", importpath = "golang.org/x/sync", - sum = "h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=", - version = "v0.0.0-20190911185100-cd5d95a43a6e", + sum = "h1:0SH2R3f1b1VmIMG7BXbEZCBUu2dKmHschSmjqGUrW8A=", + version = "v0.0.0-20220907140024-f12130a52804", ) go_repository( name = "org_golang_x_sys", importpath = "golang.org/x/sys", - sum = "h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=", - version = "v0.0.0-20190412213103-97732733099d", + sum = "h1:k5II8e6QD8mITdi+okbbmR/cIyEbeXLBhy5Ha4nevyc=", + version = "v0.0.0-20221010170243-090e33056c14", ) go_repository( name = "org_golang_x_text", importpath = "golang.org/x/text", - sum = "h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=", - version = "v0.3.0", + sum = "h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=", + version = "v0.3.7", ) go_repository( name = "org_golang_x_tools", @@ -161,12 +273,12 @@ def gazelle_deps(): "gazelle:exclude **/testdata/**/*", ], importpath = "golang.org/x/tools", - sum = "h1:aZzprAO9/8oim3qStq3wc1Xuxx4QmAGriC4VU4ojemQ=", - version = "v0.0.0-20191119224855-298f0cb1881e", + sum = "h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=", + version = "v0.1.12", ) go_repository( name = "org_golang_x_xerrors", importpath = "golang.org/x/xerrors", - sum = "h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=", - version = "v0.0.0-20191204190536-9bdfabe68543", + sum = "h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=", + version = "v0.0.0-20200804184101-5ec99f83aff1", ) diff --git a/go.mod b/go.mod index 7903ca1b32..0afdf52445 100644 --- a/go.mod +++ b/go.mod @@ -1,14 +1,20 @@ module github.com/bazelbuild/rules_python -go 1.18 +go 1.19 require ( - github.com/bazelbuild/bazel-gazelle v0.23.0 - github.com/bazelbuild/buildtools v0.0.0-20200718160251-b1667ff58f71 - github.com/bazelbuild/rules_go v0.0.0-20190719190356-6dae44dc5cab - github.com/bmatcuk/doublestar v1.2.2 - github.com/emirpasic/gods v1.12.0 + github.com/bazelbuild/bazel-gazelle v0.27.0 + github.com/bazelbuild/buildtools v0.0.0-20221004120235-7186f635531b + github.com/bazelbuild/rules_go v0.35.0 + github.com/bmatcuk/doublestar v1.3.4 + github.com/emirpasic/gods v1.18.1 github.com/ghodss/yaml v1.0.0 github.com/google/uuid v1.3.0 - gopkg.in/yaml.v2 v2.2.8 + gopkg.in/yaml.v2 v2.4.0 +) + +require ( + github.com/google/go-cmp v0.5.9 // indirect + golang.org/x/sys v0.0.0-20221010170243-090e33056c14 // indirect + golang.org/x/tools v0.1.12 // indirect ) diff --git a/go.sum b/go.sum index 4a8161ff6b..1a952616ba 100644 --- a/go.sum +++ b/go.sum @@ -1,48 +1,94 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/bazelbuild/bazel-gazelle v0.23.0 h1:Ks6YN+WkOv2lYWlvf7ksxUpLvrDbBHPBXXUrBFQ3BZM= -github.com/bazelbuild/bazel-gazelle v0.23.0/go.mod h1:3mHi4TYn0QxwdMKPJfj3FKhZxYgWm46DjWQQPOg20BY= -github.com/bazelbuild/buildtools v0.0.0-20200718160251-b1667ff58f71 h1:Et1IIXrXwhpDvR5wH9REPEZ0sUtzUoJSq19nfmBqzBY= -github.com/bazelbuild/buildtools v0.0.0-20200718160251-b1667ff58f71/go.mod h1:5JP0TXzWDHXv8qvxRC4InIazwdyDseBDbzESUMKk1yU= -github.com/bazelbuild/rules_go v0.0.0-20190719190356-6dae44dc5cab h1:wzbawlkLtl2ze9w/312NHZ84c7kpUCtlkD8HgFY27sw= -github.com/bazelbuild/rules_go v0.0.0-20190719190356-6dae44dc5cab/go.mod h1:MC23Dc/wkXEyk3Wpq6lCqz0ZAYOZDw2DR5y3N1q2i7M= -github.com/bmatcuk/doublestar v1.2.2 h1:oC24CykoSAB8zd7XgruHo33E0cHJf/WhQA/7BeXj+x0= -github.com/bmatcuk/doublestar v1.2.2/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= -github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/bazelbuild/bazel-gazelle v0.27.0 h1:+/ZhUxlDy4XnyMIGeKkbRZoIGssy1eO51GijwIvvuwE= +github.com/bazelbuild/bazel-gazelle v0.27.0/go.mod h1:2K6B42/loq8ext4JObmam4gTYx4En1MUSzHFKQF8hPM= +github.com/bazelbuild/buildtools v0.0.0-20221004120235-7186f635531b h1:jhiMzJ+8unnLRtV8rpbWBFE9pFNzIqgUTyZU5aA++w8= +github.com/bazelbuild/buildtools v0.0.0-20221004120235-7186f635531b/go.mod h1:689QdV3hBP7Vo9dJMmzhoYIyo/9iMhEmHkJcnaPRCbo= +github.com/bazelbuild/rules_go v0.35.0 h1:ViPR65vOrg74JKntAUFY6qZkheBKGB6to7wFd8gCRU4= +github.com/bazelbuild/rules_go v0.35.0/go.mod h1:ahciH68Viyxtm/gvCQplaAiu8buhf/b+gWswcPjFixI= +github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0= +github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +go.starlark.net v0.0.0-20210223155950-e043a3d3c984/go.mod h1:t3mmBBPzAVvK0L0n1drDmrQsJ8FoIx4INCqVMTr/Zo0= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20221010170243-090e33056c14 h1:k5II8e6QD8mITdi+okbbmR/cIyEbeXLBhy5Ha4nevyc= +golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e h1:aZzprAO9/8oim3qStq3wc1Xuxx4QmAGriC4VU4ojemQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal_deps.bzl b/internal_deps.bzl index 7d6e3328c4..8a089f053e 100644 --- a/internal_deps.bzl +++ b/internal_deps.bzl @@ -37,23 +37,20 @@ def rules_python_internal_deps(): maybe( http_archive, name = "io_bazel_rules_go", - sha256 = "f2dcd210c7095febe54b804bb1cd3a58fe8435a909db2ec04e31542631cf715c", + sha256 = "099a9fb96a376ccbbb7d291ed4ecbdfd42f6bc822ab77ae6f1b5cb9e914e94fa", urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.31.0/rules_go-v0.31.0.zip", - "https://github.com/bazelbuild/rules_go/releases/download/v0.31.0/rules_go-v0.31.0.zip", + "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.35.0/rules_go-v0.35.0.zip", + "https://github.com/bazelbuild/rules_go/releases/download/v0.35.0/rules_go-v0.35.0.zip", ], ) maybe( http_archive, name = "bazel_gazelle", - patch_args = ["-p1"], - patches = ["@rules_python//gazelle:bazel_gazelle.pr1095.patch"], - sha256 = "0bb8056ab9ed4cbcab5b74348d8530c0e0b939987b0cfe36c1ab53d35a99e4de", - strip_prefix = "bazel-gazelle-2834ea44b3ec6371c924baaf28704730ec9d4559", + sha256 = "efbbba6ac1a4fd342d5122cbdfdb82aeb2cf2862e35022c752eaddffada7c3f3", urls = [ - # No release since March, and we need subsequent fixes - "https://github.com/bazelbuild/bazel-gazelle/archive/2834ea44b3ec6371c924baaf28704730ec9d4559.zip", + "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.27.0/bazel-gazelle-v0.27.0.tar.gz", + "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.27.0/bazel-gazelle-v0.27.0.tar.gz", ], ) diff --git a/internal_setup.bzl b/internal_setup.bzl index 5965665b05..f4d3a1a8db 100644 --- a/internal_setup.bzl +++ b/internal_setup.bzl @@ -38,6 +38,6 @@ def rules_python_internal_setup(): go_rules_dependencies() - go_register_toolchains(version = "1.18") + go_register_toolchains(version = "1.19.2") gazelle_dependencies() From 8dff1751629915554c1b8f61ba4f5ce2bf3442cb Mon Sep 17 00:00:00 2001 From: Chris Love <335402+chrislovecnm@users.noreply.github.com> Date: Tue, 25 Oct 2022 14:04:05 -0600 Subject: [PATCH 053/234] Updating docs (#868) --- CONTRIBUTING.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 41dbd96fc2..8092f361fd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,6 +6,7 @@ just a few small guidelines you need to follow. ## Formatting Starlark files should be formatted by buildifier. +Otherwise the Buildkite CI will yell at you about formatting/linting violations. We suggest using a pre-commit hook to automate this. First [install pre-commit](https://pre-commit.com/#installation), then run @@ -13,8 +14,15 @@ then run ```shell pre-commit install ``` +### Running buildifer manually -Otherwise the Buildkite CI will yell at you about formatting/linting violations. +If you choose to run buildifier manually, run the following command: + +```shell +$ buildifier --lint=fix --warnings=native-py -warnings=all WORKSPACE +``` + +Replace the argument "WORKSPACE" with the file that you are linting. ## Contributor License Agreement From b095f6fbdf0ff1285d6364727a1fa5bbdf0e7335 Mon Sep 17 00:00:00 2001 From: Chris Love <335402+chrislovecnm@users.noreply.github.com> Date: Tue, 25 Oct 2022 14:06:04 -0600 Subject: [PATCH 054/234] Updating Gazelle version in example (#857) --- examples/build_file_generation/WORKSPACE | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/examples/build_file_generation/WORKSPACE b/examples/build_file_generation/WORKSPACE index 63ea962920..ec5c10fb32 100644 --- a/examples/build_file_generation/WORKSPACE +++ b/examples/build_file_generation/WORKSPACE @@ -12,22 +12,19 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") # needed platforms. http_archive( name = "io_bazel_rules_go", - sha256 = "69de5c704a05ff37862f7e0f5534d4f479418afc21806c887db544a316f3cb6b", + sha256 = "099a9fb96a376ccbbb7d291ed4ecbdfd42f6bc822ab77ae6f1b5cb9e914e94fa", urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.27.0/rules_go-v0.27.0.tar.gz", - "https://github.com/bazelbuild/rules_go/releases/download/v0.27.0/rules_go-v0.27.0.tar.gz", + "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.35.0/rules_go-v0.35.0.zip", + "https://github.com/bazelbuild/rules_go/releases/download/v0.35.0/rules_go-v0.35.0.zip", ], ) -# NB: bazel-gazelle version must be after 18 August 2021 -# to include https://github.com/bazelbuild/bazel-gazelle/commit/2834ea4 http_archive( name = "bazel_gazelle", - sha256 = "fd8d852ebcb770b41c1c933fc3085b4a23e1426a1af4e791d39b67bb8d894eb7", - strip_prefix = "bazel-gazelle-41b542f9b0fefe916a95ca5460458abf916f5fe5", + sha256 = "efbbba6ac1a4fd342d5122cbdfdb82aeb2cf2862e35022c752eaddffada7c3f3", urls = [ - # No release since March, and we need subsequent fixes - "https://github.com/bazelbuild/bazel-gazelle/archive/41b542f9b0fefe916a95ca5460458abf916f5fe5.zip", + "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.27.0/bazel-gazelle-v0.27.0.tar.gz", + "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.27.0/bazel-gazelle-v0.27.0.tar.gz", ], ) @@ -36,7 +33,7 @@ load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_depe go_rules_dependencies() -go_register_toolchains(version = "1.16.5") +go_register_toolchains(version = "1.18.3") gazelle_dependencies() From 6d9080f5d3ea171e626cf19263c576f9308e8009 Mon Sep 17 00:00:00 2001 From: Derek Cormier Date: Wed, 26 Oct 2022 10:41:58 -0700 Subject: [PATCH 055/234] Update bzlmod example to use latest Bazel release (#867) Update bzlmod example to use latest Bazel release --- examples/BUILD | 2 ++ internal_setup.bzl | 7 +++++++ .../bazel_integration_test.bzl | 21 ++++++++++++++----- tools/bazel_integration_test/test_runner.py | 9 ++++++++ version.bzl | 3 +++ 5 files changed, 37 insertions(+), 5 deletions(-) diff --git a/examples/BUILD b/examples/BUILD index ee4d7e4861..fcdbdb1a28 100644 --- a/examples/BUILD +++ b/examples/BUILD @@ -40,4 +40,6 @@ bazel_integration_test( bazel_integration_test( name = "bzlmod_example", + bzlmod = True, + override_bazel_version = "6.0.0rc1", ) diff --git a/internal_setup.bzl b/internal_setup.bzl index f4d3a1a8db..beb26e8a81 100644 --- a/internal_setup.bzl +++ b/internal_setup.bzl @@ -31,6 +31,13 @@ def rules_python_internal_setup(): # Depend on the Bazel binaries for running bazel-in-bazel tests bazel_binaries(versions = SUPPORTED_BAZEL_VERSIONS) + # Bazel 5.3.0 has bzlmod bugs so we use 6.0 prerelease for the bzlmod example. + # SUPPORTED_BAZEL_VERSIONS doesn't currently support multiple versions. For now, + # we only want to run the bzlmod example with a separate version. + bazel_binaries(versions = [ + "6.0.0rc1", + ]) + bazel_skylib_workspace() # gazelle:repository_macro gazelle/deps.bzl%gazelle_deps diff --git a/tools/bazel_integration_test/bazel_integration_test.bzl b/tools/bazel_integration_test/bazel_integration_test.bzl index 704a525adb..93059fb8da 100644 --- a/tools/bazel_integration_test/bazel_integration_test.bzl +++ b/tools/bazel_integration_test/bazel_integration_test.bzl @@ -1,9 +1,9 @@ "Define a rule for running bazel test under Bazel" -load("//:version.bzl", "SUPPORTED_BAZEL_VERSIONS") +load("//:version.bzl", "SUPPORTED_BAZEL_VERSIONS", "bazel_version_to_binary_label") load("//python:defs.bzl", "py_test") -BAZEL_BINARY = "@build_bazel_bazel_%s//:bazel_binary" % SUPPORTED_BAZEL_VERSIONS[0].replace(".", "_") +BAZEL_BINARY = bazel_version_to_binary_label(SUPPORTED_BAZEL_VERSIONS[0]) _ATTRS = { "bazel_binary": attr.label( @@ -19,6 +19,10 @@ It is assumed by the test runner that the bazel binary is found at label_workspa Note that if a command contains a bare `--` argument, the --test_arg passed to Bazel will appear before it. """, ), + "bzlmod": attr.bool( + default = False, + doc = """Whether the test uses bzlmod.""", + ), "workspace_files": attr.label( doc = """A filegroup of all files in the workspace-under-test necessary to run the test.""", ), @@ -44,12 +48,14 @@ You probably need to run {{ "workspaceRoot": "{TMPL_workspace_root}", "bazelBinaryWorkspace": "{TMPL_bazel_binary_workspace}", - "bazelCommands": [ {TMPL_bazel_commands} ] + "bazelCommands": [ {TMPL_bazel_commands} ], + "bzlmod": {TMPL_bzlmod} }} """.format( TMPL_workspace_root = ctx.files.workspace_files[0].dirname, TMPL_bazel_binary_workspace = ctx.attr.bazel_binary.label.workspace_name, TMPL_bazel_commands = ", ".join(["\"%s\"" % s for s in ctx.attr.bazel_commands]), + TMPL_bzlmod = str(ctx.attr.bzlmod).lower(), ), ) @@ -64,11 +70,13 @@ _config = rule( attrs = _ATTRS, ) -def bazel_integration_test(name, **kwargs): +def bazel_integration_test(name, override_bazel_version = None, bzlmod = False, **kwargs): """Wrapper macro to set default srcs and run a py_test with config Args: name: name of the resulting py_test + override_bazel_version: bazel version to use in test + bzlmod: whether the test uses bzlmod **kwargs: additional attributes like timeout and visibility """ @@ -83,9 +91,12 @@ def bazel_integration_test(name, **kwargs): ) workspace_files = kwargs.pop("workspace_files", "_%s_sources" % name) + bazel_binary = BAZEL_BINARY if not override_bazel_version else bazel_version_to_binary_label(override_bazel_version) _config( name = "_%s_config" % name, workspace_files = workspace_files, + bazel_binary = bazel_binary, + bzlmod = bzlmod, ) tags = kwargs.pop("tags", []) @@ -98,7 +109,7 @@ def bazel_integration_test(name, **kwargs): args = [native.package_name() + "/_%s_config.json" % name], deps = [Label("//python/runfiles")], data = [ - BAZEL_BINARY, + bazel_binary, "//:distribution", "_%s_config" % name, workspace_files, diff --git a/tools/bazel_integration_test/test_runner.py b/tools/bazel_integration_test/test_runner.py index ce81274d5e..31bb62792e 100644 --- a/tools/bazel_integration_test/test_runner.py +++ b/tools/bazel_integration_test/test_runner.py @@ -53,6 +53,15 @@ def main(conf_file): % os.environ["TEST_SRCDIR"] ) + # TODO: --override_module isn't supported in the current BAZEL_VERSION (5.2.0) + # This condition and attribute can be removed when bazel is updated for + # the rest of rules_python. + if (config["bzlmod"]): + bazel_args.append( + "--override_module=rules_python=%s/rules_python" + % os.environ["TEST_SRCDIR"] + ) + # Bazel's wrapper script needs this or you get # 2020/07/13 21:58:11 could not get the user's cache directory: $HOME is not defined os.environ["HOME"] = str(tmp_homedir) diff --git a/version.bzl b/version.bzl index 829762a577..a73ef4d968 100644 --- a/version.bzl +++ b/version.bzl @@ -28,3 +28,6 @@ SUPPORTED_BAZEL_VERSIONS = [ # TODO: add LTS versions of bazel like 1.0.0, 2.0.0 BAZEL_VERSION, ] + +def bazel_version_to_binary_label(version): + return "@build_bazel_bazel_%s//:bazel_binary" % version.replace(".", "_") From f8945f469402476b9320e64c6fee0789f1f79abf Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Wed, 2 Nov 2022 09:10:25 -0700 Subject: [PATCH 056/234] Remove defunct owners, add new owners (#873) * Remove brandjon, lberki, thundergolfer; they're no longer active in the repo. * Add rickeylev as replacement owner. --- .github/CODEOWNERS | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 073f6989dd..a35be61b52 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,21 +1,6 @@ # NB: Last matching rule takes precedence in CODEOWNERS. -# Fall-through to community maintainers. -* @thundergolfer - -# Core Python rules belong to the Bazel team. -/python/ @brandjon @lberki -# But not everything under python/ is the core Python rules. -/python/pip.bzl @thundergolfer -/python/requirements.txt @thundergolfer +* @rickeylev # Directory containing the Gazelle extension and Go code. /gazelle/ @f0rmiga - -# The proposals dir corresponds to the Bazel proposals process, documented -# here: https://bazel.build/designs/index.html -/proposals/ @brandjon @lberki - -# Certain repo metadata files should stay as-is, particularly these. -/LICENSE @brandjon @lberki -/CONTRIBUTING.md @brandjon @lberki From 7f65a6dd3fcef5742ac3c5bf59957774a30785da Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Wed, 2 Nov 2022 11:19:57 -0700 Subject: [PATCH 057/234] Add hrfuller as code owner for pip_parse (#874) --- .github/CODEOWNERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index a35be61b52..ed4bcf3046 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,3 +4,6 @@ # Directory containing the Gazelle extension and Go code. /gazelle/ @f0rmiga + +# pip_parse related code +/python/pip_install/ @hrfuller From a08cc0ecb0d97cba374ef01c88a60c4055898cc6 Mon Sep 17 00:00:00 2001 From: Ekesh Kumar <0ekesh@gmail.com> Date: Wed, 2 Nov 2022 13:37:41 -0500 Subject: [PATCH 058/234] Update `pip_install` to `pip_parse` in README.md (#852) `pip_install` is deprecated and will be removed in a future release. The example has already been updated to `pip_parse`, but the caption has not been updated yet. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 944493c6a9..c1ba8f1699 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ target in the appropriate wheel repo. ### Installing third_party packages -To add pip dependencies to your `WORKSPACE`, load the `pip_install` function, and call it to create the +To add pip dependencies to your `WORKSPACE`, load the `pip_parse` function, and call it to create the central external repo and individual wheel external repos. From b1546b6f2bd6806c5a941c81b6a1baca33c34549 Mon Sep 17 00:00:00 2001 From: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Date: Wed, 2 Nov 2022 12:52:35 -0700 Subject: [PATCH 059/234] chore: add f0rmiga as codeowner for toolchains (#875) --- .github/CODEOWNERS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ed4bcf3046..54374b30ad 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -5,5 +5,10 @@ # Directory containing the Gazelle extension and Go code. /gazelle/ @f0rmiga +# Toolchains +/python/repositories.bzl @f0rmiga +/python/private/toolchains_repo.bzl @f0rmiga +/python/tests/toolchains/ @f0rmiga + # pip_parse related code /python/pip_install/ @hrfuller From bd42ad2becc8b890424612ae91d652a3b9bb82e3 Mon Sep 17 00:00:00 2001 From: William Smith <87392567+william-smith-skydio@users.noreply.github.com> Date: Fri, 4 Nov 2022 15:20:51 -0700 Subject: [PATCH 060/234] Support annotations on pip packages with extras. (#865) * Support annotations on pip packages with extras. E.g., the following requirement: ``` requests[security]>=2.8.1 ``` This is handled correctly by all of the other plumbing, but trying to add an annotation to `requests` will fail. This is because annotations have separate logic for parsing requirements in the generated .bzl file. It would previously turn the requirement into `requests[security]` rather than just `requests`. * Add test verifying that annotations work for packages with extras. --- examples/pip_parse_vendored/requirements.bzl | 2 +- .../pip_repository_annotations/.gitignore | 1 + examples/pip_repository_annotations/BUILD | 12 +++++++++-- examples/pip_repository_annotations/WORKSPACE | 13 ++++++++++++ .../pip_repository_annotations_test.py | 20 +++++++++++++++++++ .../requirements.in | 1 + .../requirements.txt | 20 +++++++++++++++++++ .../parse_requirements_to_bzl.py | 2 +- 8 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 examples/pip_repository_annotations/.gitignore diff --git a/examples/pip_parse_vendored/requirements.bzl b/examples/pip_parse_vendored/requirements.bzl index 33199b07aa..6f1fbd0b75 100644 --- a/examples/pip_parse_vendored/requirements.bzl +++ b/examples/pip_parse_vendored/requirements.bzl @@ -38,7 +38,7 @@ def entry_point(pkg, script = None): def _get_annotation(requirement): # This expects to parse `setuptools==58.2.0 --hash=sha256:2551203ae6955b9876741a26ab3e767bb3242dafe86a32a749ea0d78b6792f11` # down wo `setuptools`. - name = requirement.split(" ")[0].split("=")[0] + name = requirement.split(" ")[0].split("=")[0].split("[")[0] return _annotations.get(name) def install_deps(**whl_library_kwargs): diff --git a/examples/pip_repository_annotations/.gitignore b/examples/pip_repository_annotations/.gitignore new file mode 100644 index 0000000000..a6ef824c1f --- /dev/null +++ b/examples/pip_repository_annotations/.gitignore @@ -0,0 +1 @@ +/bazel-* diff --git a/examples/pip_repository_annotations/BUILD b/examples/pip_repository_annotations/BUILD index 4fd124e6c7..84089f77d0 100644 --- a/examples/pip_repository_annotations/BUILD +++ b/examples/pip_repository_annotations/BUILD @@ -16,9 +16,13 @@ compile_pip_requirements( py_test( name = "pip_parse_annotations_test", srcs = ["pip_repository_annotations_test.py"], - env = {"WHEEL_PKG_DIR": "pip_parsed_wheel"}, + env = { + "REQUESTS_PKG_DIR": "pip_parsed_requests", + "WHEEL_PKG_DIR": "pip_parsed_wheel", + }, main = "pip_repository_annotations_test.py", deps = [ + "@pip_parsed_requests//:pkg", "@pip_parsed_wheel//:pkg", "@rules_python//python/runfiles", ], @@ -27,10 +31,14 @@ py_test( py_test( name = "pip_install_annotations_test", srcs = ["pip_repository_annotations_test.py"], - env = {"WHEEL_PKG_DIR": "pip_installed_wheel"}, + env = { + "REQUESTS_PKG_DIR": "pip_installed_requests", + "WHEEL_PKG_DIR": "pip_installed_wheel", + }, main = "pip_repository_annotations_test.py", deps = [ requirement("wheel"), + requirement("requests"), "@rules_python//python/runfiles", ], ) diff --git a/examples/pip_repository_annotations/WORKSPACE b/examples/pip_repository_annotations/WORKSPACE index aeea84207c..8fd998b7ae 100644 --- a/examples/pip_repository_annotations/WORKSPACE +++ b/examples/pip_repository_annotations/WORKSPACE @@ -30,6 +30,19 @@ load("@rules_python//python:pip.bzl", "package_annotation", "pip_install", "pip_ # package. For details on `package_annotation` and it's uses, see the # docs at @rules_python//docs:pip.md`. ANNOTATIONS = { + # This annotation verifies that annotations work correctly for pip packages with extras + # specified, in this case requests[security]. + "requests": package_annotation( + additive_build_content = """\ +load("@bazel_skylib//rules:write_file.bzl", "write_file") +write_file( + name = "generated_file", + out = "generated_file.txt", + content = ["Hello world from requests"], +) +""", + data = [":generated_file"], + ), "wheel": package_annotation( additive_build_content = """\ load("@bazel_skylib//rules:write_file.bzl", "write_file") diff --git a/examples/pip_repository_annotations/pip_repository_annotations_test.py b/examples/pip_repository_annotations/pip_repository_annotations_test.py index e78880ae72..d53b9bccaa 100644 --- a/examples/pip_repository_annotations/pip_repository_annotations_test.py +++ b/examples/pip_repository_annotations/pip_repository_annotations_test.py @@ -90,6 +90,26 @@ def test_data_exclude_glob(self): self.assertTrue(Path(metadata_path).exists()) self.assertFalse(Path(wheel_path).exists()) + def requests_pkg_dir(self) -> str: + env = os.environ.get("REQUESTS_PKG_DIR") + self.assertIsNotNone(env) + return env + + def test_extra(self): + # This test verifies that annotations work correctly for pip packages with extras + # specified, in this case requests[security]. + r = runfiles.Create() + rpath = r.Rlocation( + "pip_repository_annotations_example/external/{}/generated_file.txt".format( + self.requests_pkg_dir() + ) + ) + generated_file = Path(rpath) + self.assertTrue(generated_file.exists()) + + content = generated_file.read_text().rstrip() + self.assertEqual(content, "Hello world from requests") + if __name__ == "__main__": unittest.main() diff --git a/examples/pip_repository_annotations/requirements.in b/examples/pip_repository_annotations/requirements.in index a955311f63..fd3f75c888 100644 --- a/examples/pip_repository_annotations/requirements.in +++ b/examples/pip_repository_annotations/requirements.in @@ -3,3 +3,4 @@ --extra-index-url https://pypi.python.org/simple/ wheel +requests[security]>=2.8.1 diff --git a/examples/pip_repository_annotations/requirements.txt b/examples/pip_repository_annotations/requirements.txt index a2f161392a..44dcbdfccf 100644 --- a/examples/pip_repository_annotations/requirements.txt +++ b/examples/pip_repository_annotations/requirements.txt @@ -6,6 +6,26 @@ # --extra-index-url https://pypi.python.org/simple/ +certifi==2022.9.24 \ + --hash=sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14 \ + --hash=sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382 + # via requests +charset-normalizer==2.1.1 \ + --hash=sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845 \ + --hash=sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f + # via requests +idna==3.4 \ + --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ + --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 + # via requests +requests[security]==2.28.1 \ + --hash=sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983 \ + --hash=sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349 + # via -r ./requirements.in +urllib3==1.26.12 \ + --hash=sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e \ + --hash=sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997 + # via requests wheel==0.37.1 \ --hash=sha256:4bdcd7d840138086126cd09254dc6195fb4fc6f01c050a1d7236f2630db1d22a \ --hash=sha256:e9a504e793efbca1b8e0e9cb979a249cf4a0a7b5b8c9e8b65a5e39d49529c1c4 diff --git a/python/pip_install/extract_wheels/parse_requirements_to_bzl.py b/python/pip_install/extract_wheels/parse_requirements_to_bzl.py index d0abcac891..30071aeaac 100644 --- a/python/pip_install/extract_wheels/parse_requirements_to_bzl.py +++ b/python/pip_install/extract_wheels/parse_requirements_to_bzl.py @@ -155,7 +155,7 @@ def entry_point(pkg, script = None): def _get_annotation(requirement): # This expects to parse `setuptools==58.2.0 --hash=sha256:2551203ae6955b9876741a26ab3e767bb3242dafe86a32a749ea0d78b6792f11` # down wo `setuptools`. - name = requirement.split(" ")[0].split("=")[0] + name = requirement.split(" ")[0].split("=")[0].split("[")[0] return _annotations.get(name) def install_deps(**whl_library_kwargs): From ba69aec9db66e3ab53597403b0a4d0954f2d6d34 Mon Sep 17 00:00:00 2001 From: Derek Cormier Date: Mon, 31 Oct 2022 20:18:10 -0700 Subject: [PATCH 061/234] Create a requirements file parser in stalark for bzlmod --- python/pip_install/private/test/BUILD | 3 + .../test/requirements_parser_tests.bzl | 202 ++++++++++++++++++ python/pip_install/requirements_parser.bzl | 116 ++++++++++ 3 files changed, 321 insertions(+) create mode 100644 python/pip_install/private/test/requirements_parser_tests.bzl create mode 100644 python/pip_install/requirements_parser.bzl diff --git a/python/pip_install/private/test/BUILD b/python/pip_install/private/test/BUILD index 60d25de7df..d4978f3979 100644 --- a/python/pip_install/private/test/BUILD +++ b/python/pip_install/private/test/BUILD @@ -1,4 +1,5 @@ load("@bazel_skylib//rules:diff_test.bzl", "diff_test") +load(":requirements_parser_tests.bzl", parse_requirements_tests = "parse_tests") diff_test( name = "srcs_diff_test", @@ -15,3 +16,5 @@ diff_test( "//conditions:default": [], }), ) + +parse_requirements_tests(name = "test_parse_requirements") diff --git a/python/pip_install/private/test/requirements_parser_tests.bzl b/python/pip_install/private/test/requirements_parser_tests.bzl new file mode 100644 index 0000000000..037e7ea9df --- /dev/null +++ b/python/pip_install/private/test/requirements_parser_tests.bzl @@ -0,0 +1,202 @@ +"Unit tests for yaml.bzl" + +load("@bazel_skylib//lib:unittest.bzl", "asserts", "unittest") +load("//python/pip_install:requirements_parser.bzl", "parse") + +def _parse_basic_test_impl(ctx): + env = unittest.begin(ctx) + + # Base cases + asserts.equals(env, [], parse("").requirements) + asserts.equals(env, [], parse("\n").requirements) + + # Various requirement specifiers (https://pip.pypa.io/en/stable/reference/requirement-specifiers/#requirement-specifiers) + asserts.equals(env, [("SomeProject", "SomeProject")], parse("SomeProject\n").requirements) + asserts.equals(env, [("SomeProject", "SomeProject == 1.3")], parse("SomeProject == 1.3\n").requirements) + asserts.equals(env, [("SomeProject", "SomeProject >= 1.2, < 2.0")], parse("SomeProject >= 1.2, < 2.0\n").requirements) + asserts.equals(env, [("SomeProject", "SomeProject[foo, bar]")], parse("SomeProject[foo, bar]\n").requirements) + asserts.equals(env, [("SomeProject", "SomeProject ~= 1.4.2")], parse("SomeProject ~= 1.4.2\n").requirements) + asserts.equals(env, [("SomeProject", "SomeProject == 5.4 ; python_version < '3.8'")], parse("SomeProject == 5.4 ; python_version < '3.8'\n").requirements) + asserts.equals(env, [("SomeProject", "SomeProject ; sys_platform == 'win32'")], parse("SomeProject ; sys_platform == 'win32'\n").requirements) + asserts.equals(env, [("requests", "requests [security] >= 2.8.1, == 2.8.* ; python_version < 2.7")], parse("requests [security] >= 2.8.1, == 2.8.* ; python_version < 2.7\n").requirements) + + # Multiple requirements + asserts.equals(env, [("FooProject", "FooProject==1.0.0"), ("BarProject", "BarProject==2.0.0")], parse("""\ +FooProject==1.0.0 +BarProject==2.0.0 +""").requirements) + + asserts.equals(env, [("FooProject", "FooProject==1.0.0"), ("BarProject", "BarProject==2.0.0")], parse("""\ +FooProject==1.0.0 + +BarProject==2.0.0 +""").requirements) + + # Comments + asserts.equals(env, [("SomeProject", "SomeProject")], parse("""\ +# This is a comment +SomeProject +""").requirements) + asserts.equals(env, [("SomeProject", "SomeProject")], parse("""\ +SomeProject +# This is a comment +""").requirements) + asserts.equals(env, [("SomeProject", "SomeProject == 1.3")], parse("""\ +SomeProject == 1.3 # This is a comment +""").requirements) + asserts.equals(env, [("FooProject", "FooProject==1.0.0"), ("BarProject", "BarProject==2.0.0")], parse("""\ +FooProject==1.0.0 +# Comment +BarProject==2.0.0 #Comment +""").requirements) + + # Multiline + asserts.equals(env, [("certifi", "certifi==2021.10.8 --hash=sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872 --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569")], parse("""\ +certifi==2021.10.8 \ + --hash=sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872 \ + --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569 + # via requests +""").requirements) + + # Options + asserts.equals(env, ["--pre"], parse("--pre\n").options) + asserts.equals(env, ["--find-links /my/local/archives"], parse("--find-links /my/local/archives\n").options) + asserts.equals(env, ["--pre", "--find-links /my/local/archives"], parse("""\ +--pre +--find-links /my/local/archives +""").options) + asserts.equals(env, ["--pre", "--find-links /my/local/archives"], parse("""\ +--pre # Comment +--find-links /my/local/archives +""").options) + asserts.equals(env, struct(requirements = [("FooProject", "FooProject==1.0.0")], options = ["--pre", "--find-links /my/local/archives"]), parse("""\ +--pre # Comment +FooProject==1.0.0 +--find-links /my/local/archives +""")) + + return unittest.end(env) + +def _parse_requirements_lockfile_test_impl(ctx): + env = unittest.begin(ctx) + + asserts.equals(env, [ + ("certifi", "certifi==2021.10.8 --hash=sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872 --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"), + ("chardet", "chardet==4.0.0 --hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa --hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"), + ("idna", "idna==2.10 --hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 --hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"), + ("pathspec", "pathspec==0.9.0 --hash=sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a --hash=sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"), + ("python-dateutil", "python-dateutil==2.8.2 --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"), + ("python-magic", "python-magic==0.4.24 --hash=sha256:4fec8ee805fea30c07afccd1592c0f17977089895bdfaae5fec870a84e997626 --hash=sha256:de800df9fb50f8ec5974761054a708af6e4246b03b4bdaee993f948947b0ebcf"), + ("pyyaml", "pyyaml==6.0 --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 --hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b --hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 --hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 --hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba --hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"), + ("requests", "requests==2.25.1 --hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 --hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"), + ("s3cmd", "s3cmd==2.1.0 --hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa --hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03"), + ("six", "six==1.16.0 --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"), + ("urllib3", "urllib3==1.26.7 --hash=sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece --hash=sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844"), + ("yamllint", "yamllint==1.26.3 --hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e"), + ("setuptools", "setuptools==59.6.0 --hash=sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373 --hash=sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e"), + ], parse("""\ +# +# This file is autogenerated by pip-compile with python 3.9 +# To update, run: +# +# bazel run //:requirements.update +# +certifi==2021.10.8 \ + --hash=sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872 \ + --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569 + # via requests +chardet==4.0.0 \ + --hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa \ + --hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5 + # via requests +idna==2.10 \ + --hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 \ + --hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0 + # via requests +pathspec==0.9.0 \ + --hash=sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a \ + --hash=sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1 + # via yamllint +python-dateutil==2.8.2 \ + --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ + --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 + # via s3cmd +python-magic==0.4.24 \ + --hash=sha256:4fec8ee805fea30c07afccd1592c0f17977089895bdfaae5fec870a84e997626 \ + --hash=sha256:de800df9fb50f8ec5974761054a708af6e4246b03b4bdaee993f948947b0ebcf + # via s3cmd +pyyaml==6.0 \ + --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ + --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ + --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ + --hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b \ + --hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 \ + --hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 \ + --hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba \ + --hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 \ + --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ + --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ + --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ + --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ + --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ + --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ + --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ + --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ + --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ + --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ + --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ + --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ + --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ + --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ + --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ + --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ + --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ + --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ + --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ + --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ + --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ + --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ + --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ + --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ + --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 + # via yamllint +requests==2.25.1 \ + --hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \ + --hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e + # via -r ./requirements.in +s3cmd==2.1.0 \ + --hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \ + --hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03 + # via -r ./requirements.in +six==1.16.0 \ + --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ + --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 + # via python-dateutil +urllib3==1.26.7 \ + --hash=sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece \ + --hash=sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844 + # via requests +yamllint==1.26.3 \ + --hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e + # via -r ./requirements.in + +# The following packages are considered to be unsafe in a requirements file: +setuptools==59.6.0 \ + --hash=sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373 \ + --hash=sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e + # via yamllint +""").requirements) + + return unittest.end(env) + +parse_basic_test = unittest.make( + _parse_basic_test_impl, + attrs = {}, +) +parse_requirements_lockfile_test = unittest.make( + _parse_requirements_lockfile_test_impl, + attrs = {}, +) + +def parse_tests(name): + unittest.suite(name, parse_basic_test, parse_requirements_lockfile_test) diff --git a/python/pip_install/requirements_parser.bzl b/python/pip_install/requirements_parser.bzl new file mode 100644 index 0000000000..2e62bcc699 --- /dev/null +++ b/python/pip_install/requirements_parser.bzl @@ -0,0 +1,116 @@ +"Pip requirements parser for Starlark" + +_STATE = struct( + # Consume extraneous whitespace + ConsumeSpace = 0, + # Consume a comment + ConsumeComment = 1, + # Parse the name of a pip package + ParseDependency = 2, + # Parse a full requirement line + ParseRequirement = 3, + # Parse a pip option + ParseOption = 4, +) + +EOF = {} + +def parse(content): + """A simplistic (and incomplete) pip requirements lockfile parser. + + Parses package names and their full requirement lines, as well pip + options. + + Args: + content: lockfile content as a string + + Returns: + Struct with fields `requirements` and `options`. + + requirements: List of requirements, where each requirement is a 2-element + tuple containing the package name and the requirement line. + E.g., [(certifi', 'certifi==2021.10.8 --hash=sha256:7888...'), ...] + + options: List of pip option lines + """ + content = content.replace("\r", "") + + result = struct( + requirements = [], + options = [], + ) + state = _STATE.ConsumeSpace + buffer = "" + + inputs = content.elems()[:] + inputs.append(EOF) + + for input in inputs: + if state == _STATE.ConsumeSpace: + (state, buffer) = _handleConsumeSpace(input) + elif state == _STATE.ConsumeComment: + (state, buffer) = _handleConsumeComment(input, buffer, result) + elif state == _STATE.ParseDependency: + (state, buffer) = _handleParseDependency(input, buffer, result) + elif state == _STATE.ParseOption: + (state, buffer) = _handleParseOption(input, buffer, result) + elif state == _STATE.ParseRequirement: + (state, buffer) = _handleParseRequirement(input, buffer, result) + else: + fail("Unknown state %d" % state) + + return result + +def _handleConsumeSpace(input): + if input == EOF: + return (_STATE.ConsumeSpace, "") + if input.isspace(): + return (_STATE.ConsumeSpace, "") + elif input == "#": + return (_STATE.ConsumeComment, "") + elif input == "-": + return (_STATE.ParseOption, input) + + return (_STATE.ParseDependency, input) + +def _handleConsumeComment(input, buffer, result): + if input == "\n": + if len(result.requirements) > 0 and len(result.requirements[-1]) == 1: + result.requirements[-1] = (result.requirements[-1][0], buffer.rstrip(" \n")) + return (_STATE.ConsumeSpace, "") + elif len(buffer) > 0: + result.options.append(buffer.rstrip(" \n")) + return (_STATE.ConsumeSpace, "") + return (_STATE.ConsumeSpace, "") + return (_STATE.ConsumeComment, buffer) + +def _handleParseDependency(input, buffer, result): + if input == EOF: + fail("Enountered unexpected end of file while parsing requirement") + elif input.isspace() or input in [">", "<", "~", "=", ";", "["]: + result.requirements.append((buffer,)) + return (_STATE.ParseRequirement, buffer + input) + + return (_STATE.ParseDependency, buffer + input) + +def _handleParseOption(input, buffer, result): + if input == "\n" and buffer.endswith("\\"): + return (_STATE.ParseOption, buffer[0:-1]) + elif input == "\n" or input == EOF: + result.options.append(buffer.rstrip("\n")) + return (_STATE.ConsumeSpace, "") + elif input == "#": + return (_STATE.ConsumeComment, buffer) + + return (_STATE.ParseOption, buffer + input) + +def _handleParseRequirement(input, buffer, result): + if input == "\n" and buffer.endswith("\\"): + return (_STATE.ParseRequirement, buffer[0:-1]) + elif input == "\n" or input == EOF: + result.requirements[-1] = (result.requirements[-1][0], buffer.rstrip(" \n")) + return (_STATE.ConsumeSpace, "") + elif input == "#": + return (_STATE.ConsumeComment, buffer) + + return (_STATE.ParseRequirement, buffer + input) From af354c2e493e55abe5640a1c40043452cb858cdc Mon Sep 17 00:00:00 2001 From: Derek Cormier Date: Mon, 31 Oct 2022 20:18:22 -0700 Subject: [PATCH 062/234] Create a pip_parse bzlmod extension --- MODULE.bazel | 18 ++- docs/BUILD | 8 ++ docs/pip.md | 3 +- docs/pip_repository.md | 43 +++++- examples/bzlmod/.bazelversion | 1 + examples/bzlmod/BUILD.bazel | 16 ++- examples/bzlmod/MODULE.bazel | 22 ++++ examples/bzlmod/__init__.py | 9 +- examples/bzlmod/__main__.py | 2 +- examples/bzlmod/requirements.in | 4 + examples/bzlmod/requirements_lock.txt | 94 +++++++++++++ examples/bzlmod/test.py | 9 +- examples/pip_parse_vendored/requirements.bzl | 9 ++ python/extensions.bzl | 93 ++++++++++++- python/pip.bzl | 10 +- .../parse_requirements_to_bzl.py | 61 +++++++-- .../parse_requirements_to_bzl_test.py | 2 + python/pip_install/pip_repository.bzl | 124 ++++++++++++++---- python/pip_install/repositories.bzl | 2 +- 19 files changed, 472 insertions(+), 58 deletions(-) create mode 100644 examples/bzlmod/.bazelversion create mode 100644 examples/bzlmod/requirements.in create mode 100644 examples/bzlmod/requirements_lock.txt diff --git a/MODULE.bazel b/MODULE.bazel index 42c507df80..e007d0c2d9 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -4,13 +4,27 @@ module( version = "0.0.0", ) -pip_install = use_extension("@rules_python//python:extensions.bzl", "pip_install") +bazel_dep(name = "platforms", version = "0.0.4") + +internal_deps = use_extension("@rules_python//python:extensions.bzl", "internal_deps") + +internal_deps.install() use_repo( - pip_install, + internal_deps, + "pypi__build", "pypi__click", + "pypi__colorama", + "pypi__importlib_metadata", + "pypi__installer", + "pypi__more_itertools", + "pypi__packaging", + "pypi__pep517", "pypi__pip", "pypi__pip_tools", + "pypi__pyparsing", "pypi__setuptools", + "pypi__tomli", "pypi__wheel", + "pypi__zipp", ) diff --git a/docs/BUILD b/docs/BUILD index d2958219f0..f2f13be05b 100644 --- a/docs/BUILD +++ b/docs/BUILD @@ -70,6 +70,13 @@ bzl_library( ], ) +bzl_library( + name = "requirements_parser_bzl", + srcs = [ + "//python/pip_install:requirements_parser.bzl", + ], +) + bzl_library( name = "packaging_bzl", srcs = [ @@ -114,6 +121,7 @@ stardoc( deps = [ ":bazel_repo_tools", ":pip_install_bzl", + ":requirements_parser_bzl", "//third_party/github.com/bazelbuild/bazel-skylib/lib:versions", ], ) diff --git a/docs/pip.md b/docs/pip.md index f6d8430adc..7f70ef5066 100644 --- a/docs/pip.md +++ b/docs/pip.md @@ -104,7 +104,7 @@ install_deps() ## pip_parse
-pip_parse(requirements, requirements_lock, name, kwargs)
+pip_parse(requirements, requirements_lock, name, bzlmod, kwargs)
 
Accepts a locked/compiled requirements file and installs the dependencies listed within. @@ -200,6 +200,7 @@ See the example in rules_python/examples/pip_parse_vendored. | requirements | Deprecated. See requirements_lock. | None | | requirements_lock | A fully resolved 'requirements.txt' pip requirement file containing the transitive set of your dependencies. If this file is passed instead of 'requirements' no resolve will take place and pip_repository will create individual repositories for each of your dependencies so that wheels are fetched/built only for the targets specified by 'build/run/test'. Note that if your lockfile is platform-dependent, you can use the requirements_[platform] attributes. | None | | name | The name of the generated repository. The generated repositories containing each requirement will be of the form <name>_<requirement-name>. | "pip_parsed_deps" | +| bzlmod | Whether this rule is being run under a bzlmod module extension. | False | | kwargs | Additional arguments to the [pip_repository](./pip_repository.md) repository rule. | none | diff --git a/docs/pip_repository.md b/docs/pip_repository.md index 875ea117f0..20816054a9 100644 --- a/docs/pip_repository.md +++ b/docs/pip_repository.md @@ -5,8 +5,8 @@ ## pip_repository
-pip_repository(name, annotations, download_only, enable_implicit_namespace_pkgs, environment,
-               extra_pip_args, isolated, pip_data_exclude, python_interpreter,
+pip_repository(name, annotations, bzlmod, download_only, enable_implicit_namespace_pkgs,
+               environment, extra_pip_args, isolated, pip_data_exclude, python_interpreter,
                python_interpreter_target, quiet, repo_prefix, requirements_darwin, requirements_linux,
                requirements_lock, requirements_windows, timeout)
 
@@ -58,6 +58,7 @@ py_binary( | :-------------: | :-------------: | :-------------: | :-------------: | :-------------: | | name | A unique name for this repository. | Name | required | | | annotations | Optional annotations to apply to packages | Dictionary: String -> String | optional | {} | +| bzlmod | Whether this repository rule is invoked under bzlmod, in which case we do not create the install_deps() macro. | Boolean | optional | False | | download_only | Whether to use "pip download" instead of "pip wheel". Disables building wheels from source, but allows use of --platform, --python-version, --implementation, and --abi in --extra_pip_args to download wheels for a different platform from the host platform. | Boolean | optional | False | | enable_implicit_namespace_pkgs | If true, disables conversion of native namespace packages into pkg-util style namespace packages. When set all py_binary and py_test targets must specify either legacy_create_init=False or the global Bazel option --incompatible_default_to_explicit_init_py to prevent __init__.py being automatically generated in every directory.

This option is required to support some packages which cannot handle the conversion to pkg-util style. | Boolean | optional | False | | environment | Environment variables to set in the pip subprocess. Can be used to set common variables such as http_proxy, https_proxy and no_proxy Note that pip is run with "--isolated" on the CLI so PIP_<VAR>_<NAME> style env vars are ignored, but env vars that control requests and urllib3 can be passed. | Dictionary: String -> String | optional | {} | @@ -111,6 +112,25 @@ Instantiated from pip_repository and inherits config options from there. | timeout | Timeout (in seconds) on the rule's execution duration. | Integer | optional | 600 | + + +## locked_requirements_label + +
+locked_requirements_label(ctx, attr)
+
+ +Get the preferred label for a locked requirements file based on platform. + +**PARAMETERS** + + +| Name | Description | Default Value | +| :-------------: | :-------------: | :-------------: | +| ctx | repository or module context | none | +| attr | attributes for the repo rule or tag extension | none | + + ## package_annotation @@ -138,3 +158,22 @@ Annotations to apply to the BUILD file content from package generated from a `pi | srcs_exclude_glob | A list of labels to add as srcs to the generated py_library target. | [] | + + +## use_isolated + +
+use_isolated(ctx, attr)
+
+ +Determine whether or not to pass the pip `--isolated` flag to the pip invocation. + +**PARAMETERS** + + +| Name | Description | Default Value | +| :-------------: | :-------------: | :-------------: | +| ctx | repository or module context | none | +| attr | attributes for the repo rule or tag extension | none | + + diff --git a/examples/bzlmod/.bazelversion b/examples/bzlmod/.bazelversion new file mode 100644 index 0000000000..6b4ab2c84d --- /dev/null +++ b/examples/bzlmod/.bazelversion @@ -0,0 +1 @@ +6.0.0rc1 \ No newline at end of file diff --git a/examples/bzlmod/BUILD.bazel b/examples/bzlmod/BUILD.bazel index 3e0349bf4f..5693fa658f 100644 --- a/examples/bzlmod/BUILD.bazel +++ b/examples/bzlmod/BUILD.bazel @@ -1,8 +1,20 @@ +load("@pip//:requirements.bzl", "requirement") load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test") +load("@rules_python//python:pip.bzl", "compile_pip_requirements") + +compile_pip_requirements( + name = "requirements", + extra_args = ["--allow-unsafe"], + requirements_in = "requirements.in", + requirements_txt = "requirements_lock.txt", +) py_library( name = "lib", srcs = ["__init__.py"], + deps = [ + requirement("tabulate"), + ], ) py_binary( @@ -10,7 +22,9 @@ py_binary( srcs = ["__main__.py"], main = "__main__.py", visibility = ["//:__subpackages__"], - deps = [":lib"], + deps = [ + ":lib", + ], ) py_test( diff --git a/examples/bzlmod/MODULE.bazel b/examples/bzlmod/MODULE.bazel index e3fc51a115..275be3bf1f 100644 --- a/examples/bzlmod/MODULE.bazel +++ b/examples/bzlmod/MODULE.bazel @@ -10,3 +10,25 @@ local_path_override( module_name = "rules_python", path = "../..", ) + +python = use_extension("@rules_python//python:extensions.bzl", "python") + +python.toolchain( + name = "python3_9", + python_version = "3.9", +) + +use_repo(python, "python3_9_toolchains") + +register_toolchains( + "@python3_9_toolchains//:all", +) + +pip = use_extension("@rules_python//python:extensions.bzl", "pip") + +pip.parse( + name = "pip", + requirements_lock = "//:requirements_lock.txt", +) + +use_repo(pip, "pip") diff --git a/examples/bzlmod/__init__.py b/examples/bzlmod/__init__.py index da9768f838..955eb5af15 100644 --- a/examples/bzlmod/__init__.py +++ b/examples/bzlmod/__init__.py @@ -1,8 +1,5 @@ -# TODO: bzlmod should grant access to pip_install dependencies as well -# import requests +from tabulate import tabulate -def main(url): - # r = requests.get(url) - # return r.text - return url +def main(table): + return tabulate(table) diff --git a/examples/bzlmod/__main__.py b/examples/bzlmod/__main__.py index 04bcfb0b1f..8b4cb130b8 100644 --- a/examples/bzlmod/__main__.py +++ b/examples/bzlmod/__main__.py @@ -1,4 +1,4 @@ from __init__ import main if __name__ == "__main__": - print(main("https://example.com")) + print(main([["A", 1], ["B", 2]])) diff --git a/examples/bzlmod/requirements.in b/examples/bzlmod/requirements.in new file mode 100644 index 0000000000..ea285b036d --- /dev/null +++ b/examples/bzlmod/requirements.in @@ -0,0 +1,4 @@ +requests~=2.25.1 +s3cmd~=2.1.0 +yamllint~=1.26.3 +tabulate~=0.9.0 diff --git a/examples/bzlmod/requirements_lock.txt b/examples/bzlmod/requirements_lock.txt new file mode 100644 index 0000000000..8da8e6a8e1 --- /dev/null +++ b/examples/bzlmod/requirements_lock.txt @@ -0,0 +1,94 @@ +# +# This file is autogenerated by pip-compile with python 3.9 +# To update, run: +# +# bazel run //:requirements.update +# +certifi==2021.10.8 \ + --hash=sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872 \ + --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569 + # via requests +chardet==4.0.0 \ + --hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa \ + --hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5 + # via requests +idna==2.10 \ + --hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 \ + --hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0 + # via requests +pathspec==0.9.0 \ + --hash=sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a \ + --hash=sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1 + # via yamllint +python-dateutil==2.8.2 \ + --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ + --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 + # via s3cmd +python-magic==0.4.24 \ + --hash=sha256:4fec8ee805fea30c07afccd1592c0f17977089895bdfaae5fec870a84e997626 \ + --hash=sha256:de800df9fb50f8ec5974761054a708af6e4246b03b4bdaee993f948947b0ebcf + # via s3cmd +pyyaml==6.0 \ + --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ + --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ + --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ + --hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b \ + --hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 \ + --hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 \ + --hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba \ + --hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 \ + --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ + --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ + --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ + --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ + --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ + --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ + --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ + --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ + --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ + --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ + --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ + --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ + --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ + --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ + --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ + --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ + --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ + --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ + --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ + --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ + --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ + --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ + --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ + --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ + --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 + # via yamllint +requests==2.25.1 \ + --hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \ + --hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e + # via -r ./requirements.in +s3cmd==2.1.0 \ + --hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \ + --hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03 + # via -r ./requirements.in +six==1.16.0 \ + --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ + --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 + # via python-dateutil +tabulate==0.9.0 \ + --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \ + --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f + # via -r ./requirements.in +urllib3==1.26.7 \ + --hash=sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece \ + --hash=sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844 + # via requests +yamllint==1.26.3 \ + --hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e + # via -r ./requirements.in + +# The following packages are considered to be unsafe in a requirements file: +setuptools==59.6.0 \ + --hash=sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373 \ + --hash=sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e + # via yamllint diff --git a/examples/bzlmod/test.py b/examples/bzlmod/test.py index 5d725a862c..f9f0a830cd 100644 --- a/examples/bzlmod/test.py +++ b/examples/bzlmod/test.py @@ -5,7 +5,14 @@ class ExampleTest(unittest.TestCase): def test_main(self): - self.assertEquals("http://google.com", main("http://google.com")) + self.assertEquals( + """\ +- - +A 1 +B 2 +- -""", + main([["A", 1], ["B", 2]]), + ) if __name__ == "__main__": diff --git a/examples/pip_parse_vendored/requirements.bzl b/examples/pip_parse_vendored/requirements.bzl index 6f1fbd0b75..5a0dcf85f5 100644 --- a/examples/pip_parse_vendored/requirements.bzl +++ b/examples/pip_parse_vendored/requirements.bzl @@ -14,20 +14,29 @@ all_whl_requirements = ["@pip_certifi//:whl", "@pip_charset_normalizer//:whl", " _packages = [("pip_certifi", "certifi==2021.10.8 --hash=sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872 --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"), ("pip_charset_normalizer", "charset-normalizer==2.0.12 --hash=sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597 --hash=sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"), ("pip_idna", "idna==3.3 --hash=sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff --hash=sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"), ("pip_requests", "requests==2.27.1 --hash=sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61 --hash=sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"), ("pip_urllib3", "urllib3==1.26.9 --hash=sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14 --hash=sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e")] _config = {"download_only": False, "enable_implicit_namespace_pkgs": False, "environment": {}, "extra_pip_args": [], "isolated": True, "pip_data_exclude": [], "python_interpreter": "python3", "python_interpreter_target": interpreter, "quiet": True, "repo": "pip", "repo_prefix": "pip_", "timeout": 600} _annotations = {} +_bzlmod = False def _clean_name(name): return name.replace("-", "_").replace(".", "_").lower() def requirement(name): + if _bzlmod: + return "@@pip//:" + _clean_name(name) + "_pkg" return "@pip_" + _clean_name(name) + "//:pkg" def whl_requirement(name): + if _bzlmod: + return "@@pip//:" + _clean_name(name) + "_whl" return "@pip_" + _clean_name(name) + "//:whl" def data_requirement(name): + if _bzlmod: + return "@@pip//:" + _clean_name(name) + "_data" return "@pip_" + _clean_name(name) + "//:data" def dist_info_requirement(name): + if _bzlmod: + return "@@pip//:" + _clean_name(name) + "_dist_info" return "@pip_" + _clean_name(name) + "//:dist_info" def entry_point(pkg, script = None): diff --git a/python/extensions.bzl b/python/extensions.bzl index 9c1c87ab22..505ff20d13 100644 --- a/python/extensions.bzl +++ b/python/extensions.bzl @@ -1,10 +1,97 @@ "Module extensions for use with bzlmod" +load("@rules_python//python:pip.bzl", "pip_parse") +load("@rules_python//python:repositories.bzl", "python_register_toolchains") +load("@rules_python//python/pip_install:pip_repository.bzl", "locked_requirements_label", "pip_repository_attrs", "use_isolated", "whl_library") load("@rules_python//python/pip_install:repositories.bzl", "pip_install_dependencies") +load("@rules_python//python/pip_install:requirements_parser.bzl", parse_requirements = "parse") -def _pip_install_impl(_): +def _python_impl(module_ctx): + for mod in module_ctx.modules: + for attr in mod.tags.toolchain: + python_register_toolchains( + name = attr.name, + python_version = attr.python_version, + # Toolchain registration in bzlmod is done in MODULE file + register_toolchains = False, + ) + +python = module_extension( + implementation = _python_impl, + tag_classes = { + "toolchain": tag_class(attrs = dict({"name": attr.string(mandatory = True), "python_version": attr.string(mandatory = True)})), + }, +) + +# buildifier: disable=unused-variable +def _internal_deps_impl(module_ctx): pip_install_dependencies() -pip_install = module_extension( - implementation = _pip_install_impl, +internal_deps = module_extension( + implementation = _internal_deps_impl, + tag_classes = { + "install": tag_class(attrs = dict()), + }, +) + +def _pip_impl(module_ctx): + for mod in module_ctx.modules: + for attr in mod.tags.parse: + requrements_lock = locked_requirements_label(module_ctx, attr) + + # Parse the requirements file directly in starlark to get the information + # needed for the whl_libary declarations below. This is needed to contain + # the pip_parse logic to a single module extension. + requirements_lock_content = module_ctx.read(requrements_lock) + parse_result = parse_requirements(requirements_lock_content) + requirements = parse_result.requirements + extra_pip_args = attr.extra_pip_args + parse_result.options + + # Create the repository where users load the `requirement` macro. Under bzlmod + # this does not create the install_deps() macro. + pip_parse( + name = attr.name, + requirements_lock = attr.requirements_lock, + bzlmod = True, + timeout = attr.timeout, + python_interpreter = attr.python_interpreter, + python_interpreter_target = attr.python_interpreter_target, + quiet = attr.quiet, + ) + + for name, requirement_line in requirements: + whl_library( + name = "%s_%s" % (attr.name, name), + requirement = requirement_line, + repo = attr.name, + repo_prefix = attr.name + "_", + annotation = attr.annotations.get(name), + python_interpreter = attr.python_interpreter, + python_interpreter_target = attr.python_interpreter_target, + quiet = attr.quiet, + timeout = attr.timeout, + isolated = use_isolated(module_ctx, attr), + extra_pip_args = extra_pip_args, + download_only = attr.download_only, + pip_data_exclude = attr.pip_data_exclude, + enable_implicit_namespace_pkgs = attr.enable_implicit_namespace_pkgs, + environment = attr.environment, + ) + +def _pip_parse_ext_attrs(): + attrs = dict({ + "name": attr.string(mandatory = True), + }, **pip_repository_attrs) + + # Like the pip_parse macro, we end up setting this manually so + # don't allow users to override it. + attrs.pop("repo_prefix") + + return attrs + +pip = module_extension( + implementation = _pip_impl, + tag_classes = { + "parse": tag_class(attrs = _pip_parse_ext_attrs()), + }, ) diff --git a/python/pip.bzl b/python/pip.bzl index dfafefe38d..02ea538c38 100644 --- a/python/pip.bzl +++ b/python/pip.bzl @@ -46,7 +46,7 @@ def pip_install(requirements = None, name = "pip", **kwargs): print("pip_install is deprecated. Please switch to pip_parse. pip_install will be removed in a future release.") pip_parse(requirements = requirements, name = name, **kwargs) -def pip_parse(requirements = None, requirements_lock = None, name = "pip_parsed_deps", **kwargs): +def pip_parse(requirements = None, requirements_lock = None, name = "pip_parsed_deps", bzlmod = False, **kwargs): """Accepts a locked/compiled requirements file and installs the dependencies listed within. Those dependencies become available in a generated `requirements.bzl` file. @@ -142,11 +142,14 @@ def pip_parse(requirements = None, requirements_lock = None, name = "pip_parsed_ requirements (Label): Deprecated. See requirements_lock. name (str, optional): The name of the generated repository. The generated repositories containing each requirement will be of the form _. + bzlmod (bool, optional): Whether this rule is being run under a bzlmod module extension. **kwargs (dict): Additional arguments to the [`pip_repository`](./pip_repository.md) repository rule. """ - # Just in case our dependencies weren't already fetched - pip_install_dependencies() + # Don't try to fetch dependencies under bzlmod because they are already fetched via the internal_deps + # module extention, and because the maybe-install pattern doesn't work under bzlmod. + if not bzlmod: + pip_install_dependencies() # Temporary compatibility shim. # pip_install was previously document to use requirements while pip_parse was using requirements_lock. @@ -157,5 +160,6 @@ def pip_parse(requirements = None, requirements_lock = None, name = "pip_parsed_ name = name, requirements_lock = reqs_to_use, repo_prefix = "{}_".format(name), + bzlmod = bzlmod, **kwargs ) diff --git a/python/pip_install/extract_wheels/parse_requirements_to_bzl.py b/python/pip_install/extract_wheels/parse_requirements_to_bzl.py index 30071aeaac..686a57d8b2 100644 --- a/python/pip_install/extract_wheels/parse_requirements_to_bzl.py +++ b/python/pip_install/extract_wheels/parse_requirements_to_bzl.py @@ -81,7 +81,12 @@ def parse_whl_library_args(args: argparse.Namespace) -> Dict[str, Any]: whl_library_args.setdefault("python_interpreter", sys.executable) # These arguments are not used by `whl_library` - for arg in ("requirements_lock", "requirements_lock_label", "annotations"): + for arg in ( + "requirements_lock", + "requirements_lock_label", + "annotations", + "bzlmod", + ): if arg in whl_library_args: whl_library_args.pop(arg) @@ -90,9 +95,11 @@ def parse_whl_library_args(args: argparse.Namespace) -> Dict[str, Any]: def generate_parsed_requirements_contents( requirements_lock: Path, + repo: str, repo_prefix: str, whl_library_args: Dict[str, Any], annotations: Dict[str, str] = dict(), + bzlmod: bool = False, ) -> str: """ Parse each requirement from the requirements_lock file, and prepare arguments for each @@ -107,6 +114,7 @@ def generate_parsed_requirements_contents( repo_names_and_reqs = repo_names_and_requirements( install_req_and_lines, repo_prefix ) + all_requirements = ", ".join( [ bazel.sanitised_repo_library_label(ir.name, repo_prefix=repo_prefix) @@ -119,8 +127,22 @@ def generate_parsed_requirements_contents( for ir, _ in install_req_and_lines ] ) + + install_deps_macro = """ + def install_deps(**whl_library_kwargs): + whl_config = dict(_config) + whl_config.update(whl_library_kwargs) + for name, requirement in _packages: + whl_library( + name = name, + requirement = requirement, + annotation = _get_annotation(requirement), + **whl_config + ) +""" return textwrap.dedent( - """\ + ( + """\ load("@rules_python//python/pip_install:pip_repository.bzl", "whl_library") @@ -131,20 +153,29 @@ def generate_parsed_requirements_contents( _packages = {repo_names_and_reqs} _config = {args} _annotations = {annotations} + _bzlmod = {bzlmod} def _clean_name(name): return name.replace("-", "_").replace(".", "_").lower() def requirement(name): + if _bzlmod: + return "@@{repo}//:" + _clean_name(name) + "_{py_library_label}" return "@{repo_prefix}" + _clean_name(name) + "//:{py_library_label}" def whl_requirement(name): + if _bzlmod: + return "@@{repo}//:" + _clean_name(name) + "_{wheel_file_label}" return "@{repo_prefix}" + _clean_name(name) + "//:{wheel_file_label}" def data_requirement(name): + if _bzlmod: + return "@@{repo}//:" + _clean_name(name) + "_{data_label}" return "@{repo_prefix}" + _clean_name(name) + "//:{data_label}" def dist_info_requirement(name): + if _bzlmod: + return "@@{repo}//:" + _clean_name(name) + "_{dist_info_label}" return "@{repo_prefix}" + _clean_name(name) + "//:{dist_info_label}" def entry_point(pkg, script = None): @@ -157,18 +188,9 @@ def _get_annotation(requirement): # down wo `setuptools`. name = requirement.split(" ")[0].split("=")[0].split("[")[0] return _annotations.get(name) - - def install_deps(**whl_library_kwargs): - whl_config = dict(_config) - whl_config.update(whl_library_kwargs) - for name, requirement in _packages: - whl_library( - name = name, - requirement = requirement, - annotation = _get_annotation(requirement), - **whl_config - ) - """.format( +""" + + (install_deps_macro if not bzlmod else "") + ).format( all_requirements=all_requirements, all_whl_requirements=all_whl_requirements, annotations=json.dumps(annotations), @@ -178,8 +200,10 @@ def install_deps(**whl_library_kwargs): entry_point_prefix=bazel.WHEEL_ENTRY_POINT_PREFIX, py_library_label=bazel.PY_LIBRARY_LABEL, repo_names_and_reqs=repo_names_and_reqs, + repo=repo, repo_prefix=repo_prefix, wheel_file_label=bazel.WHEEL_FILE_LABEL, + bzlmod=bzlmod, ) ) @@ -236,6 +260,12 @@ def main(output: TextIO) -> None: type=annotation.annotations_map_from_str_path, help="A json encoded file containing annotations for rendered packages.", ) + parser.add_argument( + "--bzlmod", + type=coerce_to_bool, + default=False, + help="Whether this script is run under bzlmod. Under bzlmod we don't generate the install_deps() macro as it isn't needed.", + ) arguments.parse_common_args(parser) args = parser.parse_args() @@ -274,12 +304,15 @@ def main(output: TextIO) -> None: ) ) ) + output.write( generate_parsed_requirements_contents( requirements_lock=args.requirements_lock, + repo=args.repo, repo_prefix=args.repo_prefix, whl_library_args=whl_library_args, annotations=annotated_requirements, + bzlmod=args.bzlmod, ) ) diff --git a/python/pip_install/extract_wheels/parse_requirements_to_bzl_test.py b/python/pip_install/extract_wheels/parse_requirements_to_bzl_test.py index a9a4c95afe..c4879f65c1 100644 --- a/python/pip_install/extract_wheels/parse_requirements_to_bzl_test.py +++ b/python/pip_install/extract_wheels/parse_requirements_to_bzl_test.py @@ -27,6 +27,7 @@ def test_generated_requirements_bzl(self) -> None: ) args = argparse.Namespace() args.requirements_lock = str(requirements_lock.resolve()) + args.repo = ("pip_parsed_deps_pypi__",) args.repo_prefix = "pip_parsed_deps_pypi__" extra_pip_args = ["--index-url=pypi.org/simple"] pip_data_exclude = ["**.foo"] @@ -38,6 +39,7 @@ def test_generated_requirements_bzl(self) -> None: whl_library_args = parse_whl_library_args(args) contents = generate_parsed_requirements_contents( requirements_lock=args.requirements_lock, + repo=args.repo, repo_prefix=args.repo_prefix, whl_library_args=whl_library_args, ) diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl index 97109460fc..7fbf503992 100644 --- a/python/pip_install/pip_repository.bzl +++ b/python/pip_install/pip_repository.bzl @@ -2,6 +2,7 @@ load("//python:repositories.bzl", "is_standalone_interpreter") load("//python/pip_install:repositories.bzl", "all_requirements") +load("//python/pip_install:requirements_parser.bzl", parse_requirements = "parse") load("//python/pip_install/private:srcs.bzl", "PIP_INSTALL_PY_SRCS") CPPFLAGS = "CPPFLAGS" @@ -129,6 +130,28 @@ def _get_toolchain_unix_cflags(rctx): return ["-isystem {}".format(include_path)] +def use_isolated(ctx, attr): + """Determine whether or not to pass the pip `--isolated` flag to the pip invocation. + + Args: + ctx: repository or module context + attr: attributes for the repo rule or tag extension + + Returns: + True if --isolated should be passed + """ + use_isolated = attr.isolated + + # The environment variable will take precedence over the attribute + isolated_env = ctx.os.environ.get("RULES_PYTHON_PIP_ISOLATED", None) + if isolated_env != None: + if isolated_env.lower() in ("0", "false"): + use_isolated = False + else: + use_isolated = True + + return use_isolated + def _parse_optional_attrs(rctx, args): """Helper function to parse common attributes of pip_repository and whl_library repository rules. @@ -141,18 +164,7 @@ def _parse_optional_attrs(rctx, args): Returns: Augmented args list. """ - # Determine whether or not to pass the pip `--isloated` flag to the pip invocation - use_isolated = rctx.attr.isolated - - # The environment variable will take precedence over the attribute - isolated_env = rctx.os.environ.get("RULES_PYTHON_PIP_ISOLATED", None) - if isolated_env != None: - if isolated_env.lower() in ("0", "false"): - use_isolated = False - else: - use_isolated = True - - if use_isolated: + if use_isolated(rctx, rctx.attr): args.append("--isolated") # Check for None so we use empty default types from our attrs. @@ -211,21 +223,74 @@ package(default_visibility = ["//visibility:public"]) exports_files(["requirements.bzl"]) """ -def _locked_requirements(rctx): - os = rctx.os.name.lower() - requirements_txt = rctx.attr.requirements_lock - if os.startswith("mac os") and rctx.attr.requirements_darwin != None: - requirements_txt = rctx.attr.requirements_darwin - elif os.startswith("linux") and rctx.attr.requirements_linux != None: - requirements_txt = rctx.attr.requirements_linux - elif "win" in os and rctx.attr.requirements_windows != None: - requirements_txt = rctx.attr.requirements_windows +def locked_requirements_label(ctx, attr): + """Get the preferred label for a locked requirements file based on platform. + + Args: + ctx: repository or module context + attr: attributes for the repo rule or tag extension + + Returns: + Label + """ + os = ctx.os.name.lower() + requirements_txt = attr.requirements_lock + if os.startswith("mac os") and attr.requirements_darwin != None: + requirements_txt = attr.requirements_darwin + elif os.startswith("linux") and attr.requirements_linux != None: + requirements_txt = attr.requirements_linux + elif "win" in os and attr.requirements_windows != None: + requirements_txt = attr.requirements_windows if not requirements_txt: fail("""\ A requirements_lock attribute must be specified, or a platform-specific lockfile using one of the requirements_* attributes. """) return requirements_txt +# Keep in sync with `_clean_name` in generated requirements.bzl +def _clean_pkg_name(name): + return name.replace("-", "_").replace(".", "_").lower() + +def _bzlmod_pkg_aliases(rctx, requirements_txt): + """Create alias declarations for each python dependency. + + The aliases should be appended to the pip_parse repo's BUILD.bazel file. These aliases + allow users to use requirement() without needed a corresponding `use_repo()` for each dep + when using bzlmod. + + Args: + rctx: the repository context + requirements_txt: label to the requirements lock file + """ + requirements = parse_requirements(rctx.read(requirements_txt)).requirements + + build_content = "" + for requirement in requirements: + build_content += """\ + +alias( + name = "{name}_pkg", + actual = "@{repo_prefix}{dep}//:pkg", +) + +alias( + name = "{name}_whl", + actual = "@{repo_prefix}{dep}//:whl", +) + +alias( + name = "{name}_data", + actual = "@{repo_prefix}{dep}//:data", +) + +alias( + name = "{name}_dist_info", + actual = "@{repo_prefix}{dep}//:dist_info", +) +""".format(name = _clean_pkg_name(requirement[0]), repo_prefix = rctx.attr.repo_prefix, dep = requirement[0]) + + return build_content + def _pip_repository_impl(rctx): python_interpreter = _resolve_python_interpreter(rctx) @@ -234,7 +299,7 @@ def _pip_repository_impl(rctx): annotations_file = rctx.path("annotations.json") rctx.file(annotations_file, json.encode_indent(annotations, indent = " " * 4)) - requirements_txt = _locked_requirements(rctx) + requirements_txt = locked_requirements_label(rctx, rctx.attr) args = [ python_interpreter, "-m", @@ -250,6 +315,8 @@ def _pip_repository_impl(rctx): str(rctx.attr.timeout), "--annotations", annotations_file, + "--bzlmod", + str(rctx.attr.bzlmod).lower(), ] args += ["--python_interpreter", _get_python_interpreter_attr(rctx)] @@ -274,7 +341,12 @@ def _pip_repository_impl(rctx): fail("rules_python failed: %s (%s)" % (result.stdout, result.stderr)) # We need a BUILD file to load the generated requirements.bzl - rctx.file("BUILD.bazel", _BUILD_FILE_CONTENTS + "\n# The requirements.bzl file was generated by running:\n# " + " ".join([str(a) for a in args])) + build_contents = _BUILD_FILE_CONTENTS + + if rctx.attr.bzlmod: + build_contents += _bzlmod_pkg_aliases(rctx, requirements_txt) + + rctx.file("BUILD.bazel", build_contents + "\n# The requirements.bzl file was generated by running:\n# " + " ".join([str(a) for a in args])) return @@ -369,6 +441,12 @@ pip_repository_attrs = { "annotations": attr.string_dict( doc = "Optional annotations to apply to packages", ), + "bzlmod": attr.bool( + default = False, + doc = """Whether this repository rule is invoked under bzlmod, in which case +we do not create the install_deps() macro. +""", + ), "requirements_darwin": attr.label( allow_single_file = True, doc = "Override the requirements_lock attribute when the host platform is Mac OS", diff --git a/python/pip_install/repositories.bzl b/python/pip_install/repositories.bzl index 7c70104977..f225616ac4 100644 --- a/python/pip_install/repositories.bzl +++ b/python/pip_install/repositories.bzl @@ -103,7 +103,7 @@ py_library( all_requirements = [name for (name, _, _) in _RULE_DEPS] def requirement(pkg): - return "@pypi__" + pkg + "//:lib" + return Label("@pypi__" + pkg + "//:lib") def pip_install_dependencies(): """ From b8b9092764b775953843225c5dbf2469155e8fb4 Mon Sep 17 00:00:00 2001 From: Derek Cormier Date: Tue, 1 Nov 2022 11:03:50 -0700 Subject: [PATCH 063/234] Prepare for bzlmod release --- .bcr/config.yml | 3 +++ .bcr/presubmit.yml | 10 ++++++++ .bcr/source.template.json | 5 ++++ .bcr/template.metadata.json | 20 +++++++++++++++ .github/workflows/workspace_snippet.sh | 35 +++++++++++++++++++++++++- 5 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 .bcr/config.yml create mode 100644 .bcr/presubmit.yml create mode 100644 .bcr/source.template.json create mode 100644 .bcr/template.metadata.json diff --git a/.bcr/config.yml b/.bcr/config.yml new file mode 100644 index 0000000000..ac951f6594 --- /dev/null +++ b/.bcr/config.yml @@ -0,0 +1,3 @@ +fixedReleaser: + login: rickeylev + email: rlevasseur@google.com diff --git a/.bcr/presubmit.yml b/.bcr/presubmit.yml new file mode 100644 index 0000000000..2ab3c6dfe1 --- /dev/null +++ b/.bcr/presubmit.yml @@ -0,0 +1,10 @@ +bcr_test_module: + module_path: "examples/bzlmod" + matrix: + platform: ["debian10", "macos", "ubuntu2004", "windows"] + tasks: + run_tests: + name: "Run test module" + platform: ${{ platform }} + test_targets: + - "//..." diff --git a/.bcr/source.template.json b/.bcr/source.template.json new file mode 100644 index 0000000000..a3bd62f161 --- /dev/null +++ b/.bcr/source.template.json @@ -0,0 +1,5 @@ +{ + "integrity": "", + "strip_prefix": "{REPO}-{VERSION}", + "url": "https://github.com/{OWNER}/{REPO}/archive/refs/tags/{TAG}.tar.gz" +} diff --git a/.bcr/template.metadata.json b/.bcr/template.metadata.json new file mode 100644 index 0000000000..7b16b53b62 --- /dev/null +++ b/.bcr/template.metadata.json @@ -0,0 +1,20 @@ +{ + "homepage": "https://github.com/bazelbuild/rules_python", + "maintainers": [ + { + "name": "Richard Levasseur", + "email": "rlevasseur@google.com", + "github": "rickeylev" + }, + { + "name": "Thulio Ferraz Assis", + "email": "thulio@aspect.dev", + "github": "f0rmiga" + } + ], + "repository": [ + "github:bazelbuild/rules_python" + ], + "versions": [], + "yanked_versions": {} +} diff --git a/.github/workflows/workspace_snippet.sh b/.github/workflows/workspace_snippet.sh index 6fdaad35e7..9a51d06e3d 100755 --- a/.github/workflows/workspace_snippet.sh +++ b/.github/workflows/workspace_snippet.sh @@ -9,7 +9,40 @@ PREFIX="rules_python-${TAG}" SHA=$(git archive --format=tar --prefix=${PREFIX}/ ${TAG} | gzip | shasum -a 256 | awk '{print $1}') cat << EOF -WORKSPACE setup: +## Using Bzlmod with Bazel 6 + +Add to your \`MODULE.bazel\` file: + +\`\`\`starlark +bazel_dep(name = "rules_python", version = "${TAG}") + +pip = use_extension("@rules_python//python:extensions.bzl", "pip") + +pip.parse( + name = "pip", + requirements_lock = "//:requirements_lock.txt", +) + +use_repo(pip, "pip") + +# (Optional) Register a specific python toolchain instead of using the host version +python = use_extension("@rules_python//python:extensions.bzl", "python") + +python.toolchain( + name = "python3_9", + python_version = "3.9", +) + +use_repo(python, "python3_9_toolchains") + +register_toolchains( + "@python3_9_toolchains//:all", +) +\`\`\` + +## Using WORKSPACE: + +Paste this snippet into your \`WORKSPACE\` file: \`\`\`starlark load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") From 24a8b7460d03b7719d82a2ddfea794a0da4ac38d Mon Sep 17 00:00:00 2001 From: Derek Cormier Date: Mon, 7 Nov 2022 17:44:37 -0800 Subject: [PATCH 064/234] Setup fixed releaser for Publish to BCR app (#878) --- .bcr/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.bcr/config.yml b/.bcr/config.yml index ac951f6594..ba611eb33b 100644 --- a/.bcr/config.yml +++ b/.bcr/config.yml @@ -1,3 +1,3 @@ fixedReleaser: - login: rickeylev - email: rlevasseur@google.com + login: f0rmiga + email: thulio@aspect.dev From 3f0d62d18d5dfead0701b061e2f27774db6f64d6 Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Thu, 10 Nov 2022 10:37:30 -0800 Subject: [PATCH 065/234] fix(determinism): copy two missing entries from data_excludes (#881) We install some pip packages to bootstrap the pip_install/pip_parse rules, and these were allowing .pyc files as data deps. In some clients I observe that pip install is creating these with non-determinism and busting the python action caches. We already had a correct solution for user-installed packages, so we just need to include those entries for the built-ins. --- python/pip_install/repositories.bzl | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/python/pip_install/repositories.bzl b/python/pip_install/repositories.bzl index f225616ac4..8b027672df 100644 --- a/python/pip_install/repositories.bzl +++ b/python/pip_install/repositories.bzl @@ -92,7 +92,17 @@ load("@rules_python//python:defs.bzl", "py_library") py_library( name = "lib", srcs = glob(["**/*.py"]), - data = glob(["**/*"], exclude=["**/*.py", "**/* *", "BUILD", "WORKSPACE"]), + data = glob(["**/*"], exclude=[ + # These entries include those put into user-installed dependencies by + # data_exclude in /python/pip_install/extract_wheels/bazel.py + # to avoid non-determinism following pip install's behavior. + "**/*.py", + "**/*.pyc", + "**/* *", + "**/*.dist-info/RECORD", + "BUILD", + "WORKSPACE", + ]), # This makes this directory a top-level in the python import # search path for anything that depends on this. imports = ["."], From 912a5051f51581784fd64094f6bdabf93f6d698f Mon Sep 17 00:00:00 2001 From: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Date: Thu, 10 Nov 2022 10:43:53 -0800 Subject: [PATCH 066/234] fix: make conftest.py special with gazelle (#879) * fix: add conftest.py to py_test generated targets Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: use separate py_library for conftest.py This allows the conftest.py to be used on sub-directories as pytest would pick them up. Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: add testonly to conftest py_library Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: testonly is a boolean, not a string Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- gazelle/generate.go | 70 +++++++++++++++---- gazelle/target.go | 10 +++ .../simple_test_with_conftest/BUILD.in | 1 + .../simple_test_with_conftest/BUILD.out | 27 +++++++ .../simple_test_with_conftest/README.md | 4 ++ .../simple_test_with_conftest/WORKSPACE | 1 + .../simple_test_with_conftest/__init__.py | 3 + .../simple_test_with_conftest/__test__.py | 12 ++++ .../simple_test_with_conftest/conftest.py | 0 .../testdata/simple_test_with_conftest/foo.py | 2 + .../simple_test_with_conftest/test.yaml | 3 + 11 files changed, 121 insertions(+), 12 deletions(-) create mode 100644 gazelle/testdata/simple_test_with_conftest/BUILD.in create mode 100644 gazelle/testdata/simple_test_with_conftest/BUILD.out create mode 100644 gazelle/testdata/simple_test_with_conftest/README.md create mode 100644 gazelle/testdata/simple_test_with_conftest/WORKSPACE create mode 100644 gazelle/testdata/simple_test_with_conftest/__init__.py create mode 100644 gazelle/testdata/simple_test_with_conftest/__test__.py create mode 100644 gazelle/testdata/simple_test_with_conftest/conftest.py create mode 100644 gazelle/testdata/simple_test_with_conftest/foo.py create mode 100644 gazelle/testdata/simple_test_with_conftest/test.yaml diff --git a/gazelle/generate.go b/gazelle/generate.go index 077acb821a..c7b0709687 100644 --- a/gazelle/generate.go +++ b/gazelle/generate.go @@ -26,6 +26,8 @@ const ( pyBinaryEntrypointFilename = "__main__.py" pyTestEntrypointFilename = "__test__.py" pyTestEntrypointTargetname = "__test__" + conftestFilename = "conftest.py" + conftestTargetname = "conftest" ) var ( @@ -71,6 +73,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes // be generated for this package or not. hasPyTestFile := false hasPyTestTarget := false + hasConftestFile := false for _, f := range args.RegularFiles { if cfg.IgnoresFile(filepath.Base(f)) { @@ -81,6 +84,8 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes hasPyBinary = true } else if !hasPyTestFile && f == pyTestEntrypointFilename { hasPyTestFile = true + } else if f == conftestFilename { + hasConftestFile = true } else if strings.HasSuffix(f, "_test.py") || (strings.HasPrefix(f, "test_") && ext == ".py") { pyTestFilenames.Add(f) } else if ext == ".py" { @@ -196,10 +201,10 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes pyLibraryTargetName := cfg.RenderLibraryName(packageName) - // Check if a target with the same name we are generating alredy exists, - // and if it is of a different kind from the one we are generating. If - // so, we have to throw an error since Gazelle won't generate it - // correctly. + // Check if a target with the same name we are generating already + // exists, and if it is of a different kind from the one we are + // generating. If so, we have to throw an error since Gazelle won't + // generate it correctly. if args.File != nil { for _, t := range args.File.Rules { if t.Name() == pyLibraryTargetName && t.Kind() != pyLibraryKind { @@ -233,10 +238,10 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes pyBinaryTargetName := cfg.RenderBinaryName(packageName) - // Check if a target with the same name we are generating alredy exists, - // and if it is of a different kind from the one we are generating. If - // so, we have to throw an error since Gazelle won't generate it - // correctly. + // Check if a target with the same name we are generating already + // exists, and if it is of a different kind from the one we are + // generating. If so, we have to throw an error since Gazelle won't + // generate it correctly. if args.File != nil { for _, t := range args.File.Rules { if t.Name() == pyBinaryTargetName && t.Kind() != pyBinaryKind { @@ -267,6 +272,43 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes result.Imports = append(result.Imports, pyBinary.PrivateAttr(config.GazelleImportsKey)) } + var conftest *rule.Rule + if hasConftestFile { + deps, err := parser.parseSingle(conftestFilename) + if err != nil { + log.Fatalf("ERROR: %v\n", err) + } + + // Check if a target with the same name we are generating already + // exists, and if it is of a different kind from the one we are + // generating. If so, we have to throw an error since Gazelle won't + // generate it correctly. + if args.File != nil { + for _, t := range args.File.Rules { + if t.Name() == conftestTargetname && t.Kind() != pyLibraryKind { + fqTarget := label.New("", args.Rel, conftestTargetname) + err := fmt.Errorf("failed to generate target %q of kind %q: "+ + "a target of kind %q with the same name already exists.", + fqTarget.String(), pyLibraryKind, t.Kind()) + collisionErrors.Add(err) + } + } + } + + conftestTarget := newTargetBuilder(pyLibraryKind, conftestTargetname, pythonProjectRoot, args.Rel). + setUUID(uuid.Must(uuid.NewUUID()).String()). + addSrc(conftestFilename). + addModuleDependencies(deps). + addVisibility(visibility). + setTestonly(). + generateImportsAttribute() + + conftest = conftestTarget.build() + + result.Gen = append(result.Gen, conftest) + result.Imports = append(result.Imports, conftest.PrivateAttr(config.GazelleImportsKey)) + } + if hasPyTestFile || hasPyTestTarget { if hasPyTestFile { // Only add the pyTestEntrypointFilename to the pyTestFilenames if @@ -280,10 +322,10 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes pyTestTargetName := cfg.RenderTestName(packageName) - // Check if a target with the same name we are generating alredy exists, - // and if it is of a different kind from the one we are generating. If - // so, we have to throw an error since Gazelle won't generate it - // correctly. + // Check if a target with the same name we are generating already + // exists, and if it is of a different kind from the one we are + // generating. If so, we have to throw an error since Gazelle won't + // generate it correctly. if args.File != nil { for _, t := range args.File.Rules { if t.Name() == pyTestTargetName && t.Kind() != pyTestKind { @@ -317,6 +359,10 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes pyTestTarget.addModuleDependency(module{Name: pyLibrary.PrivateAttr(uuidKey).(string)}) } + if conftest != nil { + pyTestTarget.addModuleDependency(module{Name: conftest.PrivateAttr(uuidKey).(string)}) + } + pyTest := pyTestTarget.build() result.Gen = append(result.Gen, pyTest) diff --git a/gazelle/target.go b/gazelle/target.go index 2b260679b6..eef3aedd8d 100644 --- a/gazelle/target.go +++ b/gazelle/target.go @@ -22,6 +22,7 @@ type targetBuilder struct { visibility *treeset.Set main *string imports []string + testonly bool } // newTargetBuilder constructs a new targetBuilder. @@ -96,6 +97,12 @@ func (t *targetBuilder) setMain(main string) *targetBuilder { return t } +// setTestonly sets the testonly attribute to true. +func (t *targetBuilder) setTestonly() *targetBuilder { + t.testonly = true + return t +} + // generateImportsAttribute generates the imports attribute. // These are a list of import directories to be added to the PYTHONPATH. In our // case, the value we add is on Bazel sub-packages to be able to perform imports @@ -131,6 +138,9 @@ func (t *targetBuilder) build() *rule.Rule { if !t.deps.Empty() { r.SetPrivateAttr(config.GazelleImportsKey, t.deps) } + if t.testonly { + r.SetAttr("testonly", true) + } r.SetPrivateAttr(resolvedDepsKey, t.resolvedDeps) return r } diff --git a/gazelle/testdata/simple_test_with_conftest/BUILD.in b/gazelle/testdata/simple_test_with_conftest/BUILD.in new file mode 100644 index 0000000000..3f2beb3147 --- /dev/null +++ b/gazelle/testdata/simple_test_with_conftest/BUILD.in @@ -0,0 +1 @@ +load("@rules_python//python:defs.bzl", "py_library") diff --git a/gazelle/testdata/simple_test_with_conftest/BUILD.out b/gazelle/testdata/simple_test_with_conftest/BUILD.out new file mode 100644 index 0000000000..18079bf2f4 --- /dev/null +++ b/gazelle/testdata/simple_test_with_conftest/BUILD.out @@ -0,0 +1,27 @@ +load("@rules_python//python:defs.bzl", "py_library", "py_test") + +py_library( + name = "simple_test_with_conftest", + srcs = [ + "__init__.py", + "foo.py", + ], + visibility = ["//:__subpackages__"], +) + +py_library( + name = "conftest", + testonly = True, + srcs = ["conftest.py"], + visibility = ["//:__subpackages__"], +) + +py_test( + name = "simple_test_with_conftest_test", + srcs = ["__test__.py"], + main = "__test__.py", + deps = [ + ":conftest", + ":simple_test_with_conftest", + ], +) diff --git a/gazelle/testdata/simple_test_with_conftest/README.md b/gazelle/testdata/simple_test_with_conftest/README.md new file mode 100644 index 0000000000..0ff245f808 --- /dev/null +++ b/gazelle/testdata/simple_test_with_conftest/README.md @@ -0,0 +1,4 @@ +# Simple test with conftest.py + +This test case asserts that a simple `py_test` is generated as expected when a +`conftest.py` is present. diff --git a/gazelle/testdata/simple_test_with_conftest/WORKSPACE b/gazelle/testdata/simple_test_with_conftest/WORKSPACE new file mode 100644 index 0000000000..faff6af87a --- /dev/null +++ b/gazelle/testdata/simple_test_with_conftest/WORKSPACE @@ -0,0 +1 @@ +# This is a Bazel workspace for the Gazelle test data. diff --git a/gazelle/testdata/simple_test_with_conftest/__init__.py b/gazelle/testdata/simple_test_with_conftest/__init__.py new file mode 100644 index 0000000000..6a49193fe4 --- /dev/null +++ b/gazelle/testdata/simple_test_with_conftest/__init__.py @@ -0,0 +1,3 @@ +from foo import foo + +_ = foo diff --git a/gazelle/testdata/simple_test_with_conftest/__test__.py b/gazelle/testdata/simple_test_with_conftest/__test__.py new file mode 100644 index 0000000000..d6085a41b4 --- /dev/null +++ b/gazelle/testdata/simple_test_with_conftest/__test__.py @@ -0,0 +1,12 @@ +import unittest + +from __init__ import foo + + +class FooTest(unittest.TestCase): + def test_foo(self): + self.assertEqual("foo", foo()) + + +if __name__ == "__main__": + unittest.main() diff --git a/gazelle/testdata/simple_test_with_conftest/conftest.py b/gazelle/testdata/simple_test_with_conftest/conftest.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/testdata/simple_test_with_conftest/foo.py b/gazelle/testdata/simple_test_with_conftest/foo.py new file mode 100644 index 0000000000..cf68624419 --- /dev/null +++ b/gazelle/testdata/simple_test_with_conftest/foo.py @@ -0,0 +1,2 @@ +def foo(): + return "foo" diff --git a/gazelle/testdata/simple_test_with_conftest/test.yaml b/gazelle/testdata/simple_test_with_conftest/test.yaml new file mode 100644 index 0000000000..36dd656b39 --- /dev/null +++ b/gazelle/testdata/simple_test_with_conftest/test.yaml @@ -0,0 +1,3 @@ +--- +expect: + exit_code: 0 From a3b694362319f260aee645b6c376c952448cd468 Mon Sep 17 00:00:00 2001 From: John Laxson Date: Fri, 18 Nov 2022 16:38:04 -0800 Subject: [PATCH 067/234] Expose python3n.lib as libpython's interface_library (#890) --- python/repositories.bzl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/repositories.bzl b/python/repositories.bzl index efde00a4e7..6965bcd70a 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -225,7 +225,7 @@ cc_library( name = "libpython", hdrs = [":includes"], srcs = select({{ - "@platforms//os:windows": ["python3.dll"], + "@platforms//os:windows": ["python3.dll", "libs/python{python_version_nodot}.lib"], "@platforms//os:macos": ["lib/libpython{python_version}.dylib"], "@platforms//os:linux": ["lib/libpython{python_version}.so", "lib/libpython{python_version}.so.1.0"], }}), @@ -249,6 +249,7 @@ py_runtime_pair( glob_include = repr(glob_include), python_path = python_bin, python_version = python_short_version, + python_version_nodot = python_short_version.replace(".", ""), ) rctx.delete("python") rctx.symlink(python_bin, "python") From 4a0c7635638ccc34c670e66b31f311956bdaa418 Mon Sep 17 00:00:00 2001 From: Philipp Schrader Date: Sat, 19 Nov 2022 14:55:49 -0800 Subject: [PATCH 068/234] Fix //docs:update (#876) Fix //docs:update Also regenerates docs with the new stardoc version. Right now the command errors out on fresh clones or after a `bazel clean`. $ bazel run //docs:update cp: cannot stat 'bazel-bin/docs/packaging.md_': No such file or directory cp: cannot stat 'bazel-bin/docs/pip.md_': No such file or directory cp: cannot stat 'bazel-bin/docs/pip_repository.md_': No such file or directory cp: cannot stat 'bazel-bin/docs/python.md_': No such file or directory I submitted bazelbuild/stardoc#139 to fix this. @brandjon pointed out that this should just work as-is, but doesn't because of bazelbuild/bazel#15043. Until the bazel bug is addressed, we can make `//docs:update` work by pulling in the latest stardoc version. One side effect of this patch is that the generated documentation itself changed a decent amount. Now the tool works again without errors even after a fresh clone or a `bazel clean` $ bazel run //docs:update 'bazel-bin/docs/packaging.md_' -> 'docs/packaging.md' 'bazel-bin/docs/pip.md_' -> 'docs/pip.md' 'bazel-bin/docs/pip_repository.md_' -> 'docs/pip_repository.md' 'bazel-bin/docs/python.md_' -> 'docs/python.md' --- docs/packaging.md | 70 ++++++++++----------- docs/pip.md | 74 +++++++++++----------- docs/pip_repository.md | 136 +++++++++++++++++++++++------------------ docs/python.md | 68 +++++++++++---------- internal_deps.bzl | 6 +- 5 files changed, 191 insertions(+), 163 deletions(-) diff --git a/docs/packaging.md b/docs/packaging.md index af822b07eb..22e6419d1d 100755 --- a/docs/packaging.md +++ b/docs/packaging.md @@ -1,6 +1,8 @@ - +Rules for building wheels. + + ## py_package @@ -18,13 +20,13 @@ This rule is intended to be used as data dependency to py_wheel rule | Name | Description | Type | Mandatory | Default | -| :-------------: | :-------------: | :-------------: | :-------------: | :-------------: | -| name | A unique name for this target. | Name | required | | -| deps | - | List of labels | optional | [] | -| packages | List of Python packages to include in the distribution. Sub-packages are automatically included. | List of strings | optional | [] | +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this target. | Name | required | | +| deps | - | List of labels | optional | [] | +| packages | List of Python packages to include in the distribution. Sub-packages are automatically included. | List of strings | optional | [] | - + ## py_wheel @@ -83,31 +85,31 @@ py_wheel( | Name | Description | Type | Mandatory | Default | -| :-------------: | :-------------: | :-------------: | :-------------: | :-------------: | -| name | A unique name for this target. | Name | required | | -| abi | Python ABI tag. 'none' for pure-Python wheels. | String | optional | "none" | -| author | A string specifying the author of the package. | String | optional | "" | -| author_email | A string specifying the email address of the package author. | String | optional | "" | -| classifiers | A list of strings describing the categories for the package. For valid classifiers see https://pypi.org/classifiers | List of strings | optional | [] | -| console_scripts | Deprecated console_script entry points, e.g. {'main': 'examples.wheel.main:main'}.

Deprecated: prefer the entry_points attribute, which supports console_scripts as well as other entry points. | Dictionary: String -> String | optional | {} | -| deps | Targets to be included in the distribution.

The targets to package are usually py_library rules or filesets (for packaging data files).

Note it's usually better to package py_library targets and use entry_points attribute to specify console_scripts than to package py_binary rules. py_binary targets would wrap a executable script that tries to locate .runfiles directory which is not packaged in the wheel. | List of labels | optional | [] | -| description_file | A file containing text describing the package. | Label | optional | None | -| distribution | Name of the distribution.

This should match the project name onm PyPI. It's also the name that is used to refer to the package in other packages' dependencies. | String | required | | -| entry_points | entry_points, e.g. {'console_scripts': ['main = examples.wheel.main:main']}. | Dictionary: String -> List of strings | optional | {} | -| extra_distinfo_files | Extra files to add to distinfo directory in the archive. | Dictionary: Label -> String | optional | {} | -| extra_requires | List of optional requirements for this package | Dictionary: String -> List of strings | optional | {} | -| homepage | A string specifying the URL for the package homepage. | String | optional | "" | -| license | A string specifying the license of the package. | String | optional | "" | -| platform | Supported platform. Use 'any' for pure-Python wheel.

If you have included platform-specific data, such as a .pyd or .so extension module, you will need to specify the platform in standard pip format. If you support multiple platforms, you can define platform constraints, then use a select() to specify the appropriate specifier, eg:

platform = select({ "//platforms:windows_x86_64": "win_amd64", "//platforms:macos_x86_64": "macosx_10_7_x86_64", "//platforms:linux_x86_64": "manylinux2014_x86_64", }) | String | optional | "any" | -| python_requires | Python versions required by this distribution, e.g. '>=3.5,<3.7' | String | optional | "" | -| python_tag | Supported Python version(s), eg py3, cp35.cp36, etc | String | optional | "py3" | -| requires | List of requirements for this package. See the section on [Declaring required dependency](https://setuptools.readthedocs.io/en/latest/userguide/dependency_management.html#declaring-dependencies) for details and examples of the format of this argument. | List of strings | optional | [] | -| stamp | Whether to encode build information into the wheel. Possible values:

- stamp = 1: Always stamp the build information into the wheel, even in [--nostamp](https://docs.bazel.build/versions/main/user-manual.html#flag--stamp) builds. This setting should be avoided, since it potentially kills remote caching for the target and any downstream actions that depend on it.

- stamp = 0: Always replace build information by constant values. This gives good build result caching.

- stamp = -1: Embedding of build information is controlled by the [--[no]stamp](https://docs.bazel.build/versions/main/user-manual.html#flag--stamp) flag.

Stamped targets are not rebuilt unless their dependencies change. | Integer | optional | -1 | -| strip_path_prefixes | path prefixes to strip from files added to the generated package | List of strings | optional | [] | -| version | Version number of the package. Note that this attribute supports stamp format strings (eg. 1.2.3-{BUILD_TIMESTAMP}) as well as 'make variables' (e.g. 1.2.3-$(VERSION)). | String | required | | - - - +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this target. | Name | required | | +| abi | Python ABI tag. 'none' for pure-Python wheels. | String | optional | "none" | +| author | A string specifying the author of the package. | String | optional | "" | +| author_email | A string specifying the email address of the package author. | String | optional | "" | +| classifiers | A list of strings describing the categories for the package. For valid classifiers see https://pypi.org/classifiers | List of strings | optional | [] | +| console_scripts | Deprecated console_script entry points, e.g. {'main': 'examples.wheel.main:main'}.

Deprecated: prefer the entry_points attribute, which supports console_scripts as well as other entry points. | Dictionary: String -> String | optional | {} | +| deps | Targets to be included in the distribution.

The targets to package are usually py_library rules or filesets (for packaging data files).

Note it's usually better to package py_library targets and use entry_points attribute to specify console_scripts than to package py_binary rules. py_binary targets would wrap a executable script that tries to locate .runfiles directory which is not packaged in the wheel. | List of labels | optional | [] | +| description_file | A file containing text describing the package. | Label | optional | None | +| distribution | Name of the distribution.

This should match the project name onm PyPI. It's also the name that is used to refer to the package in other packages' dependencies. | String | required | | +| entry_points | entry_points, e.g. {'console_scripts': ['main = examples.wheel.main:main']}. | Dictionary: String -> List of strings | optional | {} | +| extra_distinfo_files | Extra files to add to distinfo directory in the archive. | Dictionary: Label -> String | optional | {} | +| extra_requires | List of optional requirements for this package | Dictionary: String -> List of strings | optional | {} | +| homepage | A string specifying the URL for the package homepage. | String | optional | "" | +| license | A string specifying the license of the package. | String | optional | "" | +| platform | Supported platform. Use 'any' for pure-Python wheel.

If you have included platform-specific data, such as a .pyd or .so extension module, you will need to specify the platform in standard pip format. If you support multiple platforms, you can define platform constraints, then use a select() to specify the appropriate specifier, eg:

platform = select({ "//platforms:windows_x86_64": "win_amd64", "//platforms:macos_x86_64": "macosx_10_7_x86_64", "//platforms:linux_x86_64": "manylinux2014_x86_64", }) | String | optional | "any" | +| python_requires | Python versions required by this distribution, e.g. '>=3.5,<3.7' | String | optional | "" | +| python_tag | Supported Python version(s), eg py3, cp35.cp36, etc | String | optional | "py3" | +| requires | List of requirements for this package. See the section on [Declaring required dependency](https://setuptools.readthedocs.io/en/latest/userguide/dependency_management.html#declaring-dependencies) for details and examples of the format of this argument. | List of strings | optional | [] | +| stamp | Whether to encode build information into the wheel. Possible values:

- stamp = 1: Always stamp the build information into the wheel, even in [--nostamp](https://docs.bazel.build/versions/main/user-manual.html#flag--stamp) builds. This setting should be avoided, since it potentially kills remote caching for the target and any downstream actions that depend on it.

- stamp = 0: Always replace build information by constant values. This gives good build result caching.

- stamp = -1: Embedding of build information is controlled by the [--[no]stamp](https://docs.bazel.build/versions/main/user-manual.html#flag--stamp) flag.

Stamped targets are not rebuilt unless their dependencies change. | Integer | optional | -1 | +| strip_path_prefixes | path prefixes to strip from files added to the generated package | List of strings | optional | [] | +| version | Version number of the package. Note that this attribute supports stamp format strings (eg. 1.2.3-{BUILD_TIMESTAMP}) as well as 'make variables' (e.g. 1.2.3-$(VERSION)). | String | required | | + + + ## PyWheelInfo @@ -121,8 +123,8 @@ Information about a wheel produced by `py_wheel` | Name | Description | -| :-------------: | :-------------: | -| name_file | File: A file containing the canonical name of the wheel (after stamping, if enabled). | -| wheel | File: The wheel file itself. | +| :------------- | :------------- | +| name_file | File: A file containing the canonical name of the wheel (after stamping, if enabled). | +| wheel | File: The wheel file itself. | diff --git a/docs/pip.md b/docs/pip.md index 7f70ef5066..fc38f0fea3 100644 --- a/docs/pip.md +++ b/docs/pip.md @@ -1,6 +1,8 @@ - +Import pip requirements into Bazel. + + ## compile_pip_requirements @@ -17,28 +19,28 @@ of some other compile_pip_requirements rule that references these requirements It also generates two targets for running pip-compile: -- validate with `bazel test _test` -- update with `bazel run .update` +- validate with `bazel test <name>_test` +- update with `bazel run <name>.update` **PARAMETERS** | Name | Description | Default Value | -| :-------------: | :-------------: | :-------------: | -| name | base name for generated targets, typically "requirements" | none | -| extra_args | passed to pip-compile | [] | -| visibility | passed to both the _test and .update rules | ["//visibility:private"] | -| requirements_in | file expressing desired dependencies | None | -| requirements_txt | result of "compiling" the requirements.in file | None | -| requirements_linux | File of linux specific resolve output to check validate if requirement.in has changes. | None | -| requirements_darwin | File of darwin specific resolve output to check validate if requirement.in has changes. | None | -| requirements_windows | File of windows specific resolve output to check validate if requirement.in has changes. | None | -| tags | tagging attribute common to all build rules, passed to both the _test and .update rules | None | -| kwargs | other bazel attributes passed to the "_test" rule | none | +| :------------- | :------------- | :------------- | +| name | base name for generated targets, typically "requirements" | none | +| extra_args | passed to pip-compile | [] | +| visibility | passed to both the _test and .update rules | ["//visibility:private"] | +| requirements_in | file expressing desired dependencies | None | +| requirements_txt | result of "compiling" the requirements.in file | None | +| requirements_linux | File of linux specific resolve output to check validate if requirement.in has changes. | None | +| requirements_darwin | File of darwin specific resolve output to check validate if requirement.in has changes. | None | +| requirements_windows | File of windows specific resolve output to check validate if requirement.in has changes. | None | +| tags | tagging attribute common to all build rules, passed to both the _test and .update rules | None | +| kwargs | other bazel attributes passed to the "_test" rule | none | - + ## package_annotation @@ -56,16 +58,20 @@ Annotations to apply to the BUILD file content from package generated from a `pi | Name | Description | Default Value | -| :-------------: | :-------------: | :-------------: | -| additive_build_content | Raw text to add to the generated BUILD file of a package. | None | -| copy_files | A mapping of src and out files for [@bazel_skylib//rules:copy_file.bzl][cf] | {} | -| copy_executables | A mapping of src and out files for [@bazel_skylib//rules:copy_file.bzl][cf]. Targets generated here will also be flagged as executable. | {} | -| data | A list of labels to add as data dependencies to the generated py_library target. | [] | -| data_exclude_glob | A list of exclude glob patterns to add as data to the generated py_library target. | [] | -| srcs_exclude_glob | A list of labels to add as srcs to the generated py_library target. | [] | +| :------------- | :------------- | :------------- | +| additive_build_content | Raw text to add to the generated BUILD file of a package. | None | +| copy_files | A mapping of src and out files for [@bazel_skylib//rules:copy_file.bzl][cf] | {} | +| copy_executables | A mapping of src and out files for [@bazel_skylib//rules:copy_file.bzl][cf]. Targets generated here will also be flagged as executable. | {} | +| data | A list of labels to add as data dependencies to the generated py_library target. | [] | +| data_exclude_glob | A list of exclude glob patterns to add as data to the generated py_library target. | [] | +| srcs_exclude_glob | A list of labels to add as srcs to the generated py_library target. | [] | + +**RETURNS** + +str: A json encoded string of the provided content. - + ## pip_install @@ -93,13 +99,13 @@ install_deps() | Name | Description | Default Value | -| :-------------: | :-------------: | :-------------: | -| requirements | A 'requirements.txt' pip requirements file. | None | -| name | A unique name for the created external repository (default 'pip'). | "pip" | -| kwargs | Additional arguments to the [pip_repository](./pip_repository.md) repository rule. | none | +| :------------- | :------------- | :------------- | +| requirements | A 'requirements.txt' pip requirements file. | None | +| name | A unique name for the created external repository (default 'pip'). | "pip" | +| kwargs | Additional arguments to the [pip_repository](./pip_repository.md) repository rule. | none | - + ## pip_parse @@ -196,11 +202,11 @@ See the example in rules_python/examples/pip_parse_vendored. | Name | Description | Default Value | -| :-------------: | :-------------: | :-------------: | -| requirements | Deprecated. See requirements_lock. | None | -| requirements_lock | A fully resolved 'requirements.txt' pip requirement file containing the transitive set of your dependencies. If this file is passed instead of 'requirements' no resolve will take place and pip_repository will create individual repositories for each of your dependencies so that wheels are fetched/built only for the targets specified by 'build/run/test'. Note that if your lockfile is platform-dependent, you can use the requirements_[platform] attributes. | None | -| name | The name of the generated repository. The generated repositories containing each requirement will be of the form <name>_<requirement-name>. | "pip_parsed_deps" | -| bzlmod | Whether this rule is being run under a bzlmod module extension. | False | -| kwargs | Additional arguments to the [pip_repository](./pip_repository.md) repository rule. | none | +| :------------- | :------------- | :------------- | +| requirements | Deprecated. See requirements_lock. | None | +| requirements_lock | A fully resolved 'requirements.txt' pip requirement file containing the transitive set of your dependencies. If this file is passed instead of 'requirements' no resolve will take place and pip_repository will create individual repositories for each of your dependencies so that wheels are fetched/built only for the targets specified by 'build/run/test'. Note that if your lockfile is platform-dependent, you can use the requirements_[platform] attributes. | None | +| name | The name of the generated repository. The generated repositories containing each requirement will be of the form <name>_<requirement-name>. | "pip_parsed_deps" | +| bzlmod | Whether this rule is being run under a bzlmod module extension. | False | +| kwargs | Additional arguments to the [pip_repository](./pip_repository.md) repository rule. | none | diff --git a/docs/pip_repository.md b/docs/pip_repository.md index 20816054a9..ae9100a315 100644 --- a/docs/pip_repository.md +++ b/docs/pip_repository.md @@ -1,14 +1,16 @@ - + + + ## pip_repository
 pip_repository(name, annotations, bzlmod, download_only, enable_implicit_namespace_pkgs,
                environment, extra_pip_args, isolated, pip_data_exclude, python_interpreter,
-               python_interpreter_target, quiet, repo_prefix, requirements_darwin, requirements_linux,
-               requirements_lock, requirements_windows, timeout)
+               python_interpreter_target, quiet, repo_mapping, repo_prefix, requirements_darwin,
+               requirements_linux, requirements_lock, requirements_windows, timeout)
 
A rule for importing `requirements.txt` dependencies into Bazel. @@ -55,35 +57,36 @@ py_binary( | Name | Description | Type | Mandatory | Default | -| :-------------: | :-------------: | :-------------: | :-------------: | :-------------: | -| name | A unique name for this repository. | Name | required | | -| annotations | Optional annotations to apply to packages | Dictionary: String -> String | optional | {} | -| bzlmod | Whether this repository rule is invoked under bzlmod, in which case we do not create the install_deps() macro. | Boolean | optional | False | -| download_only | Whether to use "pip download" instead of "pip wheel". Disables building wheels from source, but allows use of --platform, --python-version, --implementation, and --abi in --extra_pip_args to download wheels for a different platform from the host platform. | Boolean | optional | False | -| enable_implicit_namespace_pkgs | If true, disables conversion of native namespace packages into pkg-util style namespace packages. When set all py_binary and py_test targets must specify either legacy_create_init=False or the global Bazel option --incompatible_default_to_explicit_init_py to prevent __init__.py being automatically generated in every directory.

This option is required to support some packages which cannot handle the conversion to pkg-util style. | Boolean | optional | False | -| environment | Environment variables to set in the pip subprocess. Can be used to set common variables such as http_proxy, https_proxy and no_proxy Note that pip is run with "--isolated" on the CLI so PIP_<VAR>_<NAME> style env vars are ignored, but env vars that control requests and urllib3 can be passed. | Dictionary: String -> String | optional | {} | -| extra_pip_args | Extra arguments to pass on to pip. Must not contain spaces. | List of strings | optional | [] | -| isolated | Whether or not to pass the [--isolated](https://pip.pypa.io/en/stable/cli/pip/#cmdoption-isolated) flag to the underlying pip command. Alternatively, the RULES_PYTHON_PIP_ISOLATED enviornment varaible can be used to control this flag. | Boolean | optional | True | -| pip_data_exclude | Additional data exclusion parameters to add to the pip packages BUILD file. | List of strings | optional | [] | -| python_interpreter | The python interpreter to use. This can either be an absolute path or the name of a binary found on the host's PATH environment variable. If no value is set python3 is defaulted for Unix systems and python.exe for Windows. | String | optional | "" | -| python_interpreter_target | If you are using a custom python interpreter built by another repository rule, use this attribute to specify its BUILD target. This allows pip_repository to invoke pip using the same interpreter as your toolchain. If set, takes precedence over python_interpreter. | Label | optional | None | -| quiet | If True, suppress printing stdout and stderr output to the terminal. | Boolean | optional | True | -| repo_prefix | Prefix for the generated packages will be of the form

@<prefix><sanitized-package-name>//... | String | optional | "" | -| requirements_darwin | Override the requirements_lock attribute when the host platform is Mac OS | Label | optional | None | -| requirements_linux | Override the requirements_lock attribute when the host platform is Linux | Label | optional | None | -| requirements_lock | A fully resolved 'requirements.txt' pip requirement file containing the transitive set of your dependencies. If this file is passed instead of 'requirements' no resolve will take place and pip_repository will create individual repositories for each of your dependencies so that wheels are fetched/built only for the targets specified by 'build/run/test'. | Label | optional | None | -| requirements_windows | Override the requirements_lock attribute when the host platform is Windows | Label | optional | None | -| timeout | Timeout (in seconds) on the rule's execution duration. | Integer | optional | 600 | - - - +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this repository. | Name | required | | +| annotations | Optional annotations to apply to packages | Dictionary: String -> String | optional | {} | +| bzlmod | Whether this repository rule is invoked under bzlmod, in which case we do not create the install_deps() macro. | Boolean | optional | False | +| download_only | Whether to use "pip download" instead of "pip wheel". Disables building wheels from source, but allows use of --platform, --python-version, --implementation, and --abi in --extra_pip_args to download wheels for a different platform from the host platform. | Boolean | optional | False | +| enable_implicit_namespace_pkgs | If true, disables conversion of native namespace packages into pkg-util style namespace packages. When set all py_binary and py_test targets must specify either legacy_create_init=False or the global Bazel option --incompatible_default_to_explicit_init_py to prevent __init__.py being automatically generated in every directory.

This option is required to support some packages which cannot handle the conversion to pkg-util style. | Boolean | optional | False | +| environment | Environment variables to set in the pip subprocess. Can be used to set common variables such as http_proxy, https_proxy and no_proxy Note that pip is run with "--isolated" on the CLI so PIP_<VAR>_<NAME> style env vars are ignored, but env vars that control requests and urllib3 can be passed. | Dictionary: String -> String | optional | {} | +| extra_pip_args | Extra arguments to pass on to pip. Must not contain spaces. | List of strings | optional | [] | +| isolated | Whether or not to pass the [--isolated](https://pip.pypa.io/en/stable/cli/pip/#cmdoption-isolated) flag to the underlying pip command. Alternatively, the RULES_PYTHON_PIP_ISOLATED enviornment varaible can be used to control this flag. | Boolean | optional | True | +| pip_data_exclude | Additional data exclusion parameters to add to the pip packages BUILD file. | List of strings | optional | [] | +| python_interpreter | The python interpreter to use. This can either be an absolute path or the name of a binary found on the host's PATH environment variable. If no value is set python3 is defaulted for Unix systems and python.exe for Windows. | String | optional | "" | +| python_interpreter_target | If you are using a custom python interpreter built by another repository rule, use this attribute to specify its BUILD target. This allows pip_repository to invoke pip using the same interpreter as your toolchain. If set, takes precedence over python_interpreter. | Label | optional | None | +| quiet | If True, suppress printing stdout and stderr output to the terminal. | Boolean | optional | True | +| repo_mapping | A dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.<p>For example, an entry "@foo": "@bar" declares that, for any time this repository depends on @foo (such as a dependency on @foo//some:target, it should actually resolve that dependency within globally-declared @bar (@bar//some:target). | Dictionary: String -> String | required | | +| repo_prefix | Prefix for the generated packages will be of the form

@<prefix><sanitized-package-name>//... | String | optional | "" | +| requirements_darwin | Override the requirements_lock attribute when the host platform is Mac OS | Label | optional | None | +| requirements_linux | Override the requirements_lock attribute when the host platform is Linux | Label | optional | None | +| requirements_lock | A fully resolved 'requirements.txt' pip requirement file containing the transitive set of your dependencies. If this file is passed instead of 'requirements' no resolve will take place and pip_repository will create individual repositories for each of your dependencies so that wheels are fetched/built only for the targets specified by 'build/run/test'. | Label | optional | None | +| requirements_windows | Override the requirements_lock attribute when the host platform is Windows | Label | optional | None | +| timeout | Timeout (in seconds) on the rule's execution duration. | Integer | optional | 600 | + + + ## whl_library
 whl_library(name, annotation, download_only, enable_implicit_namespace_pkgs, environment,
             extra_pip_args, isolated, pip_data_exclude, python_interpreter, python_interpreter_target,
-            quiet, repo, repo_prefix, requirement, timeout)
+            quiet, repo, repo_mapping, repo_prefix, requirement, timeout)
 
@@ -94,25 +97,26 @@ Instantiated from pip_repository and inherits config options from there. | Name | Description | Type | Mandatory | Default | -| :-------------: | :-------------: | :-------------: | :-------------: | :-------------: | -| name | A unique name for this repository. | Name | required | | -| annotation | Optional json encoded file containing annotation to apply to the extracted wheel. See package_annotation | Label | optional | None | -| download_only | Whether to use "pip download" instead of "pip wheel". Disables building wheels from source, but allows use of --platform, --python-version, --implementation, and --abi in --extra_pip_args to download wheels for a different platform from the host platform. | Boolean | optional | False | -| enable_implicit_namespace_pkgs | If true, disables conversion of native namespace packages into pkg-util style namespace packages. When set all py_binary and py_test targets must specify either legacy_create_init=False or the global Bazel option --incompatible_default_to_explicit_init_py to prevent __init__.py being automatically generated in every directory.

This option is required to support some packages which cannot handle the conversion to pkg-util style. | Boolean | optional | False | -| environment | Environment variables to set in the pip subprocess. Can be used to set common variables such as http_proxy, https_proxy and no_proxy Note that pip is run with "--isolated" on the CLI so PIP_<VAR>_<NAME> style env vars are ignored, but env vars that control requests and urllib3 can be passed. | Dictionary: String -> String | optional | {} | -| extra_pip_args | Extra arguments to pass on to pip. Must not contain spaces. | List of strings | optional | [] | -| isolated | Whether or not to pass the [--isolated](https://pip.pypa.io/en/stable/cli/pip/#cmdoption-isolated) flag to the underlying pip command. Alternatively, the RULES_PYTHON_PIP_ISOLATED enviornment varaible can be used to control this flag. | Boolean | optional | True | -| pip_data_exclude | Additional data exclusion parameters to add to the pip packages BUILD file. | List of strings | optional | [] | -| python_interpreter | The python interpreter to use. This can either be an absolute path or the name of a binary found on the host's PATH environment variable. If no value is set python3 is defaulted for Unix systems and python.exe for Windows. | String | optional | "" | -| python_interpreter_target | If you are using a custom python interpreter built by another repository rule, use this attribute to specify its BUILD target. This allows pip_repository to invoke pip using the same interpreter as your toolchain. If set, takes precedence over python_interpreter. | Label | optional | None | -| quiet | If True, suppress printing stdout and stderr output to the terminal. | Boolean | optional | True | -| repo | Pointer to parent repo name. Used to make these rules rerun if the parent repo changes. | String | required | | -| repo_prefix | Prefix for the generated packages will be of the form

@<prefix><sanitized-package-name>//... | String | optional | "" | -| requirement | Python requirement string describing the package to make available | String | required | | -| timeout | Timeout (in seconds) on the rule's execution duration. | Integer | optional | 600 | - - - +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this repository. | Name | required | | +| annotation | Optional json encoded file containing annotation to apply to the extracted wheel. See package_annotation | Label | optional | None | +| download_only | Whether to use "pip download" instead of "pip wheel". Disables building wheels from source, but allows use of --platform, --python-version, --implementation, and --abi in --extra_pip_args to download wheels for a different platform from the host platform. | Boolean | optional | False | +| enable_implicit_namespace_pkgs | If true, disables conversion of native namespace packages into pkg-util style namespace packages. When set all py_binary and py_test targets must specify either legacy_create_init=False or the global Bazel option --incompatible_default_to_explicit_init_py to prevent __init__.py being automatically generated in every directory.

This option is required to support some packages which cannot handle the conversion to pkg-util style. | Boolean | optional | False | +| environment | Environment variables to set in the pip subprocess. Can be used to set common variables such as http_proxy, https_proxy and no_proxy Note that pip is run with "--isolated" on the CLI so PIP_<VAR>_<NAME> style env vars are ignored, but env vars that control requests and urllib3 can be passed. | Dictionary: String -> String | optional | {} | +| extra_pip_args | Extra arguments to pass on to pip. Must not contain spaces. | List of strings | optional | [] | +| isolated | Whether or not to pass the [--isolated](https://pip.pypa.io/en/stable/cli/pip/#cmdoption-isolated) flag to the underlying pip command. Alternatively, the RULES_PYTHON_PIP_ISOLATED enviornment varaible can be used to control this flag. | Boolean | optional | True | +| pip_data_exclude | Additional data exclusion parameters to add to the pip packages BUILD file. | List of strings | optional | [] | +| python_interpreter | The python interpreter to use. This can either be an absolute path or the name of a binary found on the host's PATH environment variable. If no value is set python3 is defaulted for Unix systems and python.exe for Windows. | String | optional | "" | +| python_interpreter_target | If you are using a custom python interpreter built by another repository rule, use this attribute to specify its BUILD target. This allows pip_repository to invoke pip using the same interpreter as your toolchain. If set, takes precedence over python_interpreter. | Label | optional | None | +| quiet | If True, suppress printing stdout and stderr output to the terminal. | Boolean | optional | True | +| repo | Pointer to parent repo name. Used to make these rules rerun if the parent repo changes. | String | required | | +| repo_mapping | A dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.<p>For example, an entry "@foo": "@bar" declares that, for any time this repository depends on @foo (such as a dependency on @foo//some:target, it should actually resolve that dependency within globally-declared @bar (@bar//some:target). | Dictionary: String -> String | required | | +| repo_prefix | Prefix for the generated packages will be of the form

@<prefix><sanitized-package-name>//... | String | optional | "" | +| requirement | Python requirement string describing the package to make available | String | required | | +| timeout | Timeout (in seconds) on the rule's execution duration. | Integer | optional | 600 | + + + ## locked_requirements_label @@ -126,12 +130,16 @@ Get the preferred label for a locked requirements file based on platform. | Name | Description | Default Value | -| :-------------: | :-------------: | :-------------: | -| ctx | repository or module context | none | -| attr | attributes for the repo rule or tag extension | none | +| :------------- | :------------- | :------------- | +| ctx | repository or module context | none | +| attr | attributes for the repo rule or tag extension | none | + +**RETURNS** + +Label - + ## package_annotation @@ -149,16 +157,20 @@ Annotations to apply to the BUILD file content from package generated from a `pi | Name | Description | Default Value | -| :-------------: | :-------------: | :-------------: | -| additive_build_content | Raw text to add to the generated BUILD file of a package. | None | -| copy_files | A mapping of src and out files for [@bazel_skylib//rules:copy_file.bzl][cf] | {} | -| copy_executables | A mapping of src and out files for [@bazel_skylib//rules:copy_file.bzl][cf]. Targets generated here will also be flagged as executable. | {} | -| data | A list of labels to add as data dependencies to the generated py_library target. | [] | -| data_exclude_glob | A list of exclude glob patterns to add as data to the generated py_library target. | [] | -| srcs_exclude_glob | A list of labels to add as srcs to the generated py_library target. | [] | +| :------------- | :------------- | :------------- | +| additive_build_content | Raw text to add to the generated BUILD file of a package. | None | +| copy_files | A mapping of src and out files for [@bazel_skylib//rules:copy_file.bzl][cf] | {} | +| copy_executables | A mapping of src and out files for [@bazel_skylib//rules:copy_file.bzl][cf]. Targets generated here will also be flagged as executable. | {} | +| data | A list of labels to add as data dependencies to the generated py_library target. | [] | +| data_exclude_glob | A list of exclude glob patterns to add as data to the generated py_library target. | [] | +| srcs_exclude_glob | A list of labels to add as srcs to the generated py_library target. | [] | +**RETURNS** - +str: A json encoded string of the provided content. + + + ## use_isolated @@ -172,8 +184,12 @@ Determine whether or not to pass the pip `--isolated` flag to the pip invocation | Name | Description | Default Value | -| :-------------: | :-------------: | :-------------: | -| ctx | repository or module context | none | -| attr | attributes for the repo rule or tag extension | none | +| :------------- | :------------- | :------------- | +| ctx | repository or module context | none | +| attr | attributes for the repo rule or tag extension | none | + +**RETURNS** + +True if --isolated should be passed diff --git a/docs/python.md b/docs/python.md index bd14b8258e..1726ade356 100755 --- a/docs/python.md +++ b/docs/python.md @@ -1,6 +1,10 @@ - + +Core rules for building Python projects. + + + ## current_py_toolchain @@ -19,11 +23,11 @@ current_py_toolchain(name) | Name | Description | Type | Mandatory | Default | -| :-------------: | :-------------: | :-------------: | :-------------: | :-------------: | -| name | A unique name for this target. | Name | required | | +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this target. | Name | required | | - + ## py_import @@ -45,13 +49,13 @@ This rule allows the use of Python packages as dependencies. | Name | Description | Type | Mandatory | Default | -| :-------------: | :-------------: | :-------------: | :-------------: | :-------------: | -| name | A unique name for this target. | Name | required | | -| deps | The list of other libraries to be linked in to the binary target. | List of labels | optional | [] | -| srcs | The list of Python package files provided to Python targets that depend on this target. Note that currently only the .egg format is accepted. For .whl files, try the whl_library rule. We accept contributions to extend py_import to handle .whl. | List of labels | optional | [] | +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this target. | Name | required | | +| deps | The list of other libraries to be linked in to the binary target. | List of labels | optional | [] | +| srcs | The list of Python package files provided to Python targets that depend on this target. Note that currently only the .egg format is accepted. For .whl files, try the whl_library rule. We accept contributions to extend py_import to handle .whl. | List of labels | optional | [] | - + ## py_runtime_pair @@ -74,8 +78,8 @@ schema: ```python platform_common.ToolchainInfo( - py2_runtime = , - py3_runtime = , + py2_runtime = <PyRuntimeInfo or None>, + py3_runtime = <PyRuntimeInfo or None>, ) ``` @@ -106,7 +110,7 @@ py_runtime_pair( toolchain( name = "my_toolchain", - target_compatible_with = <...>, + target_compatible_with = <...>, toolchain = ":my_py_runtime_pair", toolchain_type = "@rules_python//python:toolchain_type", ) @@ -123,13 +127,13 @@ register_toolchains("//my_pkg:my_toolchain") | Name | Description | Type | Mandatory | Default | -| :-------------: | :-------------: | :-------------: | :-------------: | :-------------: | -| name | A unique name for this target. | Name | required | | -| py2_runtime | The runtime to use for Python 2 targets. Must have python_version set to PY2. | Label | optional | None | -| py3_runtime | The runtime to use for Python 3 targets. Must have python_version set to PY3. | Label | optional | None | +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this target. | Name | required | | +| py2_runtime | The runtime to use for Python 2 targets. Must have python_version set to PY2. | Label | optional | None | +| py3_runtime | The runtime to use for Python 3 targets. Must have python_version set to PY3. | Label | optional | None | - + ## py_binary @@ -143,11 +147,11 @@ See the Bazel core [py_binary](https://docs.bazel.build/versions/master/be/pytho | Name | Description | Default Value | -| :-------------: | :-------------: | :-------------: | -| attrs | Rule attributes | none | +| :------------- | :------------- | :------------- | +| attrs | Rule attributes | none | - + ## py_library @@ -161,11 +165,11 @@ See the Bazel core [py_library](https://docs.bazel.build/versions/master/be/pyth | Name | Description | Default Value | -| :-------------: | :-------------: | :-------------: | -| attrs | Rule attributes | none | +| :------------- | :------------- | :------------- | +| attrs | Rule attributes | none | - + ## py_runtime @@ -179,11 +183,11 @@ See the Bazel core [py_runtime](https://docs.bazel.build/versions/master/be/pyth | Name | Description | Default Value | -| :-------------: | :-------------: | :-------------: | -| attrs | Rule attributes | none | +| :------------- | :------------- | :------------- | +| attrs | Rule attributes | none | - + ## py_test @@ -197,11 +201,11 @@ See the Bazel core [py_test](https://docs.bazel.build/versions/master/be/python. | Name | Description | Default Value | -| :-------------: | :-------------: | :-------------: | -| attrs | Rule attributes | none | +| :------------- | :------------- | :------------- | +| attrs | Rule attributes | none | - + ## find_requirements @@ -218,7 +222,7 @@ The aspect definition. Can be invoked on the command line as | Name | Type | -| :-------------: | :-------------: | +| :------------- | :------------- | | deps| String | @@ -226,7 +230,7 @@ The aspect definition. Can be invoked on the command line as | Name | Description | Type | Mandatory | Default | -| :-------------: | :-------------: | :-------------: | :-------------: | :-------------: | -| name | A unique name for this target. | Name | required | | +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this target. | Name | required | | diff --git a/internal_deps.bzl b/internal_deps.bzl index 8a089f053e..a41d5fb34b 100644 --- a/internal_deps.bzl +++ b/internal_deps.bzl @@ -29,9 +29,9 @@ def rules_python_internal_deps(): maybe( http_archive, name = "io_bazel_stardoc", - url = "https://github.com/bazelbuild/stardoc/archive/0.4.0.tar.gz", - sha256 = "6d07d18c15abb0f6d393adbd6075cd661a2219faab56a9517741f0fc755f6f3c", - strip_prefix = "stardoc-0.4.0", + url = "https://github.com/bazelbuild/stardoc/archive/6f274e903009158504a9d9130d7f7d5f3e9421ed.tar.gz", + sha256 = "b5d6891f869d5b5a224316ec4dd9e9d481885a9b1a1c81eb846e20180156f2fa", + strip_prefix = "stardoc-6f274e903009158504a9d9130d7f7d5f3e9421ed", ) maybe( From e093bc1f5cea3ff5e607a191093701d0bbc2ac5c Mon Sep 17 00:00:00 2001 From: Derek Cormier Date: Mon, 21 Nov 2022 02:54:47 -0800 Subject: [PATCH 069/234] fix: correct bcr metadata template filename (#892) --- .bcr/{template.metadata.json => metadata.template.json} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .bcr/{template.metadata.json => metadata.template.json} (100%) diff --git a/.bcr/template.metadata.json b/.bcr/metadata.template.json similarity index 100% rename from .bcr/template.metadata.json rename to .bcr/metadata.template.json From 00545742ad2450863aeb82353d4275a1e5ed3f24 Mon Sep 17 00:00:00 2001 From: Derek Cormier Date: Mon, 21 Nov 2022 13:19:37 -0800 Subject: [PATCH 070/234] fix: fix a bug where some transitive deps could not be resolved via bzlmod --- examples/bzlmod/BUILD.bazel | 2 + examples/bzlmod/MODULE.bazel | 1 + examples/bzlmod/requirements.in | 1 + examples/bzlmod/requirements_lock.txt | 125 +++++++++++++ examples/bzlmod/requirements_windows.txt | 223 +++++++++++++++++++++++ python/extensions.bzl | 6 +- 6 files changed, 357 insertions(+), 1 deletion(-) create mode 100644 examples/bzlmod/requirements_windows.txt diff --git a/examples/bzlmod/BUILD.bazel b/examples/bzlmod/BUILD.bazel index 5693fa658f..a00c96dbaf 100644 --- a/examples/bzlmod/BUILD.bazel +++ b/examples/bzlmod/BUILD.bazel @@ -7,12 +7,14 @@ compile_pip_requirements( extra_args = ["--allow-unsafe"], requirements_in = "requirements.in", requirements_txt = "requirements_lock.txt", + requirements_windows = "requirements_windows.txt", ) py_library( name = "lib", srcs = ["__init__.py"], deps = [ + requirement("pylint"), requirement("tabulate"), ], ) diff --git a/examples/bzlmod/MODULE.bazel b/examples/bzlmod/MODULE.bazel index 275be3bf1f..14a338cc52 100644 --- a/examples/bzlmod/MODULE.bazel +++ b/examples/bzlmod/MODULE.bazel @@ -29,6 +29,7 @@ pip = use_extension("@rules_python//python:extensions.bzl", "pip") pip.parse( name = "pip", requirements_lock = "//:requirements_lock.txt", + requirements_windows = "//:requirements_windows.txt", ) use_repo(pip, "pip") diff --git a/examples/bzlmod/requirements.in b/examples/bzlmod/requirements.in index ea285b036d..b9c0a5b49e 100644 --- a/examples/bzlmod/requirements.in +++ b/examples/bzlmod/requirements.in @@ -2,3 +2,4 @@ requests~=2.25.1 s3cmd~=2.1.0 yamllint~=1.26.3 tabulate~=0.9.0 +pylint~=2.15.5 diff --git a/examples/bzlmod/requirements_lock.txt b/examples/bzlmod/requirements_lock.txt index 8da8e6a8e1..8f22f999b7 100644 --- a/examples/bzlmod/requirements_lock.txt +++ b/examples/bzlmod/requirements_lock.txt @@ -4,6 +4,10 @@ # # bazel run //:requirements.update # +astroid==2.12.13 \ + --hash=sha256:10e0ad5f7b79c435179d0d0f0df69998c4eef4597534aae44910db060baeb907 \ + --hash=sha256:1493fe8bd3dfd73dc35bd53c9d5b6e49ead98497c47b2307662556a5692d29d7 + # via pylint certifi==2021.10.8 \ --hash=sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872 \ --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569 @@ -12,14 +16,55 @@ chardet==4.0.0 \ --hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa \ --hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5 # via requests +dill==0.3.6 \ + --hash=sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0 \ + --hash=sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373 + # via pylint idna==2.10 \ --hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 \ --hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0 # via requests +isort==5.10.1 \ + --hash=sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7 \ + --hash=sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951 + # via pylint +lazy-object-proxy==1.8.0 \ + --hash=sha256:0c1c7c0433154bb7c54185714c6929acc0ba04ee1b167314a779b9025517eada \ + --hash=sha256:14010b49a2f56ec4943b6cf925f597b534ee2fe1f0738c84b3bce0c1a11ff10d \ + --hash=sha256:4e2d9f764f1befd8bdc97673261b8bb888764dfdbd7a4d8f55e4fbcabb8c3fb7 \ + --hash=sha256:4fd031589121ad46e293629b39604031d354043bb5cdf83da4e93c2d7f3389fe \ + --hash=sha256:5b51d6f3bfeb289dfd4e95de2ecd464cd51982fe6f00e2be1d0bf94864d58acd \ + --hash=sha256:6850e4aeca6d0df35bb06e05c8b934ff7c533734eb51d0ceb2d63696f1e6030c \ + --hash=sha256:6f593f26c470a379cf7f5bc6db6b5f1722353e7bf937b8d0d0b3fba911998858 \ + --hash=sha256:71d9ae8a82203511a6f60ca5a1b9f8ad201cac0fc75038b2dc5fa519589c9288 \ + --hash=sha256:7e1561626c49cb394268edd00501b289053a652ed762c58e1081224c8d881cec \ + --hash=sha256:8f6ce2118a90efa7f62dd38c7dbfffd42f468b180287b748626293bf12ed468f \ + --hash=sha256:ae032743794fba4d171b5b67310d69176287b5bf82a21f588282406a79498891 \ + --hash=sha256:afcaa24e48bb23b3be31e329deb3f1858f1f1df86aea3d70cb5c8578bfe5261c \ + --hash=sha256:b70d6e7a332eb0217e7872a73926ad4fdc14f846e85ad6749ad111084e76df25 \ + --hash=sha256:c219a00245af0f6fa4e95901ed28044544f50152840c5b6a3e7b2568db34d156 \ + --hash=sha256:ce58b2b3734c73e68f0e30e4e725264d4d6be95818ec0a0be4bb6bf9a7e79aa8 \ + --hash=sha256:d176f392dbbdaacccf15919c77f526edf11a34aece58b55ab58539807b85436f \ + --hash=sha256:e20bfa6db17a39c706d24f82df8352488d2943a3b7ce7d4c22579cb89ca8896e \ + --hash=sha256:eac3a9a5ef13b332c059772fd40b4b1c3d45a3a2b05e33a361dee48e54a4dad0 \ + --hash=sha256:eb329f8d8145379bf5dbe722182410fe8863d186e51bf034d2075eb8d85ee25b + # via astroid +mccabe==0.7.0 \ + --hash=sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325 \ + --hash=sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e + # via pylint pathspec==0.9.0 \ --hash=sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a \ --hash=sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1 # via yamllint +platformdirs==2.5.4 \ + --hash=sha256:1006647646d80f16130f052404c6b901e80ee4ed6bef6792e1f238a8969106f7 \ + --hash=sha256:af0276409f9a02373d540bf8480021a048711d572745aef4b7842dad245eba10 + # via pylint +pylint==2.15.6 \ + --hash=sha256:15060cc22ed6830a4049cf40bc24977744df2e554d38da1b2657591de5bcd052 \ + --hash=sha256:25b13ddcf5af7d112cf96935e21806c1da60e676f952efb650130f2a4483421c + # via -r ./requirements.in python-dateutil==2.8.2 \ --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 @@ -79,10 +124,90 @@ tabulate==0.9.0 \ --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \ --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f # via -r ./requirements.in +tomli==2.0.1 \ + --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ + --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f + # via pylint +tomlkit==0.11.6 \ + --hash=sha256:07de26b0d8cfc18f871aec595fda24d95b08fef89d147caa861939f37230bf4b \ + --hash=sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73 + # via pylint +typing-extensions==4.4.0 \ + --hash=sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa \ + --hash=sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e + # via + # astroid + # pylint urllib3==1.26.7 \ --hash=sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece \ --hash=sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844 # via requests +wrapt==1.14.1 \ + --hash=sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3 \ + --hash=sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b \ + --hash=sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4 \ + --hash=sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2 \ + --hash=sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656 \ + --hash=sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3 \ + --hash=sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff \ + --hash=sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310 \ + --hash=sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a \ + --hash=sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57 \ + --hash=sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069 \ + --hash=sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383 \ + --hash=sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe \ + --hash=sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87 \ + --hash=sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d \ + --hash=sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b \ + --hash=sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907 \ + --hash=sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f \ + --hash=sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0 \ + --hash=sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28 \ + --hash=sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1 \ + --hash=sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853 \ + --hash=sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc \ + --hash=sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3 \ + --hash=sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3 \ + --hash=sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164 \ + --hash=sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1 \ + --hash=sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c \ + --hash=sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1 \ + --hash=sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7 \ + --hash=sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1 \ + --hash=sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320 \ + --hash=sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed \ + --hash=sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1 \ + --hash=sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248 \ + --hash=sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c \ + --hash=sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456 \ + --hash=sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77 \ + --hash=sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef \ + --hash=sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1 \ + --hash=sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7 \ + --hash=sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86 \ + --hash=sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4 \ + --hash=sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d \ + --hash=sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d \ + --hash=sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8 \ + --hash=sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5 \ + --hash=sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471 \ + --hash=sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00 \ + --hash=sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68 \ + --hash=sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3 \ + --hash=sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d \ + --hash=sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735 \ + --hash=sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d \ + --hash=sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569 \ + --hash=sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7 \ + --hash=sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59 \ + --hash=sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5 \ + --hash=sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb \ + --hash=sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b \ + --hash=sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f \ + --hash=sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462 \ + --hash=sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015 \ + --hash=sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af + # via astroid yamllint==1.26.3 \ --hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e # via -r ./requirements.in diff --git a/examples/bzlmod/requirements_windows.txt b/examples/bzlmod/requirements_windows.txt new file mode 100644 index 0000000000..cfd1a8d049 --- /dev/null +++ b/examples/bzlmod/requirements_windows.txt @@ -0,0 +1,223 @@ +# +# This file is autogenerated by pip-compile with python 3.9 +# To update, run: +# +# bazel run //:requirements.update +# +astroid==2.12.13 \ + --hash=sha256:10e0ad5f7b79c435179d0d0f0df69998c4eef4597534aae44910db060baeb907 \ + --hash=sha256:1493fe8bd3dfd73dc35bd53c9d5b6e49ead98497c47b2307662556a5692d29d7 + # via pylint +certifi==2021.10.8 \ + --hash=sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872 \ + --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569 + # via requests +chardet==4.0.0 \ + --hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa \ + --hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5 + # via requests +colorama==0.4.6 \ + --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ + --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 + # via pylint +dill==0.3.6 \ + --hash=sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0 \ + --hash=sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373 + # via pylint +idna==2.10 \ + --hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 \ + --hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0 + # via requests +isort==5.10.1 \ + --hash=sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7 \ + --hash=sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951 + # via pylint +lazy-object-proxy==1.8.0 \ + --hash=sha256:0c1c7c0433154bb7c54185714c6929acc0ba04ee1b167314a779b9025517eada \ + --hash=sha256:14010b49a2f56ec4943b6cf925f597b534ee2fe1f0738c84b3bce0c1a11ff10d \ + --hash=sha256:4e2d9f764f1befd8bdc97673261b8bb888764dfdbd7a4d8f55e4fbcabb8c3fb7 \ + --hash=sha256:4fd031589121ad46e293629b39604031d354043bb5cdf83da4e93c2d7f3389fe \ + --hash=sha256:5b51d6f3bfeb289dfd4e95de2ecd464cd51982fe6f00e2be1d0bf94864d58acd \ + --hash=sha256:6850e4aeca6d0df35bb06e05c8b934ff7c533734eb51d0ceb2d63696f1e6030c \ + --hash=sha256:6f593f26c470a379cf7f5bc6db6b5f1722353e7bf937b8d0d0b3fba911998858 \ + --hash=sha256:71d9ae8a82203511a6f60ca5a1b9f8ad201cac0fc75038b2dc5fa519589c9288 \ + --hash=sha256:7e1561626c49cb394268edd00501b289053a652ed762c58e1081224c8d881cec \ + --hash=sha256:8f6ce2118a90efa7f62dd38c7dbfffd42f468b180287b748626293bf12ed468f \ + --hash=sha256:ae032743794fba4d171b5b67310d69176287b5bf82a21f588282406a79498891 \ + --hash=sha256:afcaa24e48bb23b3be31e329deb3f1858f1f1df86aea3d70cb5c8578bfe5261c \ + --hash=sha256:b70d6e7a332eb0217e7872a73926ad4fdc14f846e85ad6749ad111084e76df25 \ + --hash=sha256:c219a00245af0f6fa4e95901ed28044544f50152840c5b6a3e7b2568db34d156 \ + --hash=sha256:ce58b2b3734c73e68f0e30e4e725264d4d6be95818ec0a0be4bb6bf9a7e79aa8 \ + --hash=sha256:d176f392dbbdaacccf15919c77f526edf11a34aece58b55ab58539807b85436f \ + --hash=sha256:e20bfa6db17a39c706d24f82df8352488d2943a3b7ce7d4c22579cb89ca8896e \ + --hash=sha256:eac3a9a5ef13b332c059772fd40b4b1c3d45a3a2b05e33a361dee48e54a4dad0 \ + --hash=sha256:eb329f8d8145379bf5dbe722182410fe8863d186e51bf034d2075eb8d85ee25b + # via astroid +mccabe==0.7.0 \ + --hash=sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325 \ + --hash=sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e + # via pylint +pathspec==0.9.0 \ + --hash=sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a \ + --hash=sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1 + # via yamllint +platformdirs==2.5.4 \ + --hash=sha256:1006647646d80f16130f052404c6b901e80ee4ed6bef6792e1f238a8969106f7 \ + --hash=sha256:af0276409f9a02373d540bf8480021a048711d572745aef4b7842dad245eba10 + # via pylint +pylint==2.15.6 \ + --hash=sha256:15060cc22ed6830a4049cf40bc24977744df2e554d38da1b2657591de5bcd052 \ + --hash=sha256:25b13ddcf5af7d112cf96935e21806c1da60e676f952efb650130f2a4483421c + # via -r ./requirements.in +python-dateutil==2.8.2 \ + --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ + --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 + # via s3cmd +python-magic==0.4.24 \ + --hash=sha256:4fec8ee805fea30c07afccd1592c0f17977089895bdfaae5fec870a84e997626 \ + --hash=sha256:de800df9fb50f8ec5974761054a708af6e4246b03b4bdaee993f948947b0ebcf + # via s3cmd +pyyaml==6.0 \ + --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ + --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ + --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ + --hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b \ + --hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 \ + --hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 \ + --hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba \ + --hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 \ + --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ + --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ + --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ + --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ + --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ + --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ + --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ + --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ + --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ + --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ + --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ + --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ + --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ + --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ + --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ + --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ + --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ + --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ + --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ + --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ + --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ + --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ + --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ + --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ + --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 + # via yamllint +requests==2.25.1 \ + --hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \ + --hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e + # via -r ./requirements.in +s3cmd==2.1.0 \ + --hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \ + --hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03 + # via -r ./requirements.in +six==1.16.0 \ + --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ + --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 + # via python-dateutil +tabulate==0.9.0 \ + --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \ + --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f + # via -r ./requirements.in +tomli==2.0.1 \ + --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ + --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f + # via pylint +tomlkit==0.11.6 \ + --hash=sha256:07de26b0d8cfc18f871aec595fda24d95b08fef89d147caa861939f37230bf4b \ + --hash=sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73 + # via pylint +typing-extensions==4.4.0 \ + --hash=sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa \ + --hash=sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e + # via + # astroid + # pylint +urllib3==1.26.7 \ + --hash=sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece \ + --hash=sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844 + # via requests +wrapt==1.14.1 \ + --hash=sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3 \ + --hash=sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b \ + --hash=sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4 \ + --hash=sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2 \ + --hash=sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656 \ + --hash=sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3 \ + --hash=sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff \ + --hash=sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310 \ + --hash=sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a \ + --hash=sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57 \ + --hash=sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069 \ + --hash=sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383 \ + --hash=sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe \ + --hash=sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87 \ + --hash=sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d \ + --hash=sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b \ + --hash=sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907 \ + --hash=sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f \ + --hash=sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0 \ + --hash=sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28 \ + --hash=sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1 \ + --hash=sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853 \ + --hash=sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc \ + --hash=sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3 \ + --hash=sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3 \ + --hash=sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164 \ + --hash=sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1 \ + --hash=sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c \ + --hash=sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1 \ + --hash=sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7 \ + --hash=sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1 \ + --hash=sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320 \ + --hash=sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed \ + --hash=sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1 \ + --hash=sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248 \ + --hash=sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c \ + --hash=sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456 \ + --hash=sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77 \ + --hash=sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef \ + --hash=sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1 \ + --hash=sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7 \ + --hash=sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86 \ + --hash=sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4 \ + --hash=sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d \ + --hash=sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d \ + --hash=sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8 \ + --hash=sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5 \ + --hash=sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471 \ + --hash=sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00 \ + --hash=sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68 \ + --hash=sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3 \ + --hash=sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d \ + --hash=sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735 \ + --hash=sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d \ + --hash=sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569 \ + --hash=sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7 \ + --hash=sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59 \ + --hash=sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5 \ + --hash=sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb \ + --hash=sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b \ + --hash=sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f \ + --hash=sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462 \ + --hash=sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015 \ + --hash=sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af + # via astroid +yamllint==1.26.3 \ + --hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e + # via -r ./requirements.in + +# The following packages are considered to be unsafe in a requirements file: +setuptools==59.6.0 \ + --hash=sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373 \ + --hash=sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e + # via yamllint diff --git a/python/extensions.bzl b/python/extensions.bzl index 505ff20d13..4699cdd84a 100644 --- a/python/extensions.bzl +++ b/python/extensions.bzl @@ -61,7 +61,7 @@ def _pip_impl(module_ctx): for name, requirement_line in requirements: whl_library( - name = "%s_%s" % (attr.name, name), + name = "%s_%s" % (attr.name, _sanitize_name(name)), requirement = requirement_line, repo = attr.name, repo_prefix = attr.name + "_", @@ -78,6 +78,10 @@ def _pip_impl(module_ctx): environment = attr.environment, ) +# Keep in sync with python/pip_install/extract_wheels/bazel.py +def _sanitize_name(name): + return name.replace("-", "_").replace(".", "_").lower() + def _pip_parse_ext_attrs(): attrs = dict({ "name": attr.string(mandatory = True), From 17a1573ecb960f0ed839fc8581cb015737b6241d Mon Sep 17 00:00:00 2001 From: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Date: Mon, 28 Nov 2022 13:58:21 -0800 Subject: [PATCH 071/234] feat: multi-toolchain support (#846) * feat: multi-toolchain support This adds support for multiple Python versions on the same Bazel workspace. Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * feat: cross-version testing A py_test using 3.10 runs a py_binary using 3.9. Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: error message Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * doc: add link to bazelbuild/bazel PR fixing expand_location Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: set environment variables for py_binary too Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * test: extra case for default version taking another version Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: fail if args attribute is set Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: remove confusing output with same target name Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: buildifier Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * revert: use testing.TestEnvironment See comment in code for the reasons. Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: linting issues Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: black linter Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * refactor: move tests to a sub-dir Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * feat: add multi_pip_parse Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: add missing aliases Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: use requirement function in example Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: deleted packages Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: update generated docs Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * refactor: version checking of the rule is already done by other tests Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: add python_interpreter_target to multi_pip_parse Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: windows Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * refactor: unify py_test and py_binary transition impls Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: test compatible with all platforms Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * rebase: adjust multi_python_versions on ci Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * refactor: use usr flags instead of platforms in transition Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * refactor: rename rule -> rule_impl This avoids confusion with the global `rule` https://bazel.build/rules/lib/globals#rule. Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * refactor: reduce repetition of args Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: missing test and binary-specific attributes Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: add srcs and deps attrs for path expansion Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: missing bazel_skylib on integration tests Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * refactor: use ctx.target_platform_has_constraint over select Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * doc: why symlink .zip under Windows Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: apply suggestions from code review Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: use incoming edge transitions Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: use RunEnvironmentInfo when available Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: cfg should be target not exec Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- .bazelci/presubmit.yml | 16 ++ .bazelrc | 4 +- WORKSPACE | 8 +- docs/pip.md | 77 ++++++- examples/BUILD | 5 + examples/multi_python_versions/.bazelrc | 5 + examples/multi_python_versions/.gitignore | 1 + examples/multi_python_versions/WORKSPACE | 59 +++++ .../libs/my_lib/BUILD.bazel | 9 + .../libs/my_lib/__init__.py | 5 + .../requirements/BUILD.bazel | 24 ++ .../requirements/requirements.in | 1 + .../requirements/requirements_lock_3_10.txt | 56 +++++ .../requirements/requirements_lock_3_8.txt | 56 +++++ .../requirements/requirements_lock_3_9.txt | 56 +++++ .../multi_python_versions/tests/BUILD.bazel | 148 +++++++++++++ .../tests/cross_version_test.py | 25 +++ .../tests/my_lib_test.py | 10 + .../multi_python_versions/tests/version.py | 3 + .../tests/version_test.py | 9 + .../tests/version_test.sh | 10 + examples/pip_parse/WORKSPACE | 11 + python/BUILD | 3 +- python/config_settings/BUILD.bazel | 12 + python/config_settings/config_settings.bzl | 26 +++ python/config_settings/transition.bzl | 208 ++++++++++++++++++ python/pip.bzl | 198 +++++++++++++++++ python/pip_install/requirements.bzl | 24 +- python/private/toolchains_repo.bzl | 149 +++++++++++-- python/repositories.bzl | 73 +++++- tests/pip_repository_entry_points/WORKSPACE | 11 + 31 files changed, 1251 insertions(+), 51 deletions(-) create mode 100644 examples/multi_python_versions/.bazelrc create mode 100644 examples/multi_python_versions/.gitignore create mode 100644 examples/multi_python_versions/WORKSPACE create mode 100644 examples/multi_python_versions/libs/my_lib/BUILD.bazel create mode 100644 examples/multi_python_versions/libs/my_lib/__init__.py create mode 100644 examples/multi_python_versions/requirements/BUILD.bazel create mode 100644 examples/multi_python_versions/requirements/requirements.in create mode 100644 examples/multi_python_versions/requirements/requirements_lock_3_10.txt create mode 100644 examples/multi_python_versions/requirements/requirements_lock_3_8.txt create mode 100644 examples/multi_python_versions/requirements/requirements_lock_3_9.txt create mode 100644 examples/multi_python_versions/tests/BUILD.bazel create mode 100644 examples/multi_python_versions/tests/cross_version_test.py create mode 100644 examples/multi_python_versions/tests/my_lib_test.py create mode 100644 examples/multi_python_versions/tests/version.py create mode 100644 examples/multi_python_versions/tests/version_test.py create mode 100755 examples/multi_python_versions/tests/version_test.sh create mode 100644 python/config_settings/BUILD.bazel create mode 100644 python/config_settings/config_settings.bzl create mode 100644 python/config_settings/transition.bzl diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index d7ca8ef05b..56516e975b 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -85,6 +85,22 @@ tasks: working_directory: examples/bzlmod platform: windows + integration_test_multi_python_versions_linux: + <<: *reusable_build_test_all + name: multi_python_versions integration tests on Linux + working_directory: examples/multi_python_versions + platform: ubuntu2004 + integration_test_multi_python_versions_macos: + <<: *reusable_build_test_all + name: multi_python_versions integration tests on macOS + working_directory: examples/multi_python_versions + platform: macos + integration_test_multi_python_versions_windows: + <<: *reusable_build_test_all + name: multi_python_versions integration tests on Windows + working_directory: examples/multi_python_versions + platform: windows + integration_test_pip_install_linux: <<: *reusable_build_test_all name: pip_install integration tests on Linux diff --git a/.bazelrc b/.bazelrc index a4bcccfd67..510191b847 100644 --- a/.bazelrc +++ b/.bazelrc @@ -3,8 +3,8 @@ # This lets us glob() up all the files inside the examples to make them inputs to tests # (Note, we cannot use `common --deleted_packages` because the bazel version command doesn't support it) # To update these lines, run tools/bazel_integration_test/update_deleted_packages.sh -build --deleted_packages=examples/build_file_generation,examples/bzlmod,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/relative_requirements,tests/pip_repository_entry_points,tests/pip_deps -query --deleted_packages=examples/build_file_generation,examples/bzlmod,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/relative_requirements,tests/pip_repository_entry_points,tests/pip_deps +build --deleted_packages=examples/build_file_generation,examples/bzlmod,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/relative_requirements,tests/pip_repository_entry_points,tests/pip_deps +query --deleted_packages=examples/build_file_generation,examples/bzlmod,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/relative_requirements,tests/pip_repository_entry_points,tests/pip_deps test --test_output=errors diff --git a/WORKSPACE b/WORKSPACE index ff1b956534..1d9d5e4e48 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -25,13 +25,13 @@ load("//:internal_setup.bzl", "rules_python_internal_setup") rules_python_internal_setup() -load("//python:repositories.bzl", "python_register_toolchains") +load("//python:repositories.bzl", "python_register_multi_toolchains") load("//python:versions.bzl", "MINOR_MAPPING") -python_register_toolchains( +python_register_multi_toolchains( name = "python", - # We always use the latest Python internally. - python_version = MINOR_MAPPING.values()[-1], + default_version = MINOR_MAPPING.values()[-1], + python_versions = MINOR_MAPPING.values(), ) load("//gazelle:deps.bzl", "gazelle_deps") diff --git a/docs/pip.md b/docs/pip.md index fc38f0fea3..5f6c1d8565 100644 --- a/docs/pip.md +++ b/docs/pip.md @@ -2,13 +2,36 @@ Import pip requirements into Bazel. + + +## whl_library_alias + +
+whl_library_alias(name, default_version, repo_mapping, version_map, wheel_name)
+
+ + + +**ATTRIBUTES** + + +| Name | Description | Type | Mandatory | Default | +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this repository. | Name | required | | +| default_version | - | String | required | | +| repo_mapping | A dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.<p>For example, an entry "@foo": "@bar" declares that, for any time this repository depends on @foo (such as a dependency on @foo//some:target, it should actually resolve that dependency within globally-declared @bar (@bar//some:target). | Dictionary: String -> String | required | | +| version_map | - | Dictionary: String -> String | required | | +| wheel_name | - | String | required | | + + ## compile_pip_requirements
-compile_pip_requirements(name, extra_args, visibility, requirements_in, requirements_txt,
-                         requirements_linux, requirements_darwin, requirements_windows, tags, kwargs)
+compile_pip_requirements(name, extra_args, py_binary, py_test, requirements_in, requirements_txt,
+                         requirements_darwin, requirements_linux, requirements_windows, visibility,
+                         tags, kwargs)
 
Generates targets for managing pip dependencies with pip-compile. @@ -28,16 +51,50 @@ It also generates two targets for running pip-compile: | Name | Description | Default Value | | :------------- | :------------- | :------------- | -| name | base name for generated targets, typically "requirements" | none | -| extra_args | passed to pip-compile | [] | -| visibility | passed to both the _test and .update rules | ["//visibility:private"] | -| requirements_in | file expressing desired dependencies | None | -| requirements_txt | result of "compiling" the requirements.in file | None | -| requirements_linux | File of linux specific resolve output to check validate if requirement.in has changes. | None | +| name | base name for generated targets, typically "requirements". | none | +| extra_args | passed to pip-compile. | [] | +| py_binary | the py_binary rule to be used. | <function py_binary> | +| py_test | the py_test rule to be used. | <function py_test> | +| requirements_in | file expressing desired dependencies. | None | +| requirements_txt | result of "compiling" the requirements.in file. | None | | requirements_darwin | File of darwin specific resolve output to check validate if requirement.in has changes. | None | +| requirements_linux | File of linux specific resolve output to check validate if requirement.in has changes. | None | | requirements_windows | File of windows specific resolve output to check validate if requirement.in has changes. | None | -| tags | tagging attribute common to all build rules, passed to both the _test and .update rules | None | -| kwargs | other bazel attributes passed to the "_test" rule | none | +| visibility | passed to both the _test and .update rules. | ["//visibility:private"] | +| tags | tagging attribute common to all build rules, passed to both the _test and .update rules. | None | +| kwargs | other bazel attributes passed to the "_test" rule. | none | + + + + +## multi_pip_parse + +
+multi_pip_parse(name, default_version, python_versions, python_interpreter_target,
+                requirements_lock, kwargs)
+
+ +NOT INTENDED FOR DIRECT USE! + +This is intended to be used by the multi_pip_parse implementation in the template of the +multi_toolchain_aliases repository rule. + + +**PARAMETERS** + + +| Name | Description | Default Value | +| :------------- | :------------- | :------------- | +| name | the name of the multi_pip_parse repository. | none | +| default_version | the default Python version. | none | +| python_versions | all Python toolchain versions currently registered. | none | +| python_interpreter_target | a dictionary which keys are Python versions and values are resolved host interpreters. | none | +| requirements_lock | a dictionary which keys are Python versions and values are locked requirements files. | none | +| kwargs | extra arguments passed to all wrapped pip_parse. | none | + +**RETURNS** + +The internal implementation of multi_pip_parse repository rule. diff --git a/examples/BUILD b/examples/BUILD index fcdbdb1a28..39e4fce63e 100644 --- a/examples/BUILD +++ b/examples/BUILD @@ -38,6 +38,11 @@ bazel_integration_test( timeout = "long", ) +bazel_integration_test( + name = "multi_python_versions_example", + timeout = "long", +) + bazel_integration_test( name = "bzlmod_example", bzlmod = True, diff --git a/examples/multi_python_versions/.bazelrc b/examples/multi_python_versions/.bazelrc new file mode 100644 index 0000000000..f23315a7a1 --- /dev/null +++ b/examples/multi_python_versions/.bazelrc @@ -0,0 +1,5 @@ +test --test_output=errors + +# Windows requires these for multi-python support: +build --enable_runfiles +startup --windows_enable_symlinks diff --git a/examples/multi_python_versions/.gitignore b/examples/multi_python_versions/.gitignore new file mode 100644 index 0000000000..ac51a054d2 --- /dev/null +++ b/examples/multi_python_versions/.gitignore @@ -0,0 +1 @@ +bazel-* diff --git a/examples/multi_python_versions/WORKSPACE b/examples/multi_python_versions/WORKSPACE new file mode 100644 index 0000000000..9a6676ea25 --- /dev/null +++ b/examples/multi_python_versions/WORKSPACE @@ -0,0 +1,59 @@ +workspace(name = "rules_python_multi_python_versions") + +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +http_archive( + name = "bazel_skylib", + sha256 = "c6966ec828da198c5d9adbaa94c05e3a1c7f21bd012a0b29ba8ddbccb2c93b0d", + urls = [ + "https://github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", + "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", + ], +) + +local_repository( + name = "rules_python", + path = "../..", +) + +load("@rules_python//python/pip_install:repositories.bzl", "pip_install_dependencies") + +pip_install_dependencies() + +load("@rules_python//python:repositories.bzl", "python_register_multi_toolchains") + +default_python_version = "3.9" + +python_register_multi_toolchains( + name = "python", + default_version = default_python_version, + python_versions = [ + "3.8", + "3.9", + "3.10", + ], +) + +load("@python//:pip.bzl", "multi_pip_parse") +load("@python//3.10:defs.bzl", interpreter_3_10 = "interpreter") +load("@python//3.8:defs.bzl", interpreter_3_8 = "interpreter") +load("@python//3.9:defs.bzl", interpreter_3_9 = "interpreter") + +multi_pip_parse( + name = "pypi", + default_version = default_python_version, + python_interpreter_target = { + "3.10": interpreter_3_10, + "3.8": interpreter_3_8, + "3.9": interpreter_3_9, + }, + requirements_lock = { + "3.10": "//requirements:requirements_lock_3_10.txt", + "3.8": "//requirements:requirements_lock_3_8.txt", + "3.9": "//requirements:requirements_lock_3_9.txt", + }, +) + +load("@pypi//:requirements.bzl", "install_deps") + +install_deps() diff --git a/examples/multi_python_versions/libs/my_lib/BUILD.bazel b/examples/multi_python_versions/libs/my_lib/BUILD.bazel new file mode 100644 index 0000000000..8c29f6083c --- /dev/null +++ b/examples/multi_python_versions/libs/my_lib/BUILD.bazel @@ -0,0 +1,9 @@ +load("@pypi//:requirements.bzl", "requirement") +load("@rules_python//python:defs.bzl", "py_library") + +py_library( + name = "my_lib", + srcs = ["__init__.py"], + visibility = ["@//tests:__pkg__"], + deps = [requirement("websockets")], +) diff --git a/examples/multi_python_versions/libs/my_lib/__init__.py b/examples/multi_python_versions/libs/my_lib/__init__.py new file mode 100644 index 0000000000..3f02b96905 --- /dev/null +++ b/examples/multi_python_versions/libs/my_lib/__init__.py @@ -0,0 +1,5 @@ +import websockets + + +def websockets_is_for_python_version(sanitized_version_check): + return f"pypi_{sanitized_version_check}_websockets" in websockets.__file__ diff --git a/examples/multi_python_versions/requirements/BUILD.bazel b/examples/multi_python_versions/requirements/BUILD.bazel new file mode 100644 index 0000000000..4848fabe10 --- /dev/null +++ b/examples/multi_python_versions/requirements/BUILD.bazel @@ -0,0 +1,24 @@ +load("@python//3.10:defs.bzl", compile_pip_requirements_3_10 = "compile_pip_requirements") +load("@python//3.8:defs.bzl", compile_pip_requirements_3_8 = "compile_pip_requirements") +load("@python//3.9:defs.bzl", compile_pip_requirements_3_9 = "compile_pip_requirements") + +compile_pip_requirements_3_8( + name = "requirements_3_8", + extra_args = ["--allow-unsafe"], + requirements_in = "requirements.in", + requirements_txt = "requirements_lock_3_8.txt", +) + +compile_pip_requirements_3_9( + name = "requirements_3_9", + extra_args = ["--allow-unsafe"], + requirements_in = "requirements.in", + requirements_txt = "requirements_lock_3_9.txt", +) + +compile_pip_requirements_3_10( + name = "requirements_3_10", + extra_args = ["--allow-unsafe"], + requirements_in = "requirements.in", + requirements_txt = "requirements_lock_3_10.txt", +) diff --git a/examples/multi_python_versions/requirements/requirements.in b/examples/multi_python_versions/requirements/requirements.in new file mode 100644 index 0000000000..14774b465e --- /dev/null +++ b/examples/multi_python_versions/requirements/requirements.in @@ -0,0 +1 @@ +websockets diff --git a/examples/multi_python_versions/requirements/requirements_lock_3_10.txt b/examples/multi_python_versions/requirements/requirements_lock_3_10.txt new file mode 100644 index 0000000000..0e332bfa3e --- /dev/null +++ b/examples/multi_python_versions/requirements/requirements_lock_3_10.txt @@ -0,0 +1,56 @@ +# +# This file is autogenerated by pip-compile with python 3.10 +# To update, run: +# +# bazel run //requirements:requirements_3_10.update +# +websockets==10.3 \ + --hash=sha256:07cdc0a5b2549bcfbadb585ad8471ebdc7bdf91e32e34ae3889001c1c106a6af \ + --hash=sha256:210aad7fdd381c52e58777560860c7e6110b6174488ef1d4b681c08b68bf7f8c \ + --hash=sha256:28dd20b938a57c3124028680dc1600c197294da5db4292c76a0b48efb3ed7f76 \ + --hash=sha256:2f94fa3ae454a63ea3a19f73b95deeebc9f02ba2d5617ca16f0bbdae375cda47 \ + --hash=sha256:31564a67c3e4005f27815634343df688b25705cccb22bc1db621c781ddc64c69 \ + --hash=sha256:347974105bbd4ea068106ec65e8e8ebd86f28c19e529d115d89bd8cc5cda3079 \ + --hash=sha256:379e03422178436af4f3abe0aa8f401aa77ae2487843738542a75faf44a31f0c \ + --hash=sha256:3eda1cb7e9da1b22588cefff09f0951771d6ee9fa8dbe66f5ae04cc5f26b2b55 \ + --hash=sha256:51695d3b199cd03098ae5b42833006a0f43dc5418d3102972addc593a783bc02 \ + --hash=sha256:54c000abeaff6d8771a4e2cef40900919908ea7b6b6a30eae72752607c6db559 \ + --hash=sha256:5b936bf552e4f6357f5727579072ff1e1324717902127ffe60c92d29b67b7be3 \ + --hash=sha256:6075fd24df23133c1b078e08a9b04a3bc40b31a8def4ee0b9f2c8865acce913e \ + --hash=sha256:661f641b44ed315556a2fa630239adfd77bd1b11cb0b9d96ed8ad90b0b1e4978 \ + --hash=sha256:6ea6b300a6bdd782e49922d690e11c3669828fe36fc2471408c58b93b5535a98 \ + --hash=sha256:6ed1d6f791eabfd9808afea1e068f5e59418e55721db8b7f3bfc39dc831c42ae \ + --hash=sha256:7934e055fd5cd9dee60f11d16c8d79c4567315824bacb1246d0208a47eca9755 \ + --hash=sha256:7ab36e17af592eec5747c68ef2722a74c1a4a70f3772bc661079baf4ae30e40d \ + --hash=sha256:7f6d96fdb0975044fdd7953b35d003b03f9e2bcf85f2d2cf86285ece53e9f991 \ + --hash=sha256:83e5ca0d5b743cde3d29fda74ccab37bdd0911f25bd4cdf09ff8b51b7b4f2fa1 \ + --hash=sha256:85506b3328a9e083cc0a0fb3ba27e33c8db78341b3eb12eb72e8afd166c36680 \ + --hash=sha256:8af75085b4bc0b5c40c4a3c0e113fa95e84c60f4ed6786cbb675aeb1ee128247 \ + --hash=sha256:8b1359aba0ff810d5830d5ab8e2c4a02bebf98a60aa0124fb29aa78cfdb8031f \ + --hash=sha256:8fbd7d77f8aba46d43245e86dd91a8970eac4fb74c473f8e30e9c07581f852b2 \ + --hash=sha256:907e8247480f287aa9bbc9391bd6de23c906d48af54c8c421df84655eef66af7 \ + --hash=sha256:93d5ea0b5da8d66d868b32c614d2b52d14304444e39e13a59566d4acb8d6e2e4 \ + --hash=sha256:97bc9d41e69a7521a358f9b8e44871f6cdeb42af31815c17aed36372d4eec667 \ + --hash=sha256:994cdb1942a7a4c2e10098d9162948c9e7b235df755de91ca33f6e0481366fdb \ + --hash=sha256:a141de3d5a92188234afa61653ed0bbd2dde46ad47b15c3042ffb89548e77094 \ + --hash=sha256:a1e15b230c3613e8ea82c9fc6941b2093e8eb939dd794c02754d33980ba81e36 \ + --hash=sha256:aad5e300ab32036eb3fdc350ad30877210e2f51bceaca83fb7fef4d2b6c72b79 \ + --hash=sha256:b529fdfa881b69fe563dbd98acce84f3e5a67df13de415e143ef053ff006d500 \ + --hash=sha256:b9c77f0d1436ea4b4dc089ed8335fa141e6a251a92f75f675056dac4ab47a71e \ + --hash=sha256:bb621ec2dbbbe8df78a27dbd9dd7919f9b7d32a73fafcb4d9252fc4637343582 \ + --hash=sha256:c7250848ce69559756ad0086a37b82c986cd33c2d344ab87fea596c5ac6d9442 \ + --hash=sha256:c8d1d14aa0f600b5be363077b621b1b4d1eb3fbf90af83f9281cda668e6ff7fd \ + --hash=sha256:d1655a6fc7aecd333b079d00fb3c8132d18988e47f19740c69303bf02e9883c6 \ + --hash=sha256:d6353ba89cfc657a3f5beabb3b69be226adbb5c6c7a66398e17809b0ce3c4731 \ + --hash=sha256:da4377904a3379f0c1b75a965fff23b28315bcd516d27f99a803720dfebd94d4 \ + --hash=sha256:e49ea4c1a9543d2bd8a747ff24411509c29e4bdcde05b5b0895e2120cb1a761d \ + --hash=sha256:e4e08305bfd76ba8edab08dcc6496f40674f44eb9d5e23153efa0a35750337e8 \ + --hash=sha256:e6fa05a680e35d0fcc1470cb070b10e6fe247af54768f488ed93542e71339d6f \ + --hash=sha256:e7e6f2d6fd48422071cc8a6f8542016f350b79cc782752de531577d35e9bd677 \ + --hash=sha256:e904c0381c014b914136c492c8fa711ca4cced4e9b3d110e5e7d436d0fc289e8 \ + --hash=sha256:ec2b0ab7edc8cd4b0eb428b38ed89079bdc20c6bdb5f889d353011038caac2f9 \ + --hash=sha256:ef5ce841e102278c1c2e98f043db99d6755b1c58bde475516aef3a008ed7f28e \ + --hash=sha256:f351c7d7d92f67c0609329ab2735eee0426a03022771b00102816a72715bb00b \ + --hash=sha256:fab7c640815812ed5f10fbee7abbf58788d602046b7bb3af9b1ac753a6d5e916 \ + --hash=sha256:fc06cc8073c8e87072138ba1e431300e2d408f054b27047d047b549455066ff4 + # via -r requirements/requirements.in diff --git a/examples/multi_python_versions/requirements/requirements_lock_3_8.txt b/examples/multi_python_versions/requirements/requirements_lock_3_8.txt new file mode 100644 index 0000000000..30419da431 --- /dev/null +++ b/examples/multi_python_versions/requirements/requirements_lock_3_8.txt @@ -0,0 +1,56 @@ +# +# This file is autogenerated by pip-compile with python 3.8 +# To update, run: +# +# bazel run //requirements:requirements_3_8.update +# +websockets==10.3 \ + --hash=sha256:07cdc0a5b2549bcfbadb585ad8471ebdc7bdf91e32e34ae3889001c1c106a6af \ + --hash=sha256:210aad7fdd381c52e58777560860c7e6110b6174488ef1d4b681c08b68bf7f8c \ + --hash=sha256:28dd20b938a57c3124028680dc1600c197294da5db4292c76a0b48efb3ed7f76 \ + --hash=sha256:2f94fa3ae454a63ea3a19f73b95deeebc9f02ba2d5617ca16f0bbdae375cda47 \ + --hash=sha256:31564a67c3e4005f27815634343df688b25705cccb22bc1db621c781ddc64c69 \ + --hash=sha256:347974105bbd4ea068106ec65e8e8ebd86f28c19e529d115d89bd8cc5cda3079 \ + --hash=sha256:379e03422178436af4f3abe0aa8f401aa77ae2487843738542a75faf44a31f0c \ + --hash=sha256:3eda1cb7e9da1b22588cefff09f0951771d6ee9fa8dbe66f5ae04cc5f26b2b55 \ + --hash=sha256:51695d3b199cd03098ae5b42833006a0f43dc5418d3102972addc593a783bc02 \ + --hash=sha256:54c000abeaff6d8771a4e2cef40900919908ea7b6b6a30eae72752607c6db559 \ + --hash=sha256:5b936bf552e4f6357f5727579072ff1e1324717902127ffe60c92d29b67b7be3 \ + --hash=sha256:6075fd24df23133c1b078e08a9b04a3bc40b31a8def4ee0b9f2c8865acce913e \ + --hash=sha256:661f641b44ed315556a2fa630239adfd77bd1b11cb0b9d96ed8ad90b0b1e4978 \ + --hash=sha256:6ea6b300a6bdd782e49922d690e11c3669828fe36fc2471408c58b93b5535a98 \ + --hash=sha256:6ed1d6f791eabfd9808afea1e068f5e59418e55721db8b7f3bfc39dc831c42ae \ + --hash=sha256:7934e055fd5cd9dee60f11d16c8d79c4567315824bacb1246d0208a47eca9755 \ + --hash=sha256:7ab36e17af592eec5747c68ef2722a74c1a4a70f3772bc661079baf4ae30e40d \ + --hash=sha256:7f6d96fdb0975044fdd7953b35d003b03f9e2bcf85f2d2cf86285ece53e9f991 \ + --hash=sha256:83e5ca0d5b743cde3d29fda74ccab37bdd0911f25bd4cdf09ff8b51b7b4f2fa1 \ + --hash=sha256:85506b3328a9e083cc0a0fb3ba27e33c8db78341b3eb12eb72e8afd166c36680 \ + --hash=sha256:8af75085b4bc0b5c40c4a3c0e113fa95e84c60f4ed6786cbb675aeb1ee128247 \ + --hash=sha256:8b1359aba0ff810d5830d5ab8e2c4a02bebf98a60aa0124fb29aa78cfdb8031f \ + --hash=sha256:8fbd7d77f8aba46d43245e86dd91a8970eac4fb74c473f8e30e9c07581f852b2 \ + --hash=sha256:907e8247480f287aa9bbc9391bd6de23c906d48af54c8c421df84655eef66af7 \ + --hash=sha256:93d5ea0b5da8d66d868b32c614d2b52d14304444e39e13a59566d4acb8d6e2e4 \ + --hash=sha256:97bc9d41e69a7521a358f9b8e44871f6cdeb42af31815c17aed36372d4eec667 \ + --hash=sha256:994cdb1942a7a4c2e10098d9162948c9e7b235df755de91ca33f6e0481366fdb \ + --hash=sha256:a141de3d5a92188234afa61653ed0bbd2dde46ad47b15c3042ffb89548e77094 \ + --hash=sha256:a1e15b230c3613e8ea82c9fc6941b2093e8eb939dd794c02754d33980ba81e36 \ + --hash=sha256:aad5e300ab32036eb3fdc350ad30877210e2f51bceaca83fb7fef4d2b6c72b79 \ + --hash=sha256:b529fdfa881b69fe563dbd98acce84f3e5a67df13de415e143ef053ff006d500 \ + --hash=sha256:b9c77f0d1436ea4b4dc089ed8335fa141e6a251a92f75f675056dac4ab47a71e \ + --hash=sha256:bb621ec2dbbbe8df78a27dbd9dd7919f9b7d32a73fafcb4d9252fc4637343582 \ + --hash=sha256:c7250848ce69559756ad0086a37b82c986cd33c2d344ab87fea596c5ac6d9442 \ + --hash=sha256:c8d1d14aa0f600b5be363077b621b1b4d1eb3fbf90af83f9281cda668e6ff7fd \ + --hash=sha256:d1655a6fc7aecd333b079d00fb3c8132d18988e47f19740c69303bf02e9883c6 \ + --hash=sha256:d6353ba89cfc657a3f5beabb3b69be226adbb5c6c7a66398e17809b0ce3c4731 \ + --hash=sha256:da4377904a3379f0c1b75a965fff23b28315bcd516d27f99a803720dfebd94d4 \ + --hash=sha256:e49ea4c1a9543d2bd8a747ff24411509c29e4bdcde05b5b0895e2120cb1a761d \ + --hash=sha256:e4e08305bfd76ba8edab08dcc6496f40674f44eb9d5e23153efa0a35750337e8 \ + --hash=sha256:e6fa05a680e35d0fcc1470cb070b10e6fe247af54768f488ed93542e71339d6f \ + --hash=sha256:e7e6f2d6fd48422071cc8a6f8542016f350b79cc782752de531577d35e9bd677 \ + --hash=sha256:e904c0381c014b914136c492c8fa711ca4cced4e9b3d110e5e7d436d0fc289e8 \ + --hash=sha256:ec2b0ab7edc8cd4b0eb428b38ed89079bdc20c6bdb5f889d353011038caac2f9 \ + --hash=sha256:ef5ce841e102278c1c2e98f043db99d6755b1c58bde475516aef3a008ed7f28e \ + --hash=sha256:f351c7d7d92f67c0609329ab2735eee0426a03022771b00102816a72715bb00b \ + --hash=sha256:fab7c640815812ed5f10fbee7abbf58788d602046b7bb3af9b1ac753a6d5e916 \ + --hash=sha256:fc06cc8073c8e87072138ba1e431300e2d408f054b27047d047b549455066ff4 + # via -r requirements/requirements.in diff --git a/examples/multi_python_versions/requirements/requirements_lock_3_9.txt b/examples/multi_python_versions/requirements/requirements_lock_3_9.txt new file mode 100644 index 0000000000..124355e4d2 --- /dev/null +++ b/examples/multi_python_versions/requirements/requirements_lock_3_9.txt @@ -0,0 +1,56 @@ +# +# This file is autogenerated by pip-compile with python 3.9 +# To update, run: +# +# bazel run //requirements:requirements_3_9.update +# +websockets==10.3 \ + --hash=sha256:07cdc0a5b2549bcfbadb585ad8471ebdc7bdf91e32e34ae3889001c1c106a6af \ + --hash=sha256:210aad7fdd381c52e58777560860c7e6110b6174488ef1d4b681c08b68bf7f8c \ + --hash=sha256:28dd20b938a57c3124028680dc1600c197294da5db4292c76a0b48efb3ed7f76 \ + --hash=sha256:2f94fa3ae454a63ea3a19f73b95deeebc9f02ba2d5617ca16f0bbdae375cda47 \ + --hash=sha256:31564a67c3e4005f27815634343df688b25705cccb22bc1db621c781ddc64c69 \ + --hash=sha256:347974105bbd4ea068106ec65e8e8ebd86f28c19e529d115d89bd8cc5cda3079 \ + --hash=sha256:379e03422178436af4f3abe0aa8f401aa77ae2487843738542a75faf44a31f0c \ + --hash=sha256:3eda1cb7e9da1b22588cefff09f0951771d6ee9fa8dbe66f5ae04cc5f26b2b55 \ + --hash=sha256:51695d3b199cd03098ae5b42833006a0f43dc5418d3102972addc593a783bc02 \ + --hash=sha256:54c000abeaff6d8771a4e2cef40900919908ea7b6b6a30eae72752607c6db559 \ + --hash=sha256:5b936bf552e4f6357f5727579072ff1e1324717902127ffe60c92d29b67b7be3 \ + --hash=sha256:6075fd24df23133c1b078e08a9b04a3bc40b31a8def4ee0b9f2c8865acce913e \ + --hash=sha256:661f641b44ed315556a2fa630239adfd77bd1b11cb0b9d96ed8ad90b0b1e4978 \ + --hash=sha256:6ea6b300a6bdd782e49922d690e11c3669828fe36fc2471408c58b93b5535a98 \ + --hash=sha256:6ed1d6f791eabfd9808afea1e068f5e59418e55721db8b7f3bfc39dc831c42ae \ + --hash=sha256:7934e055fd5cd9dee60f11d16c8d79c4567315824bacb1246d0208a47eca9755 \ + --hash=sha256:7ab36e17af592eec5747c68ef2722a74c1a4a70f3772bc661079baf4ae30e40d \ + --hash=sha256:7f6d96fdb0975044fdd7953b35d003b03f9e2bcf85f2d2cf86285ece53e9f991 \ + --hash=sha256:83e5ca0d5b743cde3d29fda74ccab37bdd0911f25bd4cdf09ff8b51b7b4f2fa1 \ + --hash=sha256:85506b3328a9e083cc0a0fb3ba27e33c8db78341b3eb12eb72e8afd166c36680 \ + --hash=sha256:8af75085b4bc0b5c40c4a3c0e113fa95e84c60f4ed6786cbb675aeb1ee128247 \ + --hash=sha256:8b1359aba0ff810d5830d5ab8e2c4a02bebf98a60aa0124fb29aa78cfdb8031f \ + --hash=sha256:8fbd7d77f8aba46d43245e86dd91a8970eac4fb74c473f8e30e9c07581f852b2 \ + --hash=sha256:907e8247480f287aa9bbc9391bd6de23c906d48af54c8c421df84655eef66af7 \ + --hash=sha256:93d5ea0b5da8d66d868b32c614d2b52d14304444e39e13a59566d4acb8d6e2e4 \ + --hash=sha256:97bc9d41e69a7521a358f9b8e44871f6cdeb42af31815c17aed36372d4eec667 \ + --hash=sha256:994cdb1942a7a4c2e10098d9162948c9e7b235df755de91ca33f6e0481366fdb \ + --hash=sha256:a141de3d5a92188234afa61653ed0bbd2dde46ad47b15c3042ffb89548e77094 \ + --hash=sha256:a1e15b230c3613e8ea82c9fc6941b2093e8eb939dd794c02754d33980ba81e36 \ + --hash=sha256:aad5e300ab32036eb3fdc350ad30877210e2f51bceaca83fb7fef4d2b6c72b79 \ + --hash=sha256:b529fdfa881b69fe563dbd98acce84f3e5a67df13de415e143ef053ff006d500 \ + --hash=sha256:b9c77f0d1436ea4b4dc089ed8335fa141e6a251a92f75f675056dac4ab47a71e \ + --hash=sha256:bb621ec2dbbbe8df78a27dbd9dd7919f9b7d32a73fafcb4d9252fc4637343582 \ + --hash=sha256:c7250848ce69559756ad0086a37b82c986cd33c2d344ab87fea596c5ac6d9442 \ + --hash=sha256:c8d1d14aa0f600b5be363077b621b1b4d1eb3fbf90af83f9281cda668e6ff7fd \ + --hash=sha256:d1655a6fc7aecd333b079d00fb3c8132d18988e47f19740c69303bf02e9883c6 \ + --hash=sha256:d6353ba89cfc657a3f5beabb3b69be226adbb5c6c7a66398e17809b0ce3c4731 \ + --hash=sha256:da4377904a3379f0c1b75a965fff23b28315bcd516d27f99a803720dfebd94d4 \ + --hash=sha256:e49ea4c1a9543d2bd8a747ff24411509c29e4bdcde05b5b0895e2120cb1a761d \ + --hash=sha256:e4e08305bfd76ba8edab08dcc6496f40674f44eb9d5e23153efa0a35750337e8 \ + --hash=sha256:e6fa05a680e35d0fcc1470cb070b10e6fe247af54768f488ed93542e71339d6f \ + --hash=sha256:e7e6f2d6fd48422071cc8a6f8542016f350b79cc782752de531577d35e9bd677 \ + --hash=sha256:e904c0381c014b914136c492c8fa711ca4cced4e9b3d110e5e7d436d0fc289e8 \ + --hash=sha256:ec2b0ab7edc8cd4b0eb428b38ed89079bdc20c6bdb5f889d353011038caac2f9 \ + --hash=sha256:ef5ce841e102278c1c2e98f043db99d6755b1c58bde475516aef3a008ed7f28e \ + --hash=sha256:f351c7d7d92f67c0609329ab2735eee0426a03022771b00102816a72715bb00b \ + --hash=sha256:fab7c640815812ed5f10fbee7abbf58788d602046b7bb3af9b1ac753a6d5e916 \ + --hash=sha256:fc06cc8073c8e87072138ba1e431300e2d408f054b27047d047b549455066ff4 + # via -r requirements/requirements.in diff --git a/examples/multi_python_versions/tests/BUILD.bazel b/examples/multi_python_versions/tests/BUILD.bazel new file mode 100644 index 0000000000..7219ca5c27 --- /dev/null +++ b/examples/multi_python_versions/tests/BUILD.bazel @@ -0,0 +1,148 @@ +load("@python//3.10:defs.bzl", py_binary_3_10 = "py_binary", py_test_3_10 = "py_test") +load("@python//3.8:defs.bzl", py_binary_3_8 = "py_binary", py_test_3_8 = "py_test") +load("@python//3.9:defs.bzl", py_binary_3_9 = "py_binary", py_test_3_9 = "py_test") +load("@rules_python//python:defs.bzl", "py_binary", "py_test") + +py_binary( + name = "version_default", + srcs = ["version.py"], + main = "version.py", +) + +py_binary_3_8( + name = "version_3_8", + srcs = ["version.py"], + main = "version.py", +) + +py_binary_3_9( + name = "version_3_9", + srcs = ["version.py"], + main = "version.py", +) + +py_binary_3_10( + name = "version_3_10", + srcs = ["version.py"], + main = "version.py", +) + +py_test( + name = "my_lib_default_test", + srcs = ["my_lib_test.py"], + main = "my_lib_test.py", + deps = ["//libs/my_lib"], +) + +py_test_3_8( + name = "my_lib_3_8_test", + srcs = ["my_lib_test.py"], + main = "my_lib_test.py", + deps = ["//libs/my_lib"], +) + +py_test_3_9( + name = "my_lib_3_9_test", + srcs = ["my_lib_test.py"], + main = "my_lib_test.py", + deps = ["//libs/my_lib"], +) + +py_test_3_10( + name = "my_lib_3_10_test", + srcs = ["my_lib_test.py"], + main = "my_lib_test.py", + deps = ["//libs/my_lib"], +) + +py_test( + name = "version_default_test", + srcs = ["version_test.py"], + env = {"VERSION_CHECK": "3.9"}, # The default defined in the WORKSPACE. + main = "version_test.py", +) + +py_test_3_8( + name = "version_3_8_test", + srcs = ["version_test.py"], + env = {"VERSION_CHECK": "3.8"}, + main = "version_test.py", +) + +py_test_3_9( + name = "version_3_9_test", + srcs = ["version_test.py"], + env = {"VERSION_CHECK": "3.9"}, + main = "version_test.py", +) + +py_test_3_10( + name = "version_3_10_test", + srcs = ["version_test.py"], + env = {"VERSION_CHECK": "3.10"}, + main = "version_test.py", +) + +py_test( + name = "version_default_takes_3_10_subprocess_test", + srcs = ["cross_version_test.py"], + data = [":version_3_10"], + env = { + "SUBPROCESS_VERSION_CHECK": "3.10", + "SUBPROCESS_VERSION_PY_BINARY": "$(rootpath :version_3_10)", + "VERSION_CHECK": "3.9", + }, + main = "cross_version_test.py", +) + +py_test_3_10( + name = "version_3_10_takes_3_9_subprocess_test", + srcs = ["cross_version_test.py"], + data = [":version_3_9"], + env = { + "SUBPROCESS_VERSION_CHECK": "3.9", + "SUBPROCESS_VERSION_PY_BINARY": "$(rootpath :version_3_9)", + "VERSION_CHECK": "3.10", + }, + main = "cross_version_test.py", +) + +sh_test( + name = "version_test_binary_default", + srcs = ["version_test.sh"], + data = [":version_default"], + env = { + "VERSION_CHECK": "3.9", # The default defined in the WORKSPACE. + "VERSION_PY_BINARY": "$(rootpath :version_default)", + }, +) + +sh_test( + name = "version_test_binary_3_8", + srcs = ["version_test.sh"], + data = [":version_3_8"], + env = { + "VERSION_CHECK": "3.8", + "VERSION_PY_BINARY": "$(rootpath :version_3_8)", + }, +) + +sh_test( + name = "version_test_binary_3_9", + srcs = ["version_test.sh"], + data = [":version_3_9"], + env = { + "VERSION_CHECK": "3.9", + "VERSION_PY_BINARY": "$(rootpath :version_3_9)", + }, +) + +sh_test( + name = "version_test_binary_3_10", + srcs = ["version_test.sh"], + data = [":version_3_10"], + env = { + "VERSION_CHECK": "3.10", + "VERSION_PY_BINARY": "$(rootpath :version_3_10)", + }, +) diff --git a/examples/multi_python_versions/tests/cross_version_test.py b/examples/multi_python_versions/tests/cross_version_test.py new file mode 100644 index 0000000000..f933ed6ffa --- /dev/null +++ b/examples/multi_python_versions/tests/cross_version_test.py @@ -0,0 +1,25 @@ +import os +import subprocess +import sys + +process = subprocess.run( + [os.getenv("SUBPROCESS_VERSION_PY_BINARY")], + stdout=subprocess.PIPE, + universal_newlines=True, +) + +subprocess_current = process.stdout.strip() +subprocess_expected = os.getenv("SUBPROCESS_VERSION_CHECK") + +if subprocess_current != subprocess_expected: + print( + f"expected subprocess version '{subprocess_expected}' is different than returned '{subprocess_current}'" + ) + sys.exit(1) + +expected = os.getenv("VERSION_CHECK") +current = f"{sys.version_info.major}.{sys.version_info.minor}" + +if current != expected: + print(f"expected version '{expected}' is different than returned '{current}'") + sys.exit(1) diff --git a/examples/multi_python_versions/tests/my_lib_test.py b/examples/multi_python_versions/tests/my_lib_test.py new file mode 100644 index 0000000000..4fc7095cf1 --- /dev/null +++ b/examples/multi_python_versions/tests/my_lib_test.py @@ -0,0 +1,10 @@ +import os +import sys + +import libs.my_lib as my_lib + +sanitized_version_check = f"{sys.version_info.major}_{sys.version_info.minor}" + +if not my_lib.websockets_is_for_python_version(sanitized_version_check): + print("expected package for Python version is different than returned") + sys.exit(1) diff --git a/examples/multi_python_versions/tests/version.py b/examples/multi_python_versions/tests/version.py new file mode 100644 index 0000000000..1007a14d7e --- /dev/null +++ b/examples/multi_python_versions/tests/version.py @@ -0,0 +1,3 @@ +import sys + +print(f"{sys.version_info.major}.{sys.version_info.minor}") diff --git a/examples/multi_python_versions/tests/version_test.py b/examples/multi_python_versions/tests/version_test.py new file mode 100644 index 0000000000..305773cf58 --- /dev/null +++ b/examples/multi_python_versions/tests/version_test.py @@ -0,0 +1,9 @@ +import os +import sys + +expected = os.getenv("VERSION_CHECK") +current = f"{sys.version_info.major}.{sys.version_info.minor}" + +if current != expected: + print(f"expected version '{expected}' is different than returned '{current}'") + sys.exit(1) diff --git a/examples/multi_python_versions/tests/version_test.sh b/examples/multi_python_versions/tests/version_test.sh new file mode 100755 index 0000000000..b8f510df31 --- /dev/null +++ b/examples/multi_python_versions/tests/version_test.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -o errexit -o nounset -o pipefail + +version_py_binary=$("${VERSION_PY_BINARY}") + +if [[ "${version_py_binary}" != "${VERSION_CHECK}" ]]; then + echo >&2 "expected version '${VERSION_CHECK}' is different than returned '${version_py_binary}'" + exit 1 +fi diff --git a/examples/pip_parse/WORKSPACE b/examples/pip_parse/WORKSPACE index e96db9f844..cd557a35db 100644 --- a/examples/pip_parse/WORKSPACE +++ b/examples/pip_parse/WORKSPACE @@ -1,5 +1,16 @@ workspace(name = "rules_python_pip_parse_example") +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +http_archive( + name = "bazel_skylib", + sha256 = "c6966ec828da198c5d9adbaa94c05e3a1c7f21bd012a0b29ba8ddbccb2c93b0d", + urls = [ + "https://github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", + "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", + ], +) + local_repository( name = "rules_python", path = "../..", diff --git a/python/BUILD b/python/BUILD index ce19653547..dcdbee15af 100644 --- a/python/BUILD +++ b/python/BUILD @@ -34,8 +34,9 @@ filegroup( name = "distribution", srcs = glob(["**"]) + [ "//python/constraints:distribution", - "//python/runfiles:distribution", + "//python/config_settings:distribution", "//python/private:distribution", + "//python/runfiles:distribution", ], visibility = ["//:__pkg__"], ) diff --git a/python/config_settings/BUILD.bazel b/python/config_settings/BUILD.bazel new file mode 100644 index 0000000000..272ba78f1f --- /dev/null +++ b/python/config_settings/BUILD.bazel @@ -0,0 +1,12 @@ +load("//python:versions.bzl", "TOOL_VERSIONS") +load(":config_settings.bzl", "construct_config_settings") + +filegroup( + name = "distribution", + srcs = glob(["*.bzl"]) + [ + "BUILD.bazel", + ], + visibility = ["//python:__pkg__"], +) + +construct_config_settings(python_versions = TOOL_VERSIONS.keys()) diff --git a/python/config_settings/config_settings.bzl b/python/config_settings/config_settings.bzl new file mode 100644 index 0000000000..977d023918 --- /dev/null +++ b/python/config_settings/config_settings.bzl @@ -0,0 +1,26 @@ +"""This module is used to construct the config settings in the BUILD file in this same package. +""" + +load("@bazel_skylib//rules:common_settings.bzl", "string_flag") + +# buildifier: disable=unnamed-macro +def construct_config_settings(python_versions): + """Constructs a set of configs for all Python versions. + + Args: + python_versions: The Python versions supported by rules_python. + """ + string_flag( + name = "python_version", + build_setting_default = python_versions[0], + values = python_versions, + visibility = ["//visibility:public"], + ) + + for python_version in python_versions: + python_version_constraint_setting = "is_python_" + python_version + native.config_setting( + name = python_version_constraint_setting, + flag_values = {":python_version": python_version}, + visibility = ["//visibility:public"], + ) diff --git a/python/config_settings/transition.bzl b/python/config_settings/transition.bzl new file mode 100644 index 0000000000..2fd3384543 --- /dev/null +++ b/python/config_settings/transition.bzl @@ -0,0 +1,208 @@ +"""The transition module contains the rule definitions to wrap py_binary and py_test and transition +them to the desired target platform. +""" + +load("@bazel_skylib//lib:dicts.bzl", "dicts") +load("//python:defs.bzl", _py_binary = "py_binary", _py_test = "py_test") + +def _transition_python_version_impl(_, attr): + return {"//python/config_settings:python_version": str(attr.python_version)} + +_transition_python_version = transition( + implementation = _transition_python_version_impl, + inputs = [], + outputs = ["//python/config_settings:python_version"], +) + +def _transition_py_impl(ctx): + target = ctx.attr.target + windows_constraint = ctx.attr._windows_constraint[platform_common.ConstraintValueInfo] + target_is_windows = ctx.target_platform_has_constraint(windows_constraint) + executable = ctx.actions.declare_file(ctx.attr.name + (".exe" if target_is_windows else "")) + ctx.actions.symlink( + is_executable = True, + output = executable, + target_file = target[DefaultInfo].files_to_run.executable, + ) + zipfile_symlink = None + if target_is_windows: + # Under Windows, the expected ".zip" does not exist, so we have to + # create the symlink ourselves to achieve the same behaviour as in macOS + # and Linux. + zipfile = None + expected_target_path = target[DefaultInfo].files_to_run.executable.short_path[:-4] + ".zip" + for file in target[DefaultInfo].default_runfiles.files.to_list(): + if file.short_path == expected_target_path: + zipfile = file + zipfile_symlink = ctx.actions.declare_file(ctx.attr.name + ".zip") + ctx.actions.symlink( + is_executable = True, + output = zipfile_symlink, + target_file = zipfile, + ) + env = {} + for k, v in ctx.attr.env.items(): + env[k] = ctx.expand_location(v) + + providers = [ + DefaultInfo( + executable = executable, + files = depset([zipfile_symlink] if zipfile_symlink else [], transitive = [target[DefaultInfo].files]), + runfiles = ctx.runfiles([zipfile_symlink] if zipfile_symlink else []).merge(target[DefaultInfo].default_runfiles), + ), + target[PyInfo], + target[PyRuntimeInfo], + # Ensure that the binary we're wrapping is included in code coverage. + coverage_common.instrumented_files_info( + ctx, + dependency_attributes = ["target"], + ), + target[OutputGroupInfo], + # testing.TestEnvironment is deprecated in favour of RunEnvironmentInfo but + # RunEnvironmentInfo is not exposed in Bazel < 5.3. + # https://github.com/bazelbuild/bazel/commit/dbdfa07e92f99497be9c14265611ad2920161483 + (RunEnvironmentInfo if hasattr(native, "RunEnvironmentInfo") else testing.TestEnvironment)(environment = env), + ] + return providers + +_COMMON_ATTRS = { + "deps": attr.label_list( + mandatory = False, + ), + "env": attr.string_dict( + mandatory = False, + ), + "python_version": attr.string( + mandatory = True, + ), + "srcs": attr.label_list( + allow_files = True, + mandatory = False, + ), + "target": attr.label( + executable = True, + cfg = "target", + mandatory = True, + providers = [PyInfo], + ), + # "tools" is a hack here. It should be "data" but "data" is not included by default in the + # location expansion in the same way it is in the native Python rules. The difference on how + # the Bazel deals with those special attributes differ on the LocationExpander, e.g.: + # https://github.com/bazelbuild/bazel/blob/ce611646/src/main/java/com/google/devtools/build/lib/analysis/LocationExpander.java#L415-L429 + # + # Since the default LocationExpander used by ctx.expand_location is not the same as the native + # rules (it doesn't set "allowDataAttributeEntriesInLabel"), we use "tools" temporarily while a + # proper fix in Bazel happens. + # + # A fix for this was proposed in https://github.com/bazelbuild/bazel/pull/16381. + "tools": attr.label_list( + allow_files = True, + mandatory = False, + ), + # Required to Opt-in to the transitions feature. + "_allowlist_function_transition": attr.label( + default = "@bazel_tools//tools/allowlists/function_transition_allowlist", + ), + "_windows_constraint": attr.label( + default = "@platforms//os:windows", + ), +} + +_transition_py_binary = rule( + _transition_py_impl, + attrs = _COMMON_ATTRS, + cfg = _transition_python_version, + executable = True, +) + +_transition_py_test = rule( + _transition_py_impl, + attrs = _COMMON_ATTRS, + cfg = _transition_python_version, + test = True, +) + +def _py_rule(rule_impl, transition_rule, name, python_version, **kwargs): + args = kwargs.pop("args", None) + data = kwargs.pop("data", None) + env = kwargs.pop("env", None) + srcs = kwargs.pop("srcs", None) + deps = kwargs.pop("deps", None) + + # Attributes common to all build rules. + # https://bazel.build/reference/be/common-definitions#common-attributes + compatible_with = kwargs.pop("compatible_with", None) + deprecation = kwargs.pop("deprecation", None) + distribs = kwargs.pop("distribs", None) + exec_compatible_with = kwargs.pop("exec_compatible_with", None) + exec_properties = kwargs.pop("exec_properties", None) + features = kwargs.pop("features", None) + restricted_to = kwargs.pop("restricted_to", None) + tags = kwargs.pop("tags", None) + target_compatible_with = kwargs.pop("target_compatible_with", None) + testonly = kwargs.pop("testonly", None) + toolchains = kwargs.pop("toolchains", None) + visibility = kwargs.pop("visibility", None) + + common_attrs = { + "compatible_with": compatible_with, + "deprecation": deprecation, + "distribs": distribs, + "exec_compatible_with": exec_compatible_with, + "exec_properties": exec_properties, + "features": features, + "restricted_to": restricted_to, + "target_compatible_with": target_compatible_with, + "testonly": testonly, + "toolchains": toolchains, + } + + # Test-specific extra attributes. + if "env_inherit" in kwargs: + common_attrs["env_inherit"] = kwargs.pop("env_inherit") + if "size" in kwargs: + common_attrs["size"] = kwargs.pop("size") + if "timeout" in kwargs: + common_attrs["timeout"] = kwargs.pop("timeout") + if "flaky" in kwargs: + common_attrs["flaky"] = kwargs.pop("flaky") + if "shard_count" in kwargs: + common_attrs["shard_count"] = kwargs.pop("shard_count") + if "local" in kwargs: + common_attrs["local"] = kwargs.pop("local") + + # Binary-specific extra attributes. + if "output_licenses" in kwargs: + common_attrs["output_licenses"] = kwargs.pop("output_licenses") + + rule_impl( + name = "_" + name, + args = args, + data = data, + deps = deps, + env = env, + srcs = srcs, + tags = ["manual"] + (tags if tags else []), + visibility = ["//visibility:private"], + **dicts.add(common_attrs, kwargs) + ) + + return transition_rule( + name = name, + args = args, + deps = deps, + env = env, + python_version = python_version, + srcs = srcs, + tags = tags, + target = ":_" + name, + tools = data, + visibility = visibility, + **common_attrs + ) + +def py_binary(name, python_version, **kwargs): + return _py_rule(_py_binary, _transition_py_binary, name, python_version, **kwargs) + +def py_test(name, python_version, **kwargs): + return _py_rule(_py_test, _transition_py_test, name, python_version, **kwargs) diff --git a/python/pip.bzl b/python/pip.bzl index 02ea538c38..a3c9b6975a 100644 --- a/python/pip.bzl +++ b/python/pip.bzl @@ -16,6 +16,7 @@ load("//python/pip_install:pip_repository.bzl", "pip_repository", _package_annotation = "package_annotation") load("//python/pip_install:repositories.bzl", "pip_install_dependencies") load("//python/pip_install:requirements.bzl", _compile_pip_requirements = "compile_pip_requirements") +load(":versions.bzl", "MINOR_MAPPING") compile_pip_requirements = _compile_pip_requirements package_annotation = _package_annotation @@ -163,3 +164,200 @@ def pip_parse(requirements = None, requirements_lock = None, name = "pip_parsed_ bzlmod = bzlmod, **kwargs ) + +def _multi_pip_parse_impl(rctx): + rules_python = rctx.attr._rules_python_workspace.workspace_name + load_statements = [] + install_deps_calls = [] + process_requirements_calls = [] + for python_version, pypi_repository in rctx.attr.pip_parses.items(): + sanitized_python_version = python_version.replace(".", "_") + load_statement = """\ +load( + "@{pypi_repository}//:requirements.bzl", + _{sanitized_python_version}_install_deps = "install_deps", + _{sanitized_python_version}_all_requirements = "all_requirements", +)""".format( + pypi_repository = pypi_repository, + sanitized_python_version = sanitized_python_version, + ) + load_statements.append(load_statement) + process_requirements_call = """\ +_process_requirements( + pkg_labels = _{sanitized_python_version}_all_requirements, + python_version = "{python_version}", + repo_prefix = "{pypi_repository}_", +)""".format( + pypi_repository = pypi_repository, + python_version = python_version, + sanitized_python_version = sanitized_python_version, + ) + process_requirements_calls.append(process_requirements_call) + install_deps_call = """ _{sanitized_python_version}_install_deps(**whl_library_kwargs)""".format( + sanitized_python_version = sanitized_python_version, + ) + install_deps_calls.append(install_deps_call) + + requirements_bzl = """\ +# Generated by python/pip.bzl + +load("@{rules_python}//python:pip.bzl", "whl_library_alias") +{load_statements} + +_wheel_names = [] +_version_map = dict() +def _process_requirements(pkg_labels, python_version, repo_prefix): + for pkg_label in pkg_labels: + workspace_name = Label(pkg_label).workspace_name + wheel_name = workspace_name[len(repo_prefix):] + _wheel_names.append(wheel_name) + if not wheel_name in _version_map: + _version_map[wheel_name] = dict() + _version_map[wheel_name][python_version] = repo_prefix + +{process_requirements_calls} + +def _clean_name(name): + return name.replace("-", "_").replace(".", "_").lower() + +def requirement(name): + return "@{name}_" + _clean_name(name) + "//:pkg" + +def whl_requirement(name): + return "@{name}_" + _clean_name(name) + "//:whl" + +def data_requirement(name): + return "@{name}_" + _clean_name(name) + "//:data" + +def dist_info_requirement(name): + return "@{name}_" + _clean_name(name) + "//:dist_info" + +def entry_point(pkg, script = None): + fail("Not implemented yet") + +def install_deps(**whl_library_kwargs): +{install_deps_calls} + for wheel_name in _wheel_names: + whl_library_alias( + name = "{name}_" + wheel_name, + wheel_name = wheel_name, + default_version = "{default_version}", + version_map = _version_map[wheel_name], + ) +""".format( + name = rctx.attr.name, + install_deps_calls = "\n".join(install_deps_calls), + load_statements = "\n".join(load_statements), + process_requirements_calls = "\n".join(process_requirements_calls), + rules_python = rules_python, + default_version = rctx.attr.default_version, + ) + rctx.file("requirements.bzl", requirements_bzl) + rctx.file("BUILD.bazel", "exports_files(['requirements.bzl'])") + +_multi_pip_parse = repository_rule( + _multi_pip_parse_impl, + attrs = { + "default_version": attr.string(), + "pip_parses": attr.string_dict(), + "_rules_python_workspace": attr.label(default = Label("//:WORKSPACE")), + }, +) + +def _whl_library_alias_impl(rctx): + rules_python = rctx.attr._rules_python_workspace.workspace_name + default_repo_prefix = rctx.attr.version_map[rctx.attr.default_version] + version_map = rctx.attr.version_map.items() + build_content = ["# Generated by python/pip.bzl"] + for alias_name in ["pkg", "whl", "data", "dist_info"]: + build_content.append(_whl_library_render_alias_target( + alias_name = alias_name, + default_repo_prefix = default_repo_prefix, + rules_python = rules_python, + version_map = version_map, + wheel_name = rctx.attr.wheel_name, + )) + rctx.file("BUILD.bazel", "\n".join(build_content)) + +def _whl_library_render_alias_target( + alias_name, + default_repo_prefix, + rules_python, + version_map, + wheel_name): + alias = ["""\ +alias( + name = "{alias_name}", + actual = select({{""".format(alias_name = alias_name)] + for [python_version, repo_prefix] in version_map: + alias.append("""\ + "@{rules_python}//python/config_settings:is_python_{full_python_version}": "{actual}",""".format( + full_python_version = MINOR_MAPPING[python_version] if python_version in MINOR_MAPPING else python_version, + actual = "@{repo_prefix}{wheel_name}//:{alias_name}".format( + repo_prefix = repo_prefix, + wheel_name = wheel_name, + alias_name = alias_name, + ), + rules_python = rules_python, + )) + alias.append("""\ + "//conditions:default": "{default_actual}", + }}), + visibility = ["//visibility:public"], +)""".format( + default_actual = "@{repo_prefix}{wheel_name}//:{alias_name}".format( + repo_prefix = default_repo_prefix, + wheel_name = wheel_name, + alias_name = alias_name, + ), + )) + return "\n".join(alias) + +whl_library_alias = repository_rule( + _whl_library_alias_impl, + attrs = { + "default_version": attr.string(mandatory = True), + "version_map": attr.string_dict(mandatory = True), + "wheel_name": attr.string(mandatory = True), + "_rules_python_workspace": attr.label(default = Label("//:WORKSPACE")), + }, +) + +def multi_pip_parse(name, default_version, python_versions, python_interpreter_target, requirements_lock, **kwargs): + """NOT INTENDED FOR DIRECT USE! + + This is intended to be used by the multi_pip_parse implementation in the template of the + multi_toolchain_aliases repository rule. + + Args: + name: the name of the multi_pip_parse repository. + default_version: the default Python version. + python_versions: all Python toolchain versions currently registered. + python_interpreter_target: a dictionary which keys are Python versions and values are resolved host interpreters. + requirements_lock: a dictionary which keys are Python versions and values are locked requirements files. + **kwargs: extra arguments passed to all wrapped pip_parse. + + Returns: + The internal implementation of multi_pip_parse repository rule. + """ + pip_parses = {} + for python_version in python_versions: + if not python_version in python_interpreter_target: + fail("Missing python_interpreter_target for Python version %s in '%s'" % (python_version, name)) + if not python_version in requirements_lock: + fail("Missing requirements_lock for Python version %s in '%s'" % (python_version, name)) + + pip_parse_name = name + "_" + python_version.replace(".", "_") + pip_parse( + name = pip_parse_name, + python_interpreter_target = python_interpreter_target[python_version], + requirements_lock = requirements_lock[python_version], + **kwargs + ) + pip_parses[python_version] = pip_parse_name + + return _multi_pip_parse( + name = name, + default_version = default_version, + pip_parses = pip_parses, + ) diff --git a/python/pip_install/requirements.bzl b/python/pip_install/requirements.bzl index cca9213e1b..7e248f625f 100644 --- a/python/pip_install/requirements.bzl +++ b/python/pip_install/requirements.bzl @@ -1,17 +1,19 @@ """Rules to verify and update pip-compile locked requirements.txt""" -load("//python:defs.bzl", "py_binary", "py_test") +load("//python:defs.bzl", _py_binary = "py_binary", _py_test = "py_test") load("//python/pip_install:repositories.bzl", "requirement") def compile_pip_requirements( name, extra_args = [], - visibility = ["//visibility:private"], + py_binary = _py_binary, + py_test = _py_test, requirements_in = None, requirements_txt = None, - requirements_linux = None, requirements_darwin = None, + requirements_linux = None, requirements_windows = None, + visibility = ["//visibility:private"], tags = None, **kwargs): """Generates targets for managing pip dependencies with pip-compile. @@ -26,16 +28,18 @@ def compile_pip_requirements( - update with `bazel run .update` Args: - name: base name for generated targets, typically "requirements" - extra_args: passed to pip-compile - visibility: passed to both the _test and .update rules - requirements_in: file expressing desired dependencies - requirements_txt: result of "compiling" the requirements.in file + name: base name for generated targets, typically "requirements". + extra_args: passed to pip-compile. + py_binary: the py_binary rule to be used. + py_test: the py_test rule to be used. + requirements_in: file expressing desired dependencies. + requirements_txt: result of "compiling" the requirements.in file. requirements_linux: File of linux specific resolve output to check validate if requirement.in has changes. requirements_darwin: File of darwin specific resolve output to check validate if requirement.in has changes. requirements_windows: File of windows specific resolve output to check validate if requirement.in has changes. - tags: tagging attribute common to all build rules, passed to both the _test and .update rules - **kwargs: other bazel attributes passed to the "_test" rule + tags: tagging attribute common to all build rules, passed to both the _test and .update rules. + visibility: passed to both the _test and .update rules. + **kwargs: other bazel attributes passed to the "_test" rule. """ requirements_in = name + ".in" if requirements_in == None else requirements_in requirements_txt = name + ".txt" if requirements_txt == None else requirements_txt diff --git a/python/private/toolchains_repo.bzl b/python/private/toolchains_repo.bzl index 282859a685..93cf31a5fc 100644 --- a/python/private/toolchains_repo.bzl +++ b/python/private/toolchains_repo.bzl @@ -32,8 +32,14 @@ load( ) def _toolchains_repo_impl(rctx): + rules_python_repository_name = rctx.attr._rules_python_workspace.workspace_name + python_version_constraint = "@{rules_python}//python/config_settings:is_python_{python_version}".format( + rules_python = rules_python_repository_name, + python_version = rctx.attr.python_version, + ) + build_content = """\ -# Generated by toolchains_repo.bzl +# Generated by python/private/toolchains_repo.bzl # # These can be registered in the workspace file or passed to --extra_toolchains # flag. By default all these toolchains are registered by the @@ -49,14 +55,17 @@ def _toolchains_repo_impl(rctx): toolchain( name = "{platform}_toolchain", target_compatible_with = {compatible_with}, + target_settings = ["{python_version_constraint}"] if {set_python_version_constraint} else [], toolchain = "@{user_repository_name}_{platform}//:python_runtimes", toolchain_type = "@bazel_tools//tools/python:toolchain_type", ) """.format( - platform = platform, + compatible_with = meta.compatible_with, name = rctx.attr.name, + platform = platform, + python_version_constraint = python_version_constraint, + set_python_version_constraint = rctx.attr.set_python_version_constraint, user_repository_name = rctx.attr.user_repository_name, - compatible_with = meta.compatible_with, ) rctx.file("BUILD.bazel", build_content) @@ -66,26 +75,26 @@ toolchains_repo = repository_rule( doc = "Creates a repository with toolchain definitions for all known platforms " + "which can be registered or selected.", attrs = { + "python_version": attr.string(doc = "The Python version."), + "set_python_version_constraint": attr.bool(doc = "if target_compatible_with for the toolchain should set the version constraint"), "user_repository_name": attr.string(doc = "what the user chose for the base name"), + "_rules_python_workspace": attr.label(default = Label("//:WORKSPACE")), }, ) -def _resolved_interpreter_os_alias_impl(rctx): - (os_name, arch) = _host_os_arch(rctx) +def _toolchain_aliases_impl(rctx): + (os_name, arch) = get_host_os_arch(rctx) - host_platform = None - for platform, meta in PLATFORMS.items(): - if meta.os_name == os_name and meta.arch == arch: - host_platform = platform - if not host_platform: - fail("No platform declared for host OS {} on arch {}".format(os_name, arch)) + host_platform = get_host_platform(os_name, arch) is_windows = (os_name == WINDOWS_NAME) python3_binary_path = "python.exe" if is_windows else "bin/python3" + rules_python_repository_name = rctx.attr._rules_python_workspace.workspace_name + # Base BUILD file for this repository. build_contents = """\ -# Generated by python/repositories.bzl +# Generated by python/private/toolchains_repo.bzl package(default_visibility = ["//visibility:public"]) exports_files(["defs.bzl"]) alias(name = "files", actual = "@{py_repository}_{host_platform}//:files") @@ -112,29 +121,135 @@ alias(name = "pip", actual = "@{py_repository}_{host_platform}//:bin # Expose a Starlark file so rules can know what host platform we used and where to find an interpreter # when using repository_ctx.path, which doesn't understand aliases. rctx.file("defs.bzl", content = """\ -# Generated by python/repositories.bzl +# Generated by python/private/toolchains_repo.bzl + +load("@{rules_python}//python/config_settings:transition.bzl", _py_binary = "py_binary", _py_test = "py_test") +load("@{rules_python}//python:pip.bzl", _compile_pip_requirements = "compile_pip_requirements") + host_platform = "{host_platform}" interpreter = "@{py_repository}_{host_platform}//:{python3_binary_path}" + +def py_binary(name, **kwargs): + return _py_binary( + name = name, + python_version = "{python_version}", + **kwargs + ) + +def py_test(name, **kwargs): + return _py_test( + name = name, + python_version = "{python_version}", + **kwargs + ) + +def compile_pip_requirements(name, **kwargs): + return _compile_pip_requirements( + name = name, + py_binary = py_binary, + py_test = py_test, + **kwargs + ) + """.format( - py_repository = rctx.attr.user_repository_name, host_platform = host_platform, + py_repository = rctx.attr.user_repository_name, + python_version = rctx.attr.python_version, python3_binary_path = python3_binary_path, + rules_python = rules_python_repository_name, )) -resolved_interpreter_os_alias = repository_rule( - _resolved_interpreter_os_alias_impl, +toolchain_aliases = repository_rule( + _toolchain_aliases_impl, doc = """Creates a repository with a shorter name meant for the host platform, which contains a BUILD.bazel file declaring aliases to the host platform's targets. """, attrs = { + "python_version": attr.string(doc = "The Python version."), "user_repository_name": attr.string( mandatory = True, doc = "The base name for all created repositories, like 'python38'.", ), + "_rules_python_workspace": attr.label(default = Label("//:WORKSPACE")), + }, +) + +def _multi_toolchain_aliases_impl(rctx): + rules_python = rctx.attr._rules_python_workspace.workspace_name + + for python_version, repository_name in rctx.attr.python_versions.items(): + file = "{}/defs.bzl".format(python_version) + rctx.file(file, content = """\ +# Generated by python/private/toolchains_repo.bzl + +load( + "@{repository_name}//:defs.bzl", + _compile_pip_requirements = "compile_pip_requirements", + _host_platform = "host_platform", + _interpreter = "interpreter", + _py_binary = "py_binary", + _py_test = "py_test", +) + +compile_pip_requirements = _compile_pip_requirements +host_platform = _host_platform +interpreter = _interpreter +py_binary = _py_binary +py_test = _py_test +""".format( + repository_name = repository_name, + )) + rctx.file("{}/BUILD.bazel".format(python_version), "") + + pip_bzl = """\ +# Generated by python/private/toolchains_repo.bzl + +load("@{rules_python}//python:pip.bzl", "pip_parse", _multi_pip_parse = "multi_pip_parse") + +def multi_pip_parse(name, requirements_lock, **kwargs): + return _multi_pip_parse( + name = name, + python_versions = {python_versions}, + requirements_lock = requirements_lock, + **kwargs + ) + +""".format( + python_versions = rctx.attr.python_versions.keys(), + rules_python = rules_python, + ) + rctx.file("pip.bzl", content = pip_bzl) + rctx.file("BUILD.bazel", "") + +multi_toolchain_aliases = repository_rule( + _multi_toolchain_aliases_impl, + attrs = { + "python_versions": attr.string_dict(doc = "The Python versions."), + "_rules_python_workspace": attr.label(default = Label("//:WORKSPACE")), }, ) -def _host_os_arch(rctx): +def sanitize_platform_name(platform): + return platform.replace("-", "_") + +def get_host_platform(os_name, arch): + """Gets the host platform. + + Args: + os_name: the host OS name. + arch: the host arch. + Returns: + The host platform. + """ + host_platform = None + for platform, meta in PLATFORMS.items(): + if meta.os_name == os_name and meta.arch == arch: + host_platform = platform + if not host_platform: + fail("No platform declared for host OS {} on arch {}".format(os_name, arch)) + return host_platform + +def get_host_os_arch(rctx): """Infer the host OS name and arch from a repository context. Args: diff --git a/python/repositories.bzl b/python/repositories.bzl index 6965bcd70a..e0c9b0626d 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -17,7 +17,12 @@ For historic reasons, pip_repositories() is defined in //python:pip.bzl. """ -load("//python/private:toolchains_repo.bzl", "resolved_interpreter_os_alias", "toolchains_repo") +load( + "//python/private:toolchains_repo.bzl", + "multi_toolchain_aliases", + "toolchain_aliases", + "toolchains_repo", +) load( ":versions.bzl", "DEFAULT_RELEASE_BASE_URL", @@ -333,6 +338,7 @@ def python_register_toolchains( distutils = None, distutils_content = None, register_toolchains = True, + set_python_version_constraint = False, tool_versions = TOOL_VERSIONS, **kwargs): """Convenience macro for users which does typical setup. @@ -350,6 +356,7 @@ def python_register_toolchains( distutils: see the distutils attribute in the python_repository repository rule. distutils_content: see the distutils_content attribute in the python_repository repository rule. register_toolchains: Whether or not to register the downloaded toolchains. + set_python_version_constraint: When set to true, target_compatible_with for the toolchains will include a version constraint. tool_versions: a dict containing a mapping of version with SHASUM and platform info. If not supplied, the defaults in python/versions.bzl will be used **kwargs: passed to each python_repositories call. @@ -359,6 +366,8 @@ def python_register_toolchains( if python_version in MINOR_MAPPING: python_version = MINOR_MAPPING[python_version] + toolchain_repo_name = "{name}_toolchains".format(name = name) + for platform in PLATFORMS.keys(): sha256 = tool_versions[python_version]["sha256"].get(platform, None) if not sha256: @@ -382,17 +391,67 @@ def python_register_toolchains( **kwargs ) if register_toolchains: - native.register_toolchains("@{name}_toolchains//:{platform}_toolchain".format( - name = name, + native.register_toolchains("@{toolchain_repo_name}//:{platform}_toolchain".format( + toolchain_repo_name = toolchain_repo_name, platform = platform, )) - resolved_interpreter_os_alias( - name = name, + toolchains_repo( + name = toolchain_repo_name, + python_version = python_version, + set_python_version_constraint = set_python_version_constraint, user_repository_name = name, ) - toolchains_repo( - name = "{name}_toolchains".format(name = name), + toolchain_aliases( + name = name, + python_version = python_version, user_repository_name = name, ) + +def python_register_multi_toolchains( + name, + python_versions, + default_version = None, + **kwargs): + """Convenience macro for registering multiple Python toolchains. + + Args: + name: base name for each name in python_register_toolchains call. + python_versions: the Python version. + default_version: the default Python version. If not set, the first version in + python_versions is used. + **kwargs: passed to each python_register_toolchains call. + """ + if len(python_versions) == 0: + fail("python_versions must not be empty") + + if not default_version: + default_version = python_versions.pop(0) + for python_version in python_versions: + if python_version == default_version: + # We register the default version lastly so that it's not picked first when --platforms + # is set with a constraint during toolchain resolution. This is due to the fact that + # Bazel will match the unconstrained toolchain if we register it before the constrained + # ones. + continue + python_register_toolchains( + name = name + "_" + python_version.replace(".", "_"), + python_version = python_version, + set_python_version_constraint = True, + **kwargs + ) + python_register_toolchains( + name = name + "_" + default_version.replace(".", "_"), + python_version = default_version, + set_python_version_constraint = False, + **kwargs + ) + + multi_toolchain_aliases( + name = name, + python_versions = { + python_version: name + "_" + python_version.replace(".", "_") + for python_version in (python_versions + [default_version]) + }, + ) diff --git a/tests/pip_repository_entry_points/WORKSPACE b/tests/pip_repository_entry_points/WORKSPACE index dd80db47fa..f9f3543b80 100644 --- a/tests/pip_repository_entry_points/WORKSPACE +++ b/tests/pip_repository_entry_points/WORKSPACE @@ -1,5 +1,16 @@ workspace(name = "pip_repository_annotations_example") +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +http_archive( + name = "bazel_skylib", + sha256 = "c6966ec828da198c5d9adbaa94c05e3a1c7f21bd012a0b29ba8ddbccb2c93b0d", + urls = [ + "https://github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", + "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", + ], +) + local_repository( name = "rules_python", path = "../..", From b95f63925f7f75dd40e549171f29b7eec2df243c Mon Sep 17 00:00:00 2001 From: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Date: Mon, 28 Nov 2022 15:21:50 -0800 Subject: [PATCH 072/234] bump: python toolchain releases (#902) Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- python/versions.bzl | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/python/versions.bzl b/python/versions.bzl index b58160463c..dfe4320025 100644 --- a/python/versions.bzl +++ b/python/versions.bzl @@ -58,6 +58,17 @@ TOOL_VERSIONS = { }, "strip_prefix": "python", }, + "3.8.15": { + "url": "20221106/cpython-{python_version}+20221106-{platform}-{build}.tar.gz", + "sha256": { + "aarch64-apple-darwin": "1e0a92d1a4f5e6d4a99f86b1cbf9773d703fe7fd032590f3e9c285c7a5eeb00a", + "aarch64-unknown-linux-gnu": "886ab33ced13c84bf59ce8ff79eba6448365bfcafea1bf415bd1d75e21b690aa", + "x86_64-apple-darwin": "70b57f28c2b5e1e3dd89f0d30edd5bc414e8b20195766cf328e1b26bed7890e1", + "x86_64-pc-windows-msvc": "2fdc3fa1c95f982179bbbaedae2b328197658638799b6dcb63f9f494b0de59e2", + "x86_64-unknown-linux-gnu": "e47edfb2ceaf43fc699e20c179ec428b6f3e497cf8e2dcd8e9c936d4b96b1e56", + }, + "strip_prefix": "python", + }, "3.9.10": { "url": "20220227/cpython-{python_version}+20220227-{platform}-{build}.tar.gz", "sha256": { @@ -91,6 +102,17 @@ TOOL_VERSIONS = { }, "strip_prefix": "python", }, + "3.9.15": { + "url": "20221106/cpython-{python_version}+20221106-{platform}-{build}.tar.gz", + "sha256": { + "aarch64-apple-darwin": "64dc7e1013481c9864152c3dd806c41144c79d5e9cd3140e185c6a5060bdc9ab", + "aarch64-unknown-linux-gnu": "52a8c0a67fb919f80962d992da1bddb511cdf92faf382701ce7673e10a8ff98f", + "x86_64-apple-darwin": "f2bcade6fc976c472f18f2b3204d67202d43ae55cf6f9e670f95e488f780da08", + "x86_64-pc-windows-msvc": "022daacab215679b87f0d200d08b9068a721605fa4721ebeda38220fc641ccf6", + "x86_64-unknown-linux-gnu": "cdc3a4cfddcd63b6cebdd75b14970e02d8ef0ac5be4d350e57ab5df56c19e85e", + }, + "strip_prefix": "python", + }, "3.10.2": { "url": "20220227/cpython-{python_version}+20220227-{platform}-{build}.tar.gz", "sha256": { @@ -124,13 +146,24 @@ TOOL_VERSIONS = { }, "strip_prefix": "python", }, + "3.10.8": { + "url": "20221106/cpython-{python_version}+20221106-{platform}-{build}.tar.gz", + "sha256": { + "aarch64-apple-darwin": "d52b03817bd245d28e0a8b2f715716cd0fcd112820ccff745636932c76afa20a", + "aarch64-unknown-linux-gnu": "33170bef18c811906b738be530f934640491b065bf16c4d276c6515321918132", + "x86_64-apple-darwin": "525b79c7ce5de90ab66bd07b0ac1008bafa147ddc8a41bef15ffb7c9c1e9e7c5", + "x86_64-pc-windows-msvc": "f2b6d2f77118f06dd2ca04dae1175e44aaa5077a5ed8ddc63333c15347182bfe", + "x86_64-unknown-linux-gnu": "6c8db44ae0e18e320320bbaaafd2d69cde8bfea171ae2d651b7993d1396260b7", + }, + "strip_prefix": "python", + }, } # buildifier: disable=unsorted-dict-items MINOR_MAPPING = { - "3.8": "3.8.13", - "3.9": "3.9.13", - "3.10": "3.10.6", + "3.8": "3.8.15", + "3.9": "3.9.15", + "3.10": "3.10.8", } PLATFORMS = { From 7e3c89c19a0da0113bac62e5b5a89e95363d544b Mon Sep 17 00:00:00 2001 From: John Laxson Date: Mon, 28 Nov 2022 15:29:03 -0800 Subject: [PATCH 073/234] Correctly reference os-specific labels from central alias repo (#889) * Correctly reference os-specific labels from central alias repo The current aliases hardcode the bazel host os, which does not work when cross compiling. * Update toolchains_repo.bzl * fix: remove spaces from key in dict Co-authored-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- python/private/toolchains_repo.bzl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/python/private/toolchains_repo.bzl b/python/private/toolchains_repo.bzl index 93cf31a5fc..4b832d941a 100644 --- a/python/private/toolchains_repo.bzl +++ b/python/private/toolchains_repo.bzl @@ -96,22 +96,22 @@ def _toolchain_aliases_impl(rctx): build_contents = """\ # Generated by python/private/toolchains_repo.bzl package(default_visibility = ["//visibility:public"]) +load("@rules_python//python:versions.bzl", "PLATFORMS", "gen_python_config_settings") +gen_python_config_settings() exports_files(["defs.bzl"]) -alias(name = "files", actual = "@{py_repository}_{host_platform}//:files") -alias(name = "includes", actual = "@{py_repository}_{host_platform}//:includes") -alias(name = "libpython", actual = "@{py_repository}_{host_platform}//:libpython") -alias(name = "py3_runtime", actual = "@{py_repository}_{host_platform}//:py3_runtime") -alias(name = "python_headers", actual = "@{py_repository}_{host_platform}//:python_headers") -alias(name = "python_runtimes", actual = "@{py_repository}_{host_platform}//:python_runtimes") -alias(name = "python3", actual = "@{py_repository}_{host_platform}//:{python3_binary_path}") +alias(name = "files", actual = select({{":" + item: "@{py_repository}_" + item + "//:files" for item in PLATFORMS.keys()}})) +alias(name = "includes", actual = select({{":" + item: "@{py_repository}_" + item + "//:includes" for item in PLATFORMS.keys()}})) +alias(name = "libpython", actual = select({{":" + item: "@{py_repository}_" + item + "//:libpython" for item in PLATFORMS.keys()}})) +alias(name = "py3_runtime", actual = select({{":" + item: "@{py_repository}_" + item + "//:py3_runtime" for item in PLATFORMS.keys()}})) +alias(name = "python_headers", actual = select({{":" + item: "@{py_repository}_" + item + "//:python_headers" for item in PLATFORMS.keys()}})) +alias(name = "python_runtimes", actual = select({{":" + item: "@{py_repository}_" + item + "//:python_runtimes" for item in PLATFORMS.keys()}})) +alias(name = "python3", actual = select({{":" + item: "@{py_repository}_" + item + "//:" + ("python.exe" if "windows" in item else "bin/python3") for item in PLATFORMS.keys()}})) """.format( py_repository = rctx.attr.user_repository_name, - host_platform = host_platform, - python3_binary_path = python3_binary_path, ) if not is_windows: build_contents += """\ -alias(name = "pip", actual = "@{py_repository}_{host_platform}//:bin/pip") +alias(name = "pip", actual = select({{":" + item: "@{py_repository}_" + item + "//:python_runtimes" for item in PLATFORMS.keys() if "windows" not in item}})) """.format( py_repository = rctx.attr.user_repository_name, host_platform = host_platform, From 6095ae2da858054040c289d2ba6561cdebfb1256 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Mon, 28 Nov 2022 15:35:33 -0800 Subject: [PATCH 074/234] Document how to get started working on rules_python (#891) * Document how to get started working on rules_python This is based on my experience getting stated myself, where I have only minimal experience with GitHub, git, and many of the tools. * Various Spelling/grammar fixes Co-authored-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- CONTRIBUTING.md | 96 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 93 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8092f361fd..7b80037244 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,10 +3,77 @@ We'd love to accept your patches and contributions to this project. There are just a few small guidelines you need to follow. +## Getting started + +Before we can work on the code, we need to get a copy of it and setup some +local environment and tools. + +First, fork the code to your user and clone your fork. This gives you a private +playground where you can do any edits you'd like. For this guide, we'll use +the [GitHub `gh` tool](https://github.com/cli/cli) +([Linux install](https://github.com/cli/cli/blob/trunk/docs/install_linux.md)). +(More advanced users may prefer the GitHub UI and raw `git` commands). + +```shell +gh repo fork bazelbuild/rules_python --clone --remote +``` + +Next, make sure you have a new enough version of Python installed that supports the +various code formatters and other devtools. For a quick start, +[install pyenv](https://github.com/pyenv/pyenv-installer) and +at least Python 3.9.15: + +```shell +curl https://pyenv.run | bash +pyenv install 3.9.15 +pyenv shell 3.9.15 +``` + +## Development workflow + +It's suggested that you create what is called a "feature/topic branch" in your +fork when you begin working on code you want to eventually send or code review. + +``` +git checkout main # Start our branch from the latest code +git checkout -b my-feature # Create and switch to our feature branch +git push origin my-feature # Cause the branch to be created in your fork. +``` + +From here, you then edit code and commit to your local branch. If you want to +save your work to github, you use `git push` to do so: + +``` +git push origin my-feature +``` + +Once the code is in your github repo, you can then turn it into a Pull Request +to the actual rules_python project and begin the code review process. + + +## Running tests + +Running tests is particularly easy thanks to Bazel, simply run: + +``` +bazel test //... +``` + +And it will run all the tests it can find. The first time you do this, it will +probably take long time because various dependencies will need to be downloaded +and setup. Subsequent runs will be faster, but there are many tests, and some of +them are slow. If you're working on a particular area of code, you can run just +the tests in those directories instead, which can speed up your edit-run cycle. + +Note that there are tests to verify generated documentation is correct -- if +you're modifying the signature of a public function, these tests will likely +fail and you'll need to [regenerate the api docs](#documentation). + ## Formatting -Starlark files should be formatted by buildifier. -Otherwise the Buildkite CI will yell at you about formatting/linting violations. +Starlark files should be formatted by +[buildifier](https://github.com/bazelbuild/buildtools/blob/master/buildifier/README.md). +Otherwise the Buildkite CI will fail with formatting/linting violations. We suggest using a pre-commit hook to automate this. First [install pre-commit](https://pre-commit.com/#installation), then run @@ -14,9 +81,12 @@ then run ```shell pre-commit install ``` + ### Running buildifer manually -If you choose to run buildifier manually, run the following command: +You can also run buildifier manually. To do this, +[install buildifier](https://github.com/bazelbuild/buildtools/blob/master/buildifier/README.md), +and run the following command: ```shell $ buildifier --lint=fix --warnings=native-py -warnings=all WORKSPACE @@ -84,3 +154,23 @@ Issues should be triaged as follows: - Anything else, such as feature requests not related to existing core rules functionality, should also be filed in this repository but without the `core-rules` label. + +## FAQ + +### Installation errors when during `git commit` + +If you did `pre-commit install`, various tools are run when you do `git commit`. +This might show as an error such as: + +``` +[INFO] Installing environment for https://github.com/psf/black. +[INFO] Once installed this environment will be reused. +[INFO] This may take a few minutes... +An unexpected error has occurred: CalledProcessError: command: ... +``` + +To fix, you'll need to figure out what command is failing and why. Because these +are tools that run locally, its likely you'll need to fix something with your +environment or the installation of the tools. For Python tools (e.g. black or +isort), you can try using a different Python version in your shell by using +tools such as [pyenv](https://github.com/pyenv/pyenv). From b69431ec4a60f6810480293ac6b4668aa623b47d Mon Sep 17 00:00:00 2001 From: Ramon Buckland Date: Wed, 23 Nov 2022 13:32:56 +1100 Subject: [PATCH 075/234] fix: #895 append _py if ending with .py --- python/pip_install/extract_wheels/bazel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/pip_install/extract_wheels/bazel.py b/python/pip_install/extract_wheels/bazel.py index 013e4a23e1..8f442c930f 100644 --- a/python/pip_install/extract_wheels/bazel.py +++ b/python/pip_install/extract_wheels/bazel.py @@ -396,7 +396,7 @@ def extract_wheel( for name, (module, attribute) in sorted(whl.entry_points().items()): # There is an extreme edge-case with entry_points that end with `.py` # See: https://github.com/bazelbuild/bazel/blob/09c621e4cf5b968f4c6cdf905ab142d5961f9ddc/src/test/java/com/google/devtools/build/lib/rules/python/PyBinaryConfiguredTargetTest.java#L174 - entry_point_without_py = name[:-3] if name.endswith(".py") else name + entry_point_without_py = f"{name[:-3]}_py" if name.endswith(".py") else name entry_point_target_name = f"{WHEEL_ENTRY_POINT_PREFIX}_{entry_point_without_py}" entry_point_script_name = f"{entry_point_target_name}.py" (directory_path / entry_point_script_name).write_text( From 518c8734fdeda1ec16207e7da6029caa75c7a878 Mon Sep 17 00:00:00 2001 From: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Date: Tue, 29 Nov 2022 09:34:16 -0800 Subject: [PATCH 076/234] fix: missing RunEnvironmentInfo (#904) * fix: missing RunEnvironmentInfo Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: add reference to github issue Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- python/config_settings/transition.bzl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python/config_settings/transition.bzl b/python/config_settings/transition.bzl index 2fd3384543..e87e2c9c22 100644 --- a/python/config_settings/transition.bzl +++ b/python/config_settings/transition.bzl @@ -58,10 +58,11 @@ def _transition_py_impl(ctx): dependency_attributes = ["target"], ), target[OutputGroupInfo], - # testing.TestEnvironment is deprecated in favour of RunEnvironmentInfo but + # TODO(f0rmiga): testing.TestEnvironment is deprecated in favour of RunEnvironmentInfo but # RunEnvironmentInfo is not exposed in Bazel < 5.3. + # https://github.com/bazelbuild/rules_python/issues/901 # https://github.com/bazelbuild/bazel/commit/dbdfa07e92f99497be9c14265611ad2920161483 - (RunEnvironmentInfo if hasattr(native, "RunEnvironmentInfo") else testing.TestEnvironment)(environment = env), + testing.TestEnvironment(environment = env), ] return providers From b5f2d065977b244be2f027a7e27691bccb56bf7f Mon Sep 17 00:00:00 2001 From: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Date: Thu, 1 Dec 2022 11:15:10 -0800 Subject: [PATCH 077/234] fix: pip_compile to handle multiple generated requirements.in (#909) * fix: pip_compile to handle multiple generated requirements.in Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: only use requirements.in absolute when generated Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: use hermetic toolchain to lock the requirements Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: tests on CI Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: windows path separator madness Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- .bazelci/presubmit.yml | 16 +++++++++ .bazelrc | 4 +-- examples/pip_parse/BUILD | 10 ------ ...quirements.in.template => requirements.in} | 0 python/pip_install/pip_compile.py | 33 +++++++++---------- tests/compile_pip_requirements/.bazelrc | 5 +++ tests/compile_pip_requirements/.gitignore | 1 + tests/compile_pip_requirements/BUILD.bazel | 33 +++++++++++++++++++ tests/compile_pip_requirements/README.md | 3 ++ tests/compile_pip_requirements/WORKSPACE | 15 +++++++++ .../requirements_lock.txt | 16 +++++++++ 11 files changed, 107 insertions(+), 29 deletions(-) rename examples/pip_parse/{requirements.in.template => requirements.in} (100%) create mode 100644 tests/compile_pip_requirements/.bazelrc create mode 100644 tests/compile_pip_requirements/.gitignore create mode 100644 tests/compile_pip_requirements/BUILD.bazel create mode 100644 tests/compile_pip_requirements/README.md create mode 100644 tests/compile_pip_requirements/WORKSPACE create mode 100644 tests/compile_pip_requirements/requirements_lock.txt diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 56516e975b..641416f2cb 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -167,6 +167,22 @@ tasks: working_directory: examples/pip_repository_annotations platform: windows + integration_test_compile_pip_requirements_linux: + <<: *reusable_build_test_all + name: compile_pip_requirements integration tests on Linux + working_directory: tests/compile_pip_requirements + platform: ubuntu2004 + integration_test_compile_pip_requirements_macos: + <<: *reusable_build_test_all + name: compile_pip_requirements integration tests on macOS + working_directory: tests/compile_pip_requirements + platform: macos + integration_test_compile_pip_requirements_windows: + <<: *reusable_build_test_all + name: compile_pip_requirements integration tests on Windows + working_directory: tests/compile_pip_requirements + platform: windows + integration_test_pip_repository_entry_points_linux: <<: *reusable_build_test_all name: pip_repository_entry_points integration tests on Linux diff --git a/.bazelrc b/.bazelrc index 510191b847..f1c7b7a210 100644 --- a/.bazelrc +++ b/.bazelrc @@ -3,8 +3,8 @@ # This lets us glob() up all the files inside the examples to make them inputs to tests # (Note, we cannot use `common --deleted_packages` because the bazel version command doesn't support it) # To update these lines, run tools/bazel_integration_test/update_deleted_packages.sh -build --deleted_packages=examples/build_file_generation,examples/bzlmod,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/relative_requirements,tests/pip_repository_entry_points,tests/pip_deps -query --deleted_packages=examples/build_file_generation,examples/bzlmod,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/relative_requirements,tests/pip_repository_entry_points,tests/pip_deps +build --deleted_packages=examples/build_file_generation,examples/bzlmod,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps +query --deleted_packages=examples/build_file_generation,examples/bzlmod,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps test --test_output=errors diff --git a/examples/pip_parse/BUILD b/examples/pip_parse/BUILD index 1b6ba55f5e..653f75ce2b 100644 --- a/examples/pip_parse/BUILD +++ b/examples/pip_parse/BUILD @@ -55,16 +55,6 @@ alias( actual = entry_point("yamllint"), ) -# The requirements.in file can be checked in to the source tree or it can be -# generated. Pretend that we do some generating of the file. For this example, -# the "template" is already the file we want. -genrule( - name = "generate_requirements_in", - srcs = ["requirements.in.template"], - outs = ["requirements.in"], - cmd = "cp $(SRCS) $(OUTS)", -) - # This rule adds a convenient way to update the requirements file. compile_pip_requirements( name = "requirements", diff --git a/examples/pip_parse/requirements.in.template b/examples/pip_parse/requirements.in similarity index 100% rename from examples/pip_parse/requirements.in.template rename to examples/pip_parse/requirements.in diff --git a/python/pip_install/pip_compile.py b/python/pip_install/pip_compile.py index c9bcf32115..8d6cf1bd47 100644 --- a/python/pip_install/pip_compile.py +++ b/python/pip_install/pip_compile.py @@ -1,6 +1,7 @@ "Set defaults for the pip-compile command to run it under Bazel" import os +import re import sys from pathlib import Path from shutil import copyfile @@ -26,19 +27,17 @@ def _select_golden_requirements_file( return requirements_txt -def _fix_up_requirements_in_path( - resolved_requirements_in, requirements_in, output_file -): +def _fix_up_requirements_in_path(absolute_prefix, output_file): """Fix up references to the input file inside of the generated requirements file. We don't want fully resolved, absolute paths in the generated requirements file. The paths could differ for every invocation. Replace them with a predictable path. """ output_file = Path(output_file) - fixed_requirements_text = output_file.read_text().replace( - resolved_requirements_in, requirements_in - ) - output_file.write_text(fixed_requirements_text) + contents = output_file.read_text() + contents = contents.replace(absolute_prefix, "") + contents = re.sub(r"\\(?!(\n|\r\n))", "/", contents) + output_file.write_text(contents) if __name__ == "__main__": @@ -58,9 +57,11 @@ def _fix_up_requirements_in_path( requirements_windows = parse_str_none(sys.argv.pop(1)) update_target_label = sys.argv.pop(1) - # The requirements_in file could be generated. We need to get the path to it before we change - # directory into the workspace directory. - resolved_requirements_in = str(Path(requirements_in).resolve()) + # The requirements_in file could be generated, so we will need to remove the + # absolute prefixes in the locked requirements output file. + requirements_in_path = Path(requirements_in) + resolved_requirements_in = str(requirements_in_path.resolve()) + absolute_prefix = resolved_requirements_in[: -len(str(requirements_in_path))] # Before loading click, set the locale for its parser. # If it leaks through to the system setting, it may fail: @@ -116,7 +117,9 @@ def _fix_up_requirements_in_path( sys.argv.append("--generate-hashes") sys.argv.append("--output-file") sys.argv.append(requirements_txt if UPDATE else requirements_out) - sys.argv.append(resolved_requirements_in) + sys.argv.append( + requirements_in if requirements_in_path.exists() else resolved_requirements_in + ) if UPDATE: print("Updating " + requirements_txt) @@ -124,9 +127,7 @@ def _fix_up_requirements_in_path( cli() except SystemExit as e: if e.code == 0: - _fix_up_requirements_in_path( - resolved_requirements_in, requirements_in, requirements_txt - ) + _fix_up_requirements_in_path(absolute_prefix, requirements_txt) raise else: # cli will exit(0) on success @@ -145,9 +146,7 @@ def _fix_up_requirements_in_path( ) sys.exit(1) elif e.code == 0: - _fix_up_requirements_in_path( - resolved_requirements_in, requirements_in, requirements_out - ) + _fix_up_requirements_in_path(absolute_prefix, requirements_out) golden_filename = _select_golden_requirements_file( requirements_txt, requirements_linux, diff --git a/tests/compile_pip_requirements/.bazelrc b/tests/compile_pip_requirements/.bazelrc new file mode 100644 index 0000000000..f23315a7a1 --- /dev/null +++ b/tests/compile_pip_requirements/.bazelrc @@ -0,0 +1,5 @@ +test --test_output=errors + +# Windows requires these for multi-python support: +build --enable_runfiles +startup --windows_enable_symlinks diff --git a/tests/compile_pip_requirements/.gitignore b/tests/compile_pip_requirements/.gitignore new file mode 100644 index 0000000000..ac51a054d2 --- /dev/null +++ b/tests/compile_pip_requirements/.gitignore @@ -0,0 +1 @@ +bazel-* diff --git a/tests/compile_pip_requirements/BUILD.bazel b/tests/compile_pip_requirements/BUILD.bazel new file mode 100644 index 0000000000..258bb71ad5 --- /dev/null +++ b/tests/compile_pip_requirements/BUILD.bazel @@ -0,0 +1,33 @@ +load("@rules_python//python:pip.bzl", "compile_pip_requirements") + +genrule( + name = "generate_requirements_extra_in", + srcs = [], + outs = ["requirements_extra.in"], + cmd = "echo 'setuptools~=65.6.3' > $@", +) + +genrule( + name = "generate_requirements_in", + srcs = [], + outs = ["requirements.in"], + cmd = """ +cat > $@ < Date: Thu, 1 Dec 2022 11:28:08 -0800 Subject: [PATCH 078/234] ci: add debian11 to the matrix (#910) Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- .bazelci/presubmit.yml | 89 ++++++++++++++----- .bcr/presubmit.yml | 2 +- examples/bzlmod/requirements.in | 2 +- examples/bzlmod/requirements_lock.txt | 5 +- examples/bzlmod/requirements_windows.txt | 5 +- .../pip_repository_entry_points_test.py | 2 +- .../requirements.in | 2 +- .../requirements.txt | 5 +- 8 files changed, 82 insertions(+), 30 deletions(-) diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 641416f2cb..349708f68e 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -32,10 +32,14 @@ tasks: platform: ubuntu2004 build_targets: ["//gazelle/..."] test_targets: ["//gazelle/..."] - linux: + ubuntu: <<: *reusable_config - name: Default test on Linux + name: Default test on Ubuntu platform: ubuntu2004 + debian: + <<: *reusable_config + name: Default test on Debian + platform: debian11 macos: <<: *reusable_config name: Default test on macOS @@ -53,11 +57,16 @@ tasks: test_flags: - "--test_tag_filters=-integration-test,-acceptance-test" - integration_test_build_file_generation_linux: + integration_test_build_file_generation_ubuntu: <<: *reusable_build_test_all - name: build_file_generation integration tests on Linux + name: build_file_generation integration tests on Ubuntu working_directory: examples/build_file_generation platform: ubuntu2004 + integration_test_build_file_generation_debian: + <<: *reusable_build_test_all + name: build_file_generation integration tests on Debian + working_directory: examples/build_file_generation + platform: debian11 integration_test_build_file_generation_macos: <<: *reusable_build_test_all name: build_file_generation integration tests on macOS @@ -69,11 +78,16 @@ tasks: working_directory: examples/build_file_generation platform: windows - integration_test_bzlmod_linux: + integration_test_bzlmod_ubuntu: <<: *reusable_build_test_all - name: bzlmod integration tests on Linux + name: bzlmod integration tests on Ubuntu working_directory: examples/bzlmod platform: ubuntu2004 + integration_test_bzlmod_debian: + <<: *reusable_build_test_all + name: bzlmod integration tests on Debian + working_directory: examples/bzlmod + platform: debian11 integration_test_bzlmod_macos: <<: *reusable_build_test_all name: bzlmod integration tests on macOS @@ -85,11 +99,16 @@ tasks: working_directory: examples/bzlmod platform: windows - integration_test_multi_python_versions_linux: + integration_test_multi_python_versions_ubuntu: <<: *reusable_build_test_all - name: multi_python_versions integration tests on Linux + name: multi_python_versions integration tests on Ubuntu working_directory: examples/multi_python_versions platform: ubuntu2004 + integration_test_multi_python_versions_debian: + <<: *reusable_build_test_all + name: multi_python_versions integration tests on Debian + working_directory: examples/multi_python_versions + platform: debian11 integration_test_multi_python_versions_macos: <<: *reusable_build_test_all name: multi_python_versions integration tests on macOS @@ -101,11 +120,16 @@ tasks: working_directory: examples/multi_python_versions platform: windows - integration_test_pip_install_linux: + integration_test_pip_install_ubuntu: <<: *reusable_build_test_all - name: pip_install integration tests on Linux + name: pip_install integration tests on Ubuntu working_directory: examples/pip_install platform: ubuntu2004 + integration_test_pip_install_debian: + <<: *reusable_build_test_all + name: pip_install integration tests on Debian + working_directory: examples/pip_install + platform: debian11 integration_test_pip_install_macos: <<: *reusable_build_test_all name: pip_install integration tests on macOS @@ -117,11 +141,16 @@ tasks: working_directory: examples/pip_install platform: windows - integration_test_pip_parse_linux: + integration_test_pip_parse_ubuntu: <<: *reusable_build_test_all - name: pip_parse integration tests on Linux + name: pip_parse integration tests on Ubuntu working_directory: examples/pip_parse platform: ubuntu2004 + integration_test_pip_parse_debian: + <<: *reusable_build_test_all + name: pip_parse integration tests on Debian + working_directory: examples/pip_parse + platform: debian11 integration_test_pip_parse_macos: <<: *reusable_build_test_all name: pip_parse integration tests on macOS @@ -133,11 +162,16 @@ tasks: working_directory: examples/pip_parse platform: windows - integration_test_pip_parse_vendored_linux: + integration_test_pip_parse_vendored_ubuntu: <<: *reusable_build_test_all - name: pip_parse_vendored integration tests on Linux + name: pip_parse_vendored integration tests on Ubuntu working_directory: examples/pip_parse_vendored platform: ubuntu2004 + integration_test_pip_parse_vendored_debian: + <<: *reusable_build_test_all + name: pip_parse_vendored integration tests on Debian + working_directory: examples/pip_parse_vendored + platform: debian11 integration_test_pip_parse_vendored_macos: <<: *reusable_build_test_all name: pip_parse_vendored integration tests on macOS @@ -151,11 +185,16 @@ tasks: # working_directory: examples/pip_parse_vendored # platform: windows - integration_test_pip_repository_annotations_linux: + integration_test_pip_repository_annotations_ubuntu: <<: *reusable_build_test_all - name: pip_repository_annotations integration tests on Linux + name: pip_repository_annotations integration tests on Ubuntu working_directory: examples/pip_repository_annotations platform: ubuntu2004 + integration_test_pip_repository_annotations_debian: + <<: *reusable_build_test_all + name: pip_repository_annotations integration tests on Debian + working_directory: examples/pip_repository_annotations + platform: debian11 integration_test_pip_repository_annotations_macos: <<: *reusable_build_test_all name: pip_repository_annotations integration tests on macOS @@ -167,11 +206,16 @@ tasks: working_directory: examples/pip_repository_annotations platform: windows - integration_test_compile_pip_requirements_linux: + integration_test_compile_pip_requirements_ubuntu: <<: *reusable_build_test_all - name: compile_pip_requirements integration tests on Linux + name: compile_pip_requirements integration tests on Ubuntu working_directory: tests/compile_pip_requirements platform: ubuntu2004 + integration_test_compile_pip_requirements_debian: + <<: *reusable_build_test_all + name: compile_pip_requirements integration tests on Debian + working_directory: tests/compile_pip_requirements + platform: debian11 integration_test_compile_pip_requirements_macos: <<: *reusable_build_test_all name: compile_pip_requirements integration tests on macOS @@ -183,11 +227,16 @@ tasks: working_directory: tests/compile_pip_requirements platform: windows - integration_test_pip_repository_entry_points_linux: + integration_test_pip_repository_entry_points_ubuntu: <<: *reusable_build_test_all - name: pip_repository_entry_points integration tests on Linux + name: pip_repository_entry_points integration tests on Ubuntu working_directory: tests/pip_repository_entry_points platform: ubuntu2004 + integration_test_pip_repository_entry_points_debian: + <<: *reusable_build_test_all + name: pip_repository_entry_points integration tests on Debian + working_directory: tests/pip_repository_entry_points + platform: debian11 integration_test_pip_repository_entry_points_macos: <<: *reusable_build_test_all name: pip_repository_entry_points integration tests on macOS diff --git a/.bcr/presubmit.yml b/.bcr/presubmit.yml index 2ab3c6dfe1..90e3122aca 100644 --- a/.bcr/presubmit.yml +++ b/.bcr/presubmit.yml @@ -1,7 +1,7 @@ bcr_test_module: module_path: "examples/bzlmod" matrix: - platform: ["debian10", "macos", "ubuntu2004", "windows"] + platform: ["debian11", "macos", "ubuntu2004", "windows"] tasks: run_tests: name: "Run test module" diff --git a/examples/bzlmod/requirements.in b/examples/bzlmod/requirements.in index b9c0a5b49e..069f7caf85 100644 --- a/examples/bzlmod/requirements.in +++ b/examples/bzlmod/requirements.in @@ -1,5 +1,5 @@ requests~=2.25.1 s3cmd~=2.1.0 -yamllint~=1.26.3 +yamllint>=1.28.0 tabulate~=0.9.0 pylint~=2.15.5 diff --git a/examples/bzlmod/requirements_lock.txt b/examples/bzlmod/requirements_lock.txt index 8f22f999b7..7126942665 100644 --- a/examples/bzlmod/requirements_lock.txt +++ b/examples/bzlmod/requirements_lock.txt @@ -208,8 +208,9 @@ wrapt==1.14.1 \ --hash=sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015 \ --hash=sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af # via astroid -yamllint==1.26.3 \ - --hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e +yamllint==1.28.0 \ + --hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \ + --hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b # via -r ./requirements.in # The following packages are considered to be unsafe in a requirements file: diff --git a/examples/bzlmod/requirements_windows.txt b/examples/bzlmod/requirements_windows.txt index cfd1a8d049..55fa92d544 100644 --- a/examples/bzlmod/requirements_windows.txt +++ b/examples/bzlmod/requirements_windows.txt @@ -212,8 +212,9 @@ wrapt==1.14.1 \ --hash=sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015 \ --hash=sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af # via astroid -yamllint==1.26.3 \ - --hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e +yamllint==1.28.0 \ + --hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \ + --hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b # via -r ./requirements.in # The following packages are considered to be unsafe in a requirements file: diff --git a/tests/pip_repository_entry_points/pip_repository_entry_points_test.py b/tests/pip_repository_entry_points/pip_repository_entry_points_test.py index 5be3f51ad9..914c5d9549 100644 --- a/tests/pip_repository_entry_points/pip_repository_entry_points_test.py +++ b/tests/pip_repository_entry_points/pip_repository_entry_points_test.py @@ -22,7 +22,7 @@ def test_entry_point_void_return(self): stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) - self.assertEqual(proc.stdout.decode("utf-8").strip(), "yamllint 1.26.3") + self.assertEqual(proc.stdout.decode("utf-8").strip(), "yamllint 1.28.0") # yamllint entry_point is of the form `def run(argv=None):` with self.assertRaises(subprocess.CalledProcessError) as context: diff --git a/tests/pip_repository_entry_points/requirements.in b/tests/pip_repository_entry_points/requirements.in index 220274b9b7..2cc4625577 100644 --- a/tests/pip_repository_entry_points/requirements.in +++ b/tests/pip_repository_entry_points/requirements.in @@ -1,5 +1,5 @@ sphinx==4.3.2 -yamllint==1.26.3 +yamllint>=1.28.0 # Last avialable for ubuntu python3.6 setuptools==59.6.0 diff --git a/tests/pip_repository_entry_points/requirements.txt b/tests/pip_repository_entry_points/requirements.txt index 279aed0e80..5491a4b791 100644 --- a/tests/pip_repository_entry_points/requirements.txt +++ b/tests/pip_repository_entry_points/requirements.txt @@ -202,8 +202,9 @@ urllib3==1.26.7 \ --hash=sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece \ --hash=sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844 # via requests -yamllint==1.26.3 \ - --hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e +yamllint==1.28.0 \ + --hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \ + --hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b # via -r ./requirements.in # The following packages are considered to be unsafe in a requirements file: From ce977e10f8564de6361146ff418a136f86629a86 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Thu, 1 Dec 2022 12:21:24 -0800 Subject: [PATCH 079/234] Fail if Python 2 values are specified (#887) Fail for py2 python_version, srcs_version, and runtime values. See https://github.com/bazelbuild/rules_python/issues/886 --- docs/python.md | 133 +++++++++++++++++------------------ python/defs.bzl | 2 +- python/private/reexports.bzl | 84 ++++++++++++++++++++++ 3 files changed, 148 insertions(+), 71 deletions(-) diff --git a/docs/python.md b/docs/python.md index 1726ade356..6682e48bd1 100755 --- a/docs/python.md +++ b/docs/python.md @@ -55,20 +55,73 @@ This rule allows the use of Python packages as dependencies. | srcs | The list of Python package files provided to Python targets that depend on this target. Note that currently only the .egg format is accepted. For .whl files, try the whl_library rule. We accept contributions to extend py_import to handle .whl. | List of labels | optional | [] | + + +## py_binary + +
+py_binary(attrs)
+
+ +See the Bazel core [py_binary](https://docs.bazel.build/versions/master/be/python.html#py_binary) documentation. + +**PARAMETERS** + + +| Name | Description | Default Value | +| :------------- | :------------- | :------------- | +| attrs | Rule attributes | none | + + + + +## py_library + +
+py_library(attrs)
+
+ +See the Bazel core [py_library](https://docs.bazel.build/versions/master/be/python.html#py_library) documentation. + +**PARAMETERS** + + +| Name | Description | Default Value | +| :------------- | :------------- | :------------- | +| attrs | Rule attributes | none | + + + + +## py_runtime + +
+py_runtime(attrs)
+
+ +See the Bazel core [py_runtime](https://docs.bazel.build/versions/master/be/python.html#py_runtime) documentation. + +**PARAMETERS** + + +| Name | Description | Default Value | +| :------------- | :------------- | :------------- | +| attrs | Rule attributes | none | + + ## py_runtime_pair
-py_runtime_pair(name, py2_runtime, py3_runtime)
+py_runtime_pair(name, py2_runtime, py3_runtime, attrs)
 
A toolchain rule for Python. -This wraps up to two Python runtimes, one for Python 2 and one for Python 3. -The rule consuming this toolchain will choose which runtime is appropriate. -Either runtime may be omitted, in which case the resulting toolchain will be -unusable for building Python code using that version. +This used to wrap up to two Python runtimes, one for Python 2 and one for Python 3. +However, Python 2 is no longer supported, so it now only wraps a single Python 3 +runtime. Usually the wrapped runtimes are declared using the `py_runtime` rule, but any rule returning a `PyRuntimeInfo` provider may be used. @@ -78,7 +131,7 @@ schema: ```python platform_common.ToolchainInfo( - py2_runtime = <PyRuntimeInfo or None>, + py2_runtime = None, py3_runtime = <PyRuntimeInfo or None>, ) ``` @@ -90,12 +143,6 @@ Example usage: load("@rules_python//python:defs.bzl", "py_runtime_pair") -py_runtime( - name = "my_py2_runtime", - interpreter_path = "/system/python2", - python_version = "PY2", -) - py_runtime( name = "my_py3_runtime", interpreter_path = "/system/python3", @@ -104,7 +151,6 @@ py_runtime( py_runtime_pair( name = "my_py_runtime_pair", - py2_runtime = ":my_py2_runtime", py3_runtime = ":my_py3_runtime", ) @@ -123,68 +169,15 @@ register_toolchains("//my_pkg:my_toolchain") ``` -**ATTRIBUTES** - - -| Name | Description | Type | Mandatory | Default | -| :------------- | :------------- | :------------- | :------------- | :------------- | -| name | A unique name for this target. | Name | required | | -| py2_runtime | The runtime to use for Python 2 targets. Must have python_version set to PY2. | Label | optional | None | -| py3_runtime | The runtime to use for Python 3 targets. Must have python_version set to PY3. | Label | optional | None | - - - - -## py_binary - -
-py_binary(attrs)
-
- -See the Bazel core [py_binary](https://docs.bazel.build/versions/master/be/python.html#py_binary) documentation. - **PARAMETERS** | Name | Description | Default Value | | :------------- | :------------- | :------------- | -| attrs | Rule attributes | none | - - - - -## py_library - -
-py_library(attrs)
-
- -See the Bazel core [py_library](https://docs.bazel.build/versions/master/be/python.html#py_library) documentation. - -**PARAMETERS** - - -| Name | Description | Default Value | -| :------------- | :------------- | :------------- | -| attrs | Rule attributes | none | - - - - -## py_runtime - -
-py_runtime(attrs)
-
- -See the Bazel core [py_runtime](https://docs.bazel.build/versions/master/be/python.html#py_runtime) documentation. - -**PARAMETERS** - - -| Name | Description | Default Value | -| :------------- | :------------- | :------------- | -| attrs | Rule attributes | none | +| name | str, the name of the target | none | +| py2_runtime | optional Label; must be unset or None; an error is raised otherwise. | None | +| py3_runtime | Label; a target with PyRuntimeInfo for Python 3. | None | +| attrs | Extra attrs passed onto the native rule | none | diff --git a/python/defs.bzl b/python/defs.bzl index 88f28c5fc0..7b60c6513b 100644 --- a/python/defs.bzl +++ b/python/defs.bzl @@ -17,7 +17,6 @@ Core rules for building Python projects. """ load("@bazel_tools//tools/python:srcs_version.bzl", _find_requirements = "find_requirements") -load("@bazel_tools//tools/python:toolchain.bzl", _py_runtime_pair = "py_runtime_pair") load( "//python/private:reexports.bzl", "internal_PyInfo", @@ -25,6 +24,7 @@ load( _py_binary = "py_binary", _py_library = "py_library", _py_runtime = "py_runtime", + _py_runtime_pair = "py_runtime_pair", _py_test = "py_test", ) diff --git a/python/private/reexports.bzl b/python/private/reexports.bzl index 6ad9e0cdcc..987187c155 100644 --- a/python/private/reexports.bzl +++ b/python/private/reexports.bzl @@ -37,6 +37,8 @@ different name. Then we can load it from defs.bzl and export it there under the original name. """ +load("@bazel_tools//tools/python:toolchain.bzl", _py_runtime_pair = "py_runtime_pair") + # The implementation of the macros and tagging mechanism follows the example # set by rules_cc and rules_java. @@ -64,6 +66,8 @@ def py_library(**attrs): Args: **attrs: Rule attributes """ + if attrs.get("srcs_version") in ("PY2", "PY2ONLY"): + fail("Python 2 is no longer supported: https://github.com/bazelbuild/rules_python/issues/886") # buildifier: disable=native-python native.py_library(**_add_tags(attrs)) @@ -74,6 +78,10 @@ def py_binary(**attrs): Args: **attrs: Rule attributes """ + if attrs.get("python_version") == "PY2": + fail("Python 2 is no longer supported: https://github.com/bazelbuild/rules_python/issues/886") + if attrs.get("srcs_version") in ("PY2", "PY2ONLY"): + fail("Python 2 is no longer supported: https://github.com/bazelbuild/rules_python/issues/886") # buildifier: disable=native-python native.py_binary(**_add_tags(attrs)) @@ -84,6 +92,10 @@ def py_test(**attrs): Args: **attrs: Rule attributes """ + if attrs.get("python_version") == "PY2": + fail("Python 2 is no longer supported: https://github.com/bazelbuild/rules_python/issues/886") + if attrs.get("srcs_version") in ("PY2", "PY2ONLY"): + fail("Python 2 is no longer supported: https://github.com/bazelbuild/rules_python/issues/886") # buildifier: disable=native-python native.py_test(**_add_tags(attrs)) @@ -94,6 +106,78 @@ def py_runtime(**attrs): Args: **attrs: Rule attributes """ + if attrs.get("python_version") == "PY2": + fail("Python 2 is no longer supported: see https://github.com/bazelbuild/rules_python/issues/886") # buildifier: disable=native-python native.py_runtime(**_add_tags(attrs)) + +# NOTE: This doc is copy/pasted from the builtin py_runtime_pair rule so our +# doc generator gives useful API docs. +def py_runtime_pair(name, py2_runtime = None, py3_runtime = None, **attrs): + """A toolchain rule for Python. + + This used to wrap up to two Python runtimes, one for Python 2 and one for Python 3. + However, Python 2 is no longer supported, so it now only wraps a single Python 3 + runtime. + + Usually the wrapped runtimes are declared using the `py_runtime` rule, but any + rule returning a `PyRuntimeInfo` provider may be used. + + This rule returns a `platform_common.ToolchainInfo` provider with the following + schema: + + ```python + platform_common.ToolchainInfo( + py2_runtime = None, + py3_runtime = , + ) + ``` + + Example usage: + + ```python + # In your BUILD file... + + load("@rules_python//python:defs.bzl", "py_runtime_pair") + + py_runtime( + name = "my_py3_runtime", + interpreter_path = "/system/python3", + python_version = "PY3", + ) + + py_runtime_pair( + name = "my_py_runtime_pair", + py3_runtime = ":my_py3_runtime", + ) + + toolchain( + name = "my_toolchain", + target_compatible_with = <...>, + toolchain = ":my_py_runtime_pair", + toolchain_type = "@rules_python//python:toolchain_type", + ) + ``` + + ```python + # In your WORKSPACE... + + register_toolchains("//my_pkg:my_toolchain") + ``` + + Args: + name: str, the name of the target + py2_runtime: optional Label; must be unset or None; an error is raised + otherwise. + py3_runtime: Label; a target with `PyRuntimeInfo` for Python 3. + **attrs: Extra attrs passed onto the native rule + """ + if attrs.get("py2_runtime"): + fail("PYthon 2 is no longer supported: see https://github.com/bazelbuild/rules_python/issues/886") + _py_runtime_pair( + name = name, + py2_runtime = py2_runtime, + py3_runtime = py3_runtime, + **attrs + ) From 9b47b75f3eef1f6c930647073dad059cab48f3d6 Mon Sep 17 00:00:00 2001 From: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Date: Thu, 1 Dec 2022 14:36:35 -0800 Subject: [PATCH 080/234] fix: windows on ci (#911) Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- .bazelci/presubmit.yml | 21 +- .bazelrc | 1 - tests/pip_repository_entry_points/.bazelrc | 3 + tests/pip_repository_entry_points/BUILD | 2 + tests/pip_repository_entry_points/WORKSPACE | 2 + .../pip_repository_entry_points_test.py | 8 +- .../requirements_windows.txt | 221 ++++++++++++++++++ 7 files changed, 241 insertions(+), 17 deletions(-) create mode 100644 tests/pip_repository_entry_points/requirements_windows.txt diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 349708f68e..41c75b7f6c 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -177,13 +177,8 @@ tasks: name: pip_parse_vendored integration tests on macOS working_directory: examples/pip_parse_vendored platform: macos - # TODO(f0rmiga): fix this test under Windows. It needs to be consistent on - # characters across all platforms. - # integration_test_pip_parse_vendored_windows: - # <<: *reusable_build_test_all - # name: pip_parse_vendored integration tests on Windows - # working_directory: examples/pip_parse_vendored - # platform: windows + # We don't run pip_parse_vendored under Windows as the file checked in is + # generated from a repository rule containing OS-specific rendered paths. integration_test_pip_repository_annotations_ubuntu: <<: *reusable_build_test_all @@ -242,10 +237,8 @@ tasks: name: pip_repository_entry_points integration tests on macOS working_directory: tests/pip_repository_entry_points platform: macos - # TODO(f0rmiga): fix me. The dependencies needed for this test are not cross-platform: - # https://github.com/bazelbuild/rules_python/issues/260 - # integration_test_pip_repository_entry_points_windows: - # <<: *reusable_build_test_all - # name: pip_repository_entry_points integration tests on Windows - # working_directory: tests/pip_repository_entry_points - # platform: windows + integration_test_pip_repository_entry_points_windows: + <<: *reusable_build_test_all + name: pip_repository_entry_points integration tests on Windows + working_directory: tests/pip_repository_entry_points + platform: windows diff --git a/.bazelrc b/.bazelrc index f1c7b7a210..cb17e8bf1a 100644 --- a/.bazelrc +++ b/.bazelrc @@ -18,5 +18,4 @@ build --incompatible_default_to_explicit_init_py # Windows makes use of runfiles for some rules build --enable_runfiles -# TODO(f0rmiga): remove this so that other features don't start relying on it. startup --windows_enable_symlinks diff --git a/tests/pip_repository_entry_points/.bazelrc b/tests/pip_repository_entry_points/.bazelrc index e7661cd8b8..b9c4c278fd 100644 --- a/tests/pip_repository_entry_points/.bazelrc +++ b/tests/pip_repository_entry_points/.bazelrc @@ -1,4 +1,7 @@ # Bazel configuration flags +build --enable_runfiles +startup --windows_enable_symlinks + # https://docs.bazel.build/versions/main/best-practices.html#using-the-bazelrc-file try-import %workspace%/user.bazelrc diff --git a/tests/pip_repository_entry_points/BUILD b/tests/pip_repository_entry_points/BUILD index 386a7cc886..81c01c316c 100644 --- a/tests/pip_repository_entry_points/BUILD +++ b/tests/pip_repository_entry_points/BUILD @@ -7,6 +7,7 @@ load("@rules_python//python:pip.bzl", "compile_pip_requirements") compile_pip_requirements( name = "requirements", extra_args = ["--allow-unsafe"], + requirements_windows = ":requirements_windows.txt", ) pip_parsed_sphinx = parsed_entry_point( @@ -50,4 +51,5 @@ py_test( "YAMLLINT_ENTRY_POINT": "$(rootpath {})".format(pip_installed_yamllint), }, main = "pip_repository_entry_points_test.py", + deps = ["@rules_python//python/runfiles"], ) diff --git a/tests/pip_repository_entry_points/WORKSPACE b/tests/pip_repository_entry_points/WORKSPACE index f9f3543b80..e2915b9d93 100644 --- a/tests/pip_repository_entry_points/WORKSPACE +++ b/tests/pip_repository_entry_points/WORKSPACE @@ -33,6 +33,7 @@ pip_parse( name = "pip_parsed", python_interpreter_target = interpreter, requirements_lock = "//:requirements.txt", + requirements_windows = "//:requirements_windows.txt", ) load("@pip_parsed//:requirements.bzl", install_pip_parse_deps = "install_deps") @@ -44,6 +45,7 @@ pip_install( name = "pip_installed", python_interpreter_target = interpreter, requirements = "//:requirements.txt", + requirements_windows = "//:requirements_windows.txt", ) load("@pip_installed//:requirements.bzl", install_pip_install_deps = "install_deps") diff --git a/tests/pip_repository_entry_points/pip_repository_entry_points_test.py b/tests/pip_repository_entry_points/pip_repository_entry_points_test.py index 914c5d9549..9e49ce927d 100644 --- a/tests/pip_repository_entry_points/pip_repository_entry_points_test.py +++ b/tests/pip_repository_entry_points/pip_repository_entry_points_test.py @@ -5,6 +5,8 @@ import unittest from pathlib import Path +from rules_python.python.runfiles import runfiles + class PipRepositoryEntryPointsTest(unittest.TestCase): maxDiff = None @@ -13,7 +15,8 @@ def test_entry_point_void_return(self): env = os.environ.get("YAMLLINT_ENTRY_POINT") self.assertIsNotNone(env) - entry_point = Path(env) + r = runfiles.Create() + entry_point = Path(r.Rlocation(str(Path(*Path(env).parts[1:])))) self.assertTrue(entry_point.exists()) proc = subprocess.run( @@ -38,7 +41,8 @@ def test_entry_point_int_return(self): env = os.environ.get("SPHINX_BUILD_ENTRY_POINT") self.assertIsNotNone(env) - entry_point = Path(env) + r = runfiles.Create() + entry_point = Path(r.Rlocation(str(Path(*Path(env).parts[1:])))) self.assertTrue(entry_point.exists()) proc = subprocess.run( diff --git a/tests/pip_repository_entry_points/requirements_windows.txt b/tests/pip_repository_entry_points/requirements_windows.txt new file mode 100644 index 0000000000..8522898099 --- /dev/null +++ b/tests/pip_repository_entry_points/requirements_windows.txt @@ -0,0 +1,221 @@ +# +# This file is autogenerated by pip-compile with python 3.10 +# To update, run: +# +# bazel run //:requirements.update +# +alabaster==0.7.12 \ + --hash=sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359 \ + --hash=sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02 + # via sphinx +babel==2.9.1 \ + --hash=sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9 \ + --hash=sha256:bc0c176f9f6a994582230df350aa6e05ba2ebe4b3ac317eab29d9be5d2768da0 + # via sphinx +certifi==2021.10.8 \ + --hash=sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872 \ + --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569 + # via requests +charset-normalizer==2.0.10 \ + --hash=sha256:876d180e9d7432c5d1dfd4c5d26b72f099d503e8fcc0feb7532c9289be60fcbd \ + --hash=sha256:cb957888737fc0bbcd78e3df769addb41fd1ff8cf950dc9e7ad7793f1bf44455 + # via requests +colorama==0.4.6 \ + --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ + --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 + # via sphinx +docutils==0.17.1 \ + --hash=sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125 \ + --hash=sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61 + # via sphinx +idna==3.3 \ + --hash=sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff \ + --hash=sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d + # via requests +imagesize==1.3.0 \ + --hash=sha256:1db2f82529e53c3e929e8926a1fa9235aa82d0bd0c580359c67ec31b2fddaa8c \ + --hash=sha256:cd1750d452385ca327479d45b64d9c7729ecf0b3969a58148298c77092261f9d + # via sphinx +jinja2==3.0.3 \ + --hash=sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8 \ + --hash=sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7 + # via sphinx +markupsafe==2.0.1 \ + --hash=sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298 \ + --hash=sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64 \ + --hash=sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b \ + --hash=sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194 \ + --hash=sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567 \ + --hash=sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff \ + --hash=sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724 \ + --hash=sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74 \ + --hash=sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646 \ + --hash=sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35 \ + --hash=sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6 \ + --hash=sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a \ + --hash=sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6 \ + --hash=sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad \ + --hash=sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26 \ + --hash=sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38 \ + --hash=sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac \ + --hash=sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7 \ + --hash=sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6 \ + --hash=sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047 \ + --hash=sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75 \ + --hash=sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f \ + --hash=sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b \ + --hash=sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135 \ + --hash=sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8 \ + --hash=sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a \ + --hash=sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a \ + --hash=sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1 \ + --hash=sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9 \ + --hash=sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864 \ + --hash=sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914 \ + --hash=sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee \ + --hash=sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f \ + --hash=sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18 \ + --hash=sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8 \ + --hash=sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2 \ + --hash=sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d \ + --hash=sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b \ + --hash=sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b \ + --hash=sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86 \ + --hash=sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6 \ + --hash=sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f \ + --hash=sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb \ + --hash=sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833 \ + --hash=sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28 \ + --hash=sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e \ + --hash=sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415 \ + --hash=sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902 \ + --hash=sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f \ + --hash=sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d \ + --hash=sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9 \ + --hash=sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d \ + --hash=sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145 \ + --hash=sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066 \ + --hash=sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c \ + --hash=sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1 \ + --hash=sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a \ + --hash=sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207 \ + --hash=sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f \ + --hash=sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53 \ + --hash=sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd \ + --hash=sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134 \ + --hash=sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85 \ + --hash=sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9 \ + --hash=sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5 \ + --hash=sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94 \ + --hash=sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509 \ + --hash=sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51 \ + --hash=sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872 + # via jinja2 +packaging==21.3 \ + --hash=sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb \ + --hash=sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522 + # via sphinx +pathspec==0.9.0 \ + --hash=sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a \ + --hash=sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1 + # via yamllint +pygments==2.11.2 \ + --hash=sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65 \ + --hash=sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a + # via sphinx +pyparsing==3.0.6 \ + --hash=sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4 \ + --hash=sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81 + # via packaging +pytz==2021.3 \ + --hash=sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c \ + --hash=sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326 + # via babel +pyyaml==6.0 \ + --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ + --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ + --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ + --hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b \ + --hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 \ + --hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 \ + --hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba \ + --hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 \ + --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ + --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ + --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ + --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ + --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ + --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ + --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ + --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ + --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ + --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ + --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ + --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ + --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ + --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ + --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ + --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ + --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ + --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ + --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ + --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ + --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ + --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ + --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ + --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ + --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 + # via yamllint +requests==2.27.1 \ + --hash=sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61 \ + --hash=sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d + # via sphinx +snowballstemmer==2.2.0 \ + --hash=sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1 \ + --hash=sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a + # via sphinx +sphinx==4.3.2 \ + --hash=sha256:0a8836751a68306b3fe97ecbe44db786f8479c3bf4b80e3a7f5c838657b4698c \ + --hash=sha256:6a11ea5dd0bdb197f9c2abc2e0ce73e01340464feaece525e64036546d24c851 + # via -r ./requirements.in +sphinxcontrib-applehelp==1.0.2 \ + --hash=sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a \ + --hash=sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58 + # via sphinx +sphinxcontrib-devhelp==1.0.2 \ + --hash=sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e \ + --hash=sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4 + # via sphinx +sphinxcontrib-htmlhelp==2.0.0 \ + --hash=sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07 \ + --hash=sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2 + # via sphinx +sphinxcontrib-jsmath==1.0.1 \ + --hash=sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178 \ + --hash=sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8 + # via sphinx +sphinxcontrib-qthelp==1.0.3 \ + --hash=sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72 \ + --hash=sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6 + # via sphinx +sphinxcontrib-serializinghtml==1.1.5 \ + --hash=sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd \ + --hash=sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952 + # via sphinx +urllib3==1.26.7 \ + --hash=sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece \ + --hash=sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844 + # via requests +yamllint==1.28.0 \ + --hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \ + --hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b + # via -r ./requirements.in + +# The following packages are considered to be unsafe in a requirements file: +setuptools==59.6.0 \ + --hash=sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373 \ + --hash=sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e + # via + # -r ./requirements.in + # sphinx + # yamllint From d170eb9d08274f23108569d42bdf92345c689ca8 Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius Date: Mon, 5 Dec 2022 10:51:35 +0900 Subject: [PATCH 081/234] Add gazelle distribution and enable build_file_generation test (#913) --- BUILD | 1 + examples/BUILD | 5 +++++ gazelle/BUILD.bazel | 10 ++++++++++ gazelle/manifest/BUILD.bazel | 9 +++++++++ gazelle/manifest/generate/BUILD.bazel | 6 ++++++ gazelle/manifest/test/BUILD.bazel | 6 ++++++ gazelle/modules_mapping/BUILD.bazel | 6 ++++++ gazelle/pythonconfig/BUILD.bazel | 6 ++++++ 8 files changed, 49 insertions(+) diff --git a/BUILD b/BUILD index 31962d234d..cb92935561 100644 --- a/BUILD +++ b/BUILD @@ -32,6 +32,7 @@ filegroup( "WORKSPACE", "internal_deps.bzl", "internal_setup.bzl", + "//gazelle:distribution", "//python:distribution", "//python/pip_install:distribution", "//third_party/github.com/bazelbuild/bazel-skylib/lib:distribution", diff --git a/examples/BUILD b/examples/BUILD index 39e4fce63e..4f99e2b819 100644 --- a/examples/BUILD +++ b/examples/BUILD @@ -17,6 +17,11 @@ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) # Apache 2.0 +bazel_integration_test( + name = "build_file_generation_example", + timeout = "long", +) + bazel_integration_test( name = "pip_install_example", timeout = "long", diff --git a/gazelle/BUILD.bazel b/gazelle/BUILD.bazel index c24a086a50..593831db46 100644 --- a/gazelle/BUILD.bazel +++ b/gazelle/BUILD.bazel @@ -69,3 +69,13 @@ gazelle_binary( languages = ["//gazelle"], visibility = ["//visibility:public"], ) + +filegroup( + name = "distribution", + srcs = glob(["**"]) + [ + "//gazelle/manifest:distribution", + "//gazelle/modules_mapping:distribution", + "//gazelle/pythonconfig:distribution", + ], + visibility = ["//:__pkg__"], +) diff --git a/gazelle/manifest/BUILD.bazel b/gazelle/manifest/BUILD.bazel index 281bcd29cf..a769d0d64d 100644 --- a/gazelle/manifest/BUILD.bazel +++ b/gazelle/manifest/BUILD.bazel @@ -17,3 +17,12 @@ go_test( data = glob(["testdata/**"]), deps = [":manifest"], ) + +filegroup( + name = "distribution", + srcs = glob(["**"]) + [ + "//gazelle/manifest/generate:distribution", + "//gazelle/manifest/test:distribution", + ], + visibility = ["//gazelle:__pkg__"], +) diff --git a/gazelle/manifest/generate/BUILD.bazel b/gazelle/manifest/generate/BUILD.bazel index 29b9f15628..a8b9cd562d 100644 --- a/gazelle/manifest/generate/BUILD.bazel +++ b/gazelle/manifest/generate/BUILD.bazel @@ -13,3 +13,9 @@ go_binary( embed = [":generate_lib"], visibility = ["//visibility:public"], ) + +filegroup( + name = "distribution", + srcs = glob(["**"]), + visibility = ["//gazelle/manifest:__pkg__"], +) diff --git a/gazelle/manifest/test/BUILD.bazel b/gazelle/manifest/test/BUILD.bazel index f14845f756..3f4a535957 100644 --- a/gazelle/manifest/test/BUILD.bazel +++ b/gazelle/manifest/test/BUILD.bazel @@ -15,3 +15,9 @@ go_binary( ) exports_files(["run.sh"]) + +filegroup( + name = "distribution", + srcs = glob(["**"]), + visibility = ["//gazelle/manifest:__pkg__"], +) diff --git a/gazelle/modules_mapping/BUILD.bazel b/gazelle/modules_mapping/BUILD.bazel index d1cd42e7d9..d4b35c8a45 100644 --- a/gazelle/modules_mapping/BUILD.bazel +++ b/gazelle/modules_mapping/BUILD.bazel @@ -5,3 +5,9 @@ py_binary( srcs = ["generator.py"], visibility = ["//visibility:public"], ) + +filegroup( + name = "distribution", + srcs = glob(["**"]), + visibility = ["//gazelle:__pkg__"], +) diff --git a/gazelle/pythonconfig/BUILD.bazel b/gazelle/pythonconfig/BUILD.bazel index cff75d9ee3..9472fd49f5 100644 --- a/gazelle/pythonconfig/BUILD.bazel +++ b/gazelle/pythonconfig/BUILD.bazel @@ -14,3 +14,9 @@ go_library( "@com_github_emirpasic_gods//lists/singlylinkedlist", ], ) + +filegroup( + name = "distribution", + srcs = glob(["**"]), + visibility = ["//gazelle:__pkg__"], +) From 6574e3457277aae4b523eea5896d037c640adf9a Mon Sep 17 00:00:00 2001 From: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Date: Tue, 6 Dec 2022 12:24:04 -0800 Subject: [PATCH 082/234] feat: gazelle manifest exclude_patterns (#917) * feat: exclude_patterns for gazelle manifest Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * feat: force gazelle manifest update on logic change Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- examples/build_file_generation/BUILD | 12 +++ .../build_file_generation/gazelle_python.yaml | 25 +---- .../build_file_generation/requirements.txt | 1 + .../requirements_lock.txt | 20 +++- gazelle/manifest/defs.bzl | 68 +++++++++++++- gazelle/manifest/generate/BUILD.bazel | 7 ++ gazelle/manifest/generate/generate.go | 30 +++++- gazelle/manifest/hasher/BUILD.bazel | 14 +++ gazelle/manifest/hasher/main.go | 30 ++++++ gazelle/manifest/manifest.go | 43 +++------ gazelle/manifest/manifest_test.go | 20 +++- gazelle/manifest/test/run.sh | 5 +- gazelle/manifest/test/test.go | 24 ++++- gazelle/manifest/testdata/gazelle_python.yaml | 2 +- gazelle/modules_mapping/def.bzl | 10 +- gazelle/modules_mapping/generator.py | 91 +++++++++++-------- 16 files changed, 295 insertions(+), 107 deletions(-) create mode 100644 gazelle/manifest/hasher/BUILD.bazel create mode 100644 gazelle/manifest/hasher/main.go diff --git a/examples/build_file_generation/BUILD b/examples/build_file_generation/BUILD index ef9e967d5a..9204a0ec61 100644 --- a/examples/build_file_generation/BUILD +++ b/examples/build_file_generation/BUILD @@ -4,11 +4,23 @@ load("@rules_python//gazelle:def.bzl", "GAZELLE_PYTHON_RUNTIME_DEPS") load("@rules_python//gazelle/manifest:defs.bzl", "gazelle_python_manifest") load("@rules_python//gazelle/modules_mapping:def.bzl", "modules_mapping") load("@rules_python//python:defs.bzl", "py_binary", "py_library") +load("@rules_python//python:pip.bzl", "compile_pip_requirements") + +compile_pip_requirements( + name = "requirements", + extra_args = ["--allow-unsafe"], + requirements_in = "requirements.txt", + requirements_txt = "requirements_lock.txt", +) # This rule fetches the metadata for python packages we depend on. That data is # required for the gazelle_python_manifest rule to update our manifest file. modules_mapping( name = "modules_map", + exclude_patterns = [ + "^_|(\\._)+", # This is the default. + "(\\.tests)+", # Add a custom one to get rid of the psutil tests. + ], wheels = all_whl_requirements, ) diff --git a/examples/build_file_generation/gazelle_python.yaml b/examples/build_file_generation/gazelle_python.yaml index 8e68c1ddd0..f25f59e4b2 100644 --- a/examples/build_file_generation/gazelle_python.yaml +++ b/examples/build_file_generation/gazelle_python.yaml @@ -6,18 +6,14 @@ manifest: modules_mapping: certifi: certifi - certifi.__init__: certifi - certifi.__main__: certifi certifi.core: certifi chardet: chardet - chardet.__init__: chardet chardet.big5freq: chardet chardet.big5prober: chardet chardet.chardistribution: chardet chardet.charsetgroupprober: chardet chardet.charsetprober: chardet chardet.cli: chardet - chardet.cli.__init__: chardet chardet.cli.chardetect: chardet chardet.codingstatemachine: chardet chardet.compat: chardet @@ -53,7 +49,6 @@ manifest: chardet.utf8prober: chardet chardet.version: chardet idna: idna - idna.__init__: idna idna.codec: idna idna.compat: idna idna.core: idna @@ -61,10 +56,8 @@ manifest: idna.intranges: idna idna.package_data: idna idna.uts46data: idna + psutil: psutil requests: requests - requests.__init__: requests - requests.__version__: requests - requests._internal_utils: requests requests.adapters: requests requests.api: requests requests.auth: requests @@ -81,18 +74,9 @@ manifest: requests.structures: requests requests.utils: requests urllib3: urllib3 - urllib3.__init__: urllib3 - urllib3._collections: urllib3 - urllib3._version: urllib3 urllib3.connection: urllib3 urllib3.connectionpool: urllib3 urllib3.contrib: urllib3 - urllib3.contrib.__init__: urllib3 - urllib3.contrib._appengine_environ: urllib3 - urllib3.contrib._securetransport: urllib3 - urllib3.contrib._securetransport.__init__: urllib3 - urllib3.contrib._securetransport.bindings: urllib3 - urllib3.contrib._securetransport.low_level: urllib3 urllib3.contrib.appengine: urllib3 urllib3.contrib.ntlmpool: urllib3 urllib3.contrib.pyopenssl: urllib3 @@ -102,19 +86,14 @@ manifest: urllib3.fields: urllib3 urllib3.filepost: urllib3 urllib3.packages: urllib3 - urllib3.packages.__init__: urllib3 urllib3.packages.backports: urllib3 - urllib3.packages.backports.__init__: urllib3 urllib3.packages.backports.makefile: urllib3 urllib3.packages.six: urllib3 urllib3.packages.ssl_match_hostname: urllib3 - urllib3.packages.ssl_match_hostname.__init__: urllib3 - urllib3.packages.ssl_match_hostname._implementation: urllib3 urllib3.poolmanager: urllib3 urllib3.request: urllib3 urllib3.response: urllib3 urllib3.util: urllib3 - urllib3.util.__init__: urllib3 urllib3.util.connection: urllib3 urllib3.util.proxy: urllib3 urllib3.util.queue: urllib3 @@ -129,4 +108,4 @@ manifest: pip_repository: name: pip incremental: true -integrity: 4b3eed2cb51741419e11bd12a4533f285d059fda8029deaf6fedfe0fcda1b782 +integrity: 91adaddb7e2d3eb7234e78979ff40b666101ab4df91c62659b954cc9376c2f86 diff --git a/examples/build_file_generation/requirements.txt b/examples/build_file_generation/requirements.txt index 9d84d35885..2851c1e65b 100644 --- a/examples/build_file_generation/requirements.txt +++ b/examples/build_file_generation/requirements.txt @@ -1 +1,2 @@ requests==2.25.1 +psutil==5.9.4 diff --git a/examples/build_file_generation/requirements_lock.txt b/examples/build_file_generation/requirements_lock.txt index b66c41fef9..07ff2eccc4 100644 --- a/examples/build_file_generation/requirements_lock.txt +++ b/examples/build_file_generation/requirements_lock.txt @@ -2,7 +2,7 @@ # This file is autogenerated by pip-compile with python 3.9 # To update, run: # -# pip-compile --generate-hashes --output-file=requirements_lock.txt requirements.txt +# bazel run //:requirements.update # certifi==2020.12.5 \ --hash=sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c \ @@ -16,10 +16,26 @@ idna==2.10 \ --hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 \ --hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0 # via requests +psutil==5.9.4 \ + --hash=sha256:149555f59a69b33f056ba1c4eb22bb7bf24332ce631c44a319cec09f876aaeff \ + --hash=sha256:16653106f3b59386ffe10e0bad3bb6299e169d5327d3f187614b1cb8f24cf2e1 \ + --hash=sha256:3d7f9739eb435d4b1338944abe23f49584bde5395f27487d2ee25ad9a8774a62 \ + --hash=sha256:3ff89f9b835100a825b14c2808a106b6fdcc4b15483141482a12c725e7f78549 \ + --hash=sha256:54c0d3d8e0078b7666984e11b12b88af2db11d11249a8ac8920dd5ef68a66e08 \ + --hash=sha256:54d5b184728298f2ca8567bf83c422b706200bcbbfafdc06718264f9393cfeb7 \ + --hash=sha256:6001c809253a29599bc0dfd5179d9f8a5779f9dffea1da0f13c53ee568115e1e \ + --hash=sha256:68908971daf802203f3d37e78d3f8831b6d1014864d7a85937941bb35f09aefe \ + --hash=sha256:6b92c532979bafc2df23ddc785ed116fced1f492ad90a6830cf24f4d1ea27d24 \ + --hash=sha256:852dd5d9f8a47169fe62fd4a971aa07859476c2ba22c2254d4a1baa4e10b95ad \ + --hash=sha256:9120cd39dca5c5e1c54b59a41d205023d436799b1c8c4d3ff71af18535728e94 \ + --hash=sha256:c1ca331af862803a42677c120aff8a814a804e09832f166f226bfd22b56feee8 \ + --hash=sha256:efeae04f9516907be44904cc7ce08defb6b665128992a56957abc9b61dca94b7 \ + --hash=sha256:fd8522436a6ada7b4aad6638662966de0d61d241cb821239b2ae7013d41a43d4 + # via -r ./requirements.txt requests==2.25.1 \ --hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \ --hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e - # via -r requirements.txt + # via -r ./requirements.txt urllib3==1.26.5 \ --hash=sha256:753a0374df26658f99d826cfe40394a686d05985786d946fbe4165b5148f5a7c \ --hash=sha256:a7acd0977125325f516bda9735fa7142b909a8d01e8b2e4c8108d0984e6e0098 diff --git a/gazelle/manifest/defs.bzl b/gazelle/manifest/defs.bzl index 8439319238..a5bbe56353 100644 --- a/gazelle/manifest/defs.bzl +++ b/gazelle/manifest/defs.bzl @@ -2,7 +2,7 @@ for updating and testing the Gazelle manifest file. """ -load("@io_bazel_rules_go//go:def.bzl", "go_binary") +load("@io_bazel_rules_go//go:def.bzl", "GoSource", "go_binary") def gazelle_python_manifest( name, @@ -38,7 +38,11 @@ def gazelle_python_manifest( update_target = "{}.update".format(name) update_target_label = "//{}:{}".format(native.package_name(), update_target) + manifest_generator_hash = Label("//gazelle/manifest/generate:generate_lib_sources_hash") + update_args = [ + "--manifest-generator-hash", + "$(rootpath {})".format(manifest_generator_hash), "--requirements", "$(rootpath {})".format(requirements), "--pip-repository-name", @@ -55,11 +59,12 @@ def gazelle_python_manifest( go_binary( name = update_target, - embed = ["@rules_python//gazelle/manifest/generate:generate_lib"], + embed = [Label("//gazelle/manifest/generate:generate_lib")], data = [ manifest, modules_mapping, requirements, + manifest_generator_hash, ], args = update_args, visibility = ["//visibility:private"], @@ -70,21 +75,23 @@ def gazelle_python_manifest( go_binary( name = test_binary, - embed = ["@rules_python//gazelle/manifest/test:test_lib"], + embed = [Label("//gazelle/manifest/test:test_lib")], visibility = ["//visibility:private"], ) native.sh_test( name = "{}.test".format(name), - srcs = ["@rules_python//gazelle/manifest/test:run.sh"], + srcs = [Label("//gazelle/manifest/test:run.sh")], data = [ ":{}".format(test_binary), manifest, requirements, + manifest_generator_hash, ], env = { "_TEST_BINARY": "$(rootpath :{})".format(test_binary), "_TEST_MANIFEST": "$(rootpath {})".format(manifest), + "_TEST_MANIFEST_GENERATOR_HASH": "$(rootpath {})".format(manifest_generator_hash), "_TEST_REQUIREMENTS": "$(rootpath {})".format(requirements), }, visibility = ["//visibility:private"], @@ -97,3 +104,56 @@ def gazelle_python_manifest( tags = ["manual"], visibility = ["//visibility:public"], ) + +# buildifier: disable=provider-params +AllSourcesInfo = provider(fields = {"all_srcs": "All sources collected from the target and dependencies."}) + +_rules_python_workspace = Label("//:WORKSPACE") + +def _get_all_sources_impl(target, ctx): + is_rules_python = target.label.workspace_name == _rules_python_workspace.workspace_name + if not is_rules_python: + # Avoid adding third-party dependency files to the checksum of the srcs. + return AllSourcesInfo(all_srcs = depset()) + srcs = depset( + target[GoSource].orig_srcs, + transitive = [dep[AllSourcesInfo].all_srcs for dep in ctx.rule.attr.deps], + ) + return [AllSourcesInfo(all_srcs = srcs)] + +_get_all_sources = aspect( + implementation = _get_all_sources_impl, + attr_aspects = ["deps"], +) + +def _sources_hash_impl(ctx): + all_srcs = ctx.attr.go_library[AllSourcesInfo].all_srcs + hash_file = ctx.actions.declare_file(ctx.attr.name + ".hash") + args = ctx.actions.args() + args.add(hash_file) + args.add_all(all_srcs) + ctx.actions.run( + outputs = [hash_file], + inputs = all_srcs, + arguments = [args], + executable = ctx.executable._hasher, + ) + return [DefaultInfo( + files = depset([hash_file]), + runfiles = ctx.runfiles([hash_file]), + )] + +sources_hash = rule( + _sources_hash_impl, + attrs = { + "go_library": attr.label( + aspects = [_get_all_sources], + providers = [GoSource], + ), + "_hasher": attr.label( + cfg = "exec", + default = Label("//gazelle/manifest/hasher"), + executable = True, + ), + }, +) diff --git a/gazelle/manifest/generate/BUILD.bazel b/gazelle/manifest/generate/BUILD.bazel index a8b9cd562d..7a5d27ff24 100644 --- a/gazelle/manifest/generate/BUILD.bazel +++ b/gazelle/manifest/generate/BUILD.bazel @@ -1,4 +1,5 @@ load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") +load("//gazelle/manifest:defs.bzl", "sources_hash") go_library( name = "generate_lib", @@ -8,6 +9,12 @@ go_library( deps = ["//gazelle/manifest"], ) +sources_hash( + name = "generate_lib_sources_hash", + go_library = ":generate_lib", + visibility = ["//visibility:public"], +) + go_binary( name = "generate", embed = [":generate_lib"], diff --git a/gazelle/manifest/generate/generate.go b/gazelle/manifest/generate/generate.go index 04d7441fd2..54e88132e6 100644 --- a/gazelle/manifest/generate/generate.go +++ b/gazelle/manifest/generate/generate.go @@ -24,12 +24,19 @@ func init() { } func main() { + var manifestGeneratorHashPath string var requirementsPath string var pipRepositoryName string var pipRepositoryIncremental bool var modulesMappingPath string var outputPath string var updateTarget string + flag.StringVar( + &manifestGeneratorHashPath, + "manifest-generator-hash", + "", + "The file containing the hash for the source code of the manifest generator."+ + "This is important to force manifest updates when the generator logic changes.") flag.StringVar( &requirementsPath, "requirements", @@ -92,7 +99,13 @@ func main() { Incremental: pipRepositoryIncremental, }, }) - if err := writeOutput(outputPath, header, manifestFile, requirementsPath); err != nil { + if err := writeOutput( + outputPath, + header, + manifestFile, + manifestGeneratorHashPath, + requirementsPath, + ); err != nil { log.Fatalf("ERROR: %v\n", err) } } @@ -129,6 +142,7 @@ func writeOutput( outputPath string, header string, manifestFile *manifest.File, + manifestGeneratorHashPath string, requirementsPath string, ) error { stat, err := os.Stat(outputPath) @@ -146,7 +160,19 @@ func writeOutput( return fmt.Errorf("failed to write output: %w", err) } - if err := manifestFile.Encode(outputFile, requirementsPath); err != nil { + manifestGeneratorHash, err := os.Open(manifestGeneratorHashPath) + if err != nil { + return fmt.Errorf("failed to write output: %w", err) + } + defer manifestGeneratorHash.Close() + + requirements, err := os.Open(requirementsPath) + if err != nil { + return fmt.Errorf("failed to write output: %w", err) + } + defer requirements.Close() + + if err := manifestFile.Encode(outputFile, manifestGeneratorHash, requirements); err != nil { return fmt.Errorf("failed to write output: %w", err) } diff --git a/gazelle/manifest/hasher/BUILD.bazel b/gazelle/manifest/hasher/BUILD.bazel new file mode 100644 index 0000000000..5e67b2f549 --- /dev/null +++ b/gazelle/manifest/hasher/BUILD.bazel @@ -0,0 +1,14 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "hasher_lib", + srcs = ["main.go"], + importpath = "github.com/bazelbuild/rules_python/gazelle/manifest/hasher", + visibility = ["//visibility:private"], +) + +go_binary( + name = "hasher", + embed = [":hasher_lib"], + visibility = ["//visibility:public"], +) diff --git a/gazelle/manifest/hasher/main.go b/gazelle/manifest/hasher/main.go new file mode 100644 index 0000000000..6e8833572b --- /dev/null +++ b/gazelle/manifest/hasher/main.go @@ -0,0 +1,30 @@ +package main + +import ( + "crypto/sha256" + "io" + "log" + "os" +) + +func main() { + h := sha256.New() + out, err := os.Create(os.Args[1]) + if err != nil { + log.Fatal(err) + } + defer out.Close() + for _, filename := range os.Args[2:] { + f, err := os.Open(filename) + if err != nil { + log.Fatal(err) + } + defer f.Close() + if _, err := io.Copy(h, f); err != nil { + log.Fatal(err) + } + } + if _, err := out.Write(h.Sum(nil)); err != nil { + log.Fatal(err) + } +} diff --git a/gazelle/manifest/manifest.go b/gazelle/manifest/manifest.go index e19162bd5d..640effc8c7 100644 --- a/gazelle/manifest/manifest.go +++ b/gazelle/manifest/manifest.go @@ -26,12 +26,8 @@ func NewFile(manifest *Manifest) *File { } // Encode encodes the manifest file to the given writer. -func (f *File) Encode(w io.Writer, requirementsPath string) error { - requirementsChecksum, err := sha256File(requirementsPath) - if err != nil { - return fmt.Errorf("failed to encode manifest file: %w", err) - } - integrityBytes, err := f.calculateIntegrity(requirementsChecksum) +func (f *File) Encode(w io.Writer, manifestGeneratorHashFile, requirements io.Reader) error { + integrityBytes, err := f.calculateIntegrity(manifestGeneratorHashFile, requirements) if err != nil { return fmt.Errorf("failed to encode manifest file: %w", err) } @@ -45,12 +41,8 @@ func (f *File) Encode(w io.Writer, requirementsPath string) error { } // VerifyIntegrity verifies if the integrity set in the File is valid. -func (f *File) VerifyIntegrity(requirementsPath string) (bool, error) { - requirementsChecksum, err := sha256File(requirementsPath) - if err != nil { - return false, fmt.Errorf("failed to verify integrity: %w", err) - } - integrityBytes, err := f.calculateIntegrity(requirementsChecksum) +func (f *File) VerifyIntegrity(manifestGeneratorHashFile, requirements io.Reader) (bool, error) { + integrityBytes, err := f.calculateIntegrity(manifestGeneratorHashFile, requirements) if err != nil { return false, fmt.Errorf("failed to verify integrity: %w", err) } @@ -62,7 +54,9 @@ func (f *File) VerifyIntegrity(requirementsPath string) (bool, error) { // provided checksum for the requirements.txt file used as input to the modules // mapping, plus the manifest structure in the manifest file. This integrity // calculation ensures the manifest files are kept up-to-date. -func (f *File) calculateIntegrity(requirementsChecksum []byte) ([]byte, error) { +func (f *File) calculateIntegrity( + manifestGeneratorHash, requirements io.Reader, +) ([]byte, error) { hash := sha256.New() // Sum the manifest part of the file. @@ -72,8 +66,13 @@ func (f *File) calculateIntegrity(requirementsChecksum []byte) ([]byte, error) { return nil, fmt.Errorf("failed to calculate integrity: %w", err) } + // Sum the manifest generator checksum bytes. + if _, err := io.Copy(hash, manifestGeneratorHash); err != nil { + return nil, fmt.Errorf("failed to calculate integrity: %w", err) + } + // Sum the requirements.txt checksum bytes. - if _, err := hash.Write(requirementsChecksum); err != nil { + if _, err := io.Copy(hash, requirements); err != nil { return nil, fmt.Errorf("failed to calculate integrity: %w", err) } @@ -134,19 +133,3 @@ type PipRepository struct { // The incremental property of pip_repository. Incremental bool } - -// sha256File calculates the checksum of a given file path. -func sha256File(filePath string) ([]byte, error) { - file, err := os.Open(filePath) - if err != nil { - return nil, fmt.Errorf("failed to calculate sha256 sum for file: %w", err) - } - defer file.Close() - - hash := sha256.New() - if _, err := io.Copy(hash, file); err != nil { - return nil, fmt.Errorf("failed to calculate sha256 sum for file: %w", err) - } - - return hash.Sum(nil), nil -} diff --git a/gazelle/manifest/manifest_test.go b/gazelle/manifest/manifest_test.go index 3b50fd1b3e..174d999a43 100644 --- a/gazelle/manifest/manifest_test.go +++ b/gazelle/manifest/manifest_test.go @@ -4,7 +4,9 @@ import ( "bytes" "io/ioutil" "log" + "os" "reflect" + "strings" "testing" "github.com/bazelbuild/rules_python/gazelle/manifest" @@ -31,7 +33,14 @@ func TestFile(t *testing.T) { PipDepsRepositoryName: pipDepsRepositoryName, }) var b bytes.Buffer - if err := f.Encode(&b, "testdata/requirements.txt"); err != nil { + manifestGeneratorHashFile := strings.NewReader("") + requirements, err := os.Open("testdata/requirements.txt") + if err != nil { + log.Println(err) + t.FailNow() + } + defer requirements.Close() + if err := f.Encode(&b, manifestGeneratorHashFile, requirements); err != nil { log.Println(err) t.FailNow() } @@ -66,7 +75,14 @@ func TestFile(t *testing.T) { log.Println(err) t.FailNow() } - valid, err := f.VerifyIntegrity("testdata/requirements.txt") + manifestGeneratorHashFile := strings.NewReader("") + requirements, err := os.Open("testdata/requirements.txt") + if err != nil { + log.Println(err) + t.FailNow() + } + defer requirements.Close() + valid, err := f.VerifyIntegrity(manifestGeneratorHashFile, requirements) if err != nil { log.Println(err) t.FailNow() diff --git a/gazelle/manifest/test/run.sh b/gazelle/manifest/test/run.sh index 4b24b51ae4..524e9b5dd5 100755 --- a/gazelle/manifest/test/run.sh +++ b/gazelle/manifest/test/run.sh @@ -5,4 +5,7 @@ set -o errexit -o nounset -"${_TEST_BINARY}" --requirements "${_TEST_REQUIREMENTS}" --manifest "${_TEST_MANIFEST}" \ No newline at end of file +"${_TEST_BINARY}" \ + --manifest-generator-hash "${_TEST_MANIFEST_GENERATOR_HASH}" \ + --requirements "${_TEST_REQUIREMENTS}" \ + --manifest "${_TEST_MANIFEST}" diff --git a/gazelle/manifest/test/test.go b/gazelle/manifest/test/test.go index 518fe06eb6..8b580b14fc 100644 --- a/gazelle/manifest/test/test.go +++ b/gazelle/manifest/test/test.go @@ -10,14 +10,22 @@ package main import ( "flag" "log" + "os" "path/filepath" "github.com/bazelbuild/rules_python/gazelle/manifest" ) func main() { + var manifestGeneratorHashPath string var requirementsPath string var manifestPath string + flag.StringVar( + &manifestGeneratorHashPath, + "manifest-generator-hash", + "", + "The file containing the hash for the source code of the manifest generator."+ + "This is important to force manifest updates when the generator logic changes.") flag.StringVar( &requirementsPath, "requirements", @@ -47,7 +55,19 @@ func main() { log.Fatalln("ERROR: failed to find the Gazelle manifest file integrity") } - valid, err := manifestFile.VerifyIntegrity(requirementsPath) + manifestGeneratorHash, err := os.Open(manifestGeneratorHashPath) + if err != nil { + log.Fatalf("ERROR: %v\n", err) + } + defer manifestGeneratorHash.Close() + + requirements, err := os.Open(requirementsPath) + if err != nil { + log.Fatalf("ERROR: %v\n", err) + } + defer requirements.Close() + + valid, err := manifestFile.VerifyIntegrity(manifestGeneratorHash, requirements) if err != nil { log.Fatalf("ERROR: %v\n", err) } @@ -60,4 +80,4 @@ func main() { "ERROR: %q is out-of-date, follow the intructions on this file for updating.\n", manifestRealpath) } -} \ No newline at end of file +} diff --git a/gazelle/manifest/testdata/gazelle_python.yaml b/gazelle/manifest/testdata/gazelle_python.yaml index 4dc1f2c545..70f7aff19a 100644 --- a/gazelle/manifest/testdata/gazelle_python.yaml +++ b/gazelle/manifest/testdata/gazelle_python.yaml @@ -10,4 +10,4 @@ manifest: arrow.parser: arrow arrow.util: arrow pip_deps_repository_name: test_repository_name -integrity: 624f5f6c078eb44b907efd5a64e308354ac3620c568232b815668bcdf3e3366a +integrity: eedf187f8b7ec27cdfc682feee4206e063b51d13d78f77c05d3a30ec11bd7411 diff --git a/gazelle/modules_mapping/def.bzl b/gazelle/modules_mapping/def.bzl index 04ea50facd..9b1352c5e4 100644 --- a/gazelle/modules_mapping/def.bzl +++ b/gazelle/modules_mapping/def.bzl @@ -12,8 +12,9 @@ module name doesn't match the wheel distribution name. def _modules_mapping_impl(ctx): modules_mapping = ctx.actions.declare_file(ctx.attr.modules_mapping_name) args = ctx.actions.args() - args.add(modules_mapping.path) - args.add_all([whl.path for whl in ctx.files.wheels]) + args.add("--output_file", modules_mapping.path) + args.add_all("--exclude_patterns", ctx.attr.exclude_patterns) + args.add_all("--wheels", [whl.path for whl in ctx.files.wheels]) ctx.actions.run( inputs = ctx.files.wheels, outputs = [modules_mapping], @@ -26,6 +27,11 @@ def _modules_mapping_impl(ctx): modules_mapping = rule( _modules_mapping_impl, attrs = { + "exclude_patterns": attr.string_list( + default = ["^_|(\\._)+"], + doc = "A set of regex patterns to match against each calculated module path. By default, exclude the modules starting with underscores.", + mandatory = False, + ), "modules_mapping_name": attr.string( default = "modules_mapping.json", doc = "The name for the output JSON file.", diff --git a/gazelle/modules_mapping/generator.py b/gazelle/modules_mapping/generator.py index ec3133af0e..51b81e7487 100644 --- a/gazelle/modules_mapping/generator.py +++ b/gazelle/modules_mapping/generator.py @@ -1,5 +1,7 @@ +import argparse import json import pathlib +import re import sys import zipfile @@ -8,36 +10,69 @@ class Generator: stderr = None output_file = None + excluded_patterns = None + mapping = {} - def __init__(self, stderr, output_file): + def __init__(self, stderr, output_file, excluded_patterns): self.stderr = stderr self.output_file = output_file + self.excluded_patterns = [re.compile(pattern) for pattern in excluded_patterns] # dig_wheel analyses the wheel .whl file determining the modules it provides # by looking at the directory structure. def dig_wheel(self, whl): - mapping = {} with zipfile.ZipFile(whl, "r") as zip_file: for path in zip_file.namelist(): if is_metadata(path): if data_has_purelib_or_platlib(path): - module_for_path(path, whl, mapping) + self.module_for_path(path, whl) else: continue else: - module_for_path(path, whl, mapping) - return mapping + self.module_for_path(path, whl) + + def module_for_path(self, path, whl): + ext = pathlib.Path(path).suffix + if ext == ".py" or ext == ".so": + if "purelib" in path or "platlib" in path: + root = "/".join(path.split("/")[2:]) + else: + root = path + + wheel_name = get_wheel_name(whl) + + if root.endswith("/__init__.py"): + # Note the '/' here means that the __init__.py is not in the + # root of the wheel, therefore we can index the directory + # where this file is as an importable package. + module = root[: -len("/__init__.py")].replace("/", ".") + if not self.is_excluded(module): + self.mapping[module] = wheel_name + + # Always index the module file. + if ext == ".so": + # Also remove extra metadata that is embeded as part of + # the file name as an extra extension. + ext = "".join(pathlib.Path(root).suffixes) + module = root[: -len(ext)].replace("/", ".") + if not self.is_excluded(module): + self.mapping[module] = wheel_name + + def is_excluded(self, module): + for pattern in self.excluded_patterns: + if pattern.search(module): + return True + return False # run is the entrypoint for the generator. def run(self, wheels): - mapping = {} for whl in wheels: try: - mapping.update(self.dig_wheel(whl)) + self.dig_wheel(whl) except AssertionError as error: print(error, file=self.stderr) return 1 - mapping_json = json.dumps(mapping) + mapping_json = json.dumps(self.mapping) with open(self.output_file, "w") as f: f.write(mapping_json) return 0 @@ -71,34 +106,14 @@ def data_has_purelib_or_platlib(path): return is_metadata(path) and (maybe_lib == "purelib" or maybe_lib == "platlib") -def module_for_path(path, whl, mapping): - ext = pathlib.Path(path).suffix - if ext == ".py" or ext == ".so": - if "purelib" in path or "platlib" in path: - root = "/".join(path.split("/")[2:]) - else: - root = path - - wheel_name = get_wheel_name(whl) - - if root.endswith("/__init__.py"): - # Note the '/' here means that the __init__.py is not in the - # root of the wheel, therefore we can index the directory - # where this file is as an importable package. - module = root[: -len("/__init__.py")].replace("/", ".") - mapping[module] = wheel_name - - # Always index the module file. - if ext == ".so": - # Also remove extra metadata that is embeded as part of - # the file name as an extra extension. - ext = "".join(pathlib.Path(root).suffixes) - module = root[: -len(ext)].replace("/", ".") - mapping[module] = wheel_name - - if __name__ == "__main__": - output_file = sys.argv[1] - wheels = sys.argv[2:] - generator = Generator(sys.stderr, output_file) - exit(generator.run(wheels)) + parser = argparse.ArgumentParser( + prog="generator", + description="Generates the modules mapping used by the Gazelle manifest.", + ) + parser.add_argument("--output_file", type=str) + parser.add_argument("--exclude_patterns", nargs="+", default=[]) + parser.add_argument("--wheels", nargs="+", default=[]) + args = parser.parse_args() + generator = Generator(sys.stderr, args.output_file, args.exclude_patterns) + exit(generator.run(args.wheels)) From 9fc69da56421dbf803a4a229e8492b0a3e48b680 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Tue, 6 Dec 2022 13:41:28 -0800 Subject: [PATCH 083/234] Add f0rmiga as codeowner of build_file_example (#918) --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 54374b30ad..3449bcfac0 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,6 +4,7 @@ # Directory containing the Gazelle extension and Go code. /gazelle/ @f0rmiga +/examples/build_file_generation/ @f0rmiga # Toolchains /python/repositories.bzl @f0rmiga From 9bf7c49ea1920e497f857ccc1e9c2d1189c8a1c9 Mon Sep 17 00:00:00 2001 From: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Date: Tue, 6 Dec 2022 13:55:53 -0800 Subject: [PATCH 084/234] fix: don't test on release (#920) Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- .github/workflows/ci.bazelrc | 8 -------- .github/workflows/release.yml | 5 ----- 2 files changed, 13 deletions(-) delete mode 100644 .github/workflows/ci.bazelrc diff --git a/.github/workflows/ci.bazelrc b/.github/workflows/ci.bazelrc deleted file mode 100644 index bd2d20b46d..0000000000 --- a/.github/workflows/ci.bazelrc +++ /dev/null @@ -1,8 +0,0 @@ -# Bazel settings to apply on CI only -# Included with a --bazelrc option in the call to bazel -build --announce_rc -test --test_output=errors -build --disk_cache=$HOME/.cache/bazel -build --repository_cache=$HOME/.cache/bazel-repo -# For bazel-in-bazel testing -test --test_env=XDG_CACHE_HOME diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b6bba429bb..a675fe1562 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,11 +12,6 @@ jobs: steps: - name: Checkout uses: actions/checkout@v2 - - name: bazel test //... - env: - # Bazelisk will download bazel to here - XDG_CACHE_HOME: ~/.cache/bazel-repo - run: bazel --bazelrc=.github/workflows/ci.bazelrc --bazelrc=.bazelrc test //... - name: Prepare workspace snippet run: .github/workflows/workspace_snippet.sh ${{ env.GITHUB_REF_NAME }} > release_notes.txt - name: Release From 45280380d22e7eaf136b290fd3e7c01d757fa8d1 Mon Sep 17 00:00:00 2001 From: stdll00 <16006732+stdll00@users.noreply.github.com> Date: Wed, 7 Dec 2022 10:05:13 +0900 Subject: [PATCH 085/234] fix: gazelle panics when "# gazelle:ignore" doesn't have a value (#915) * add panic case * fix: return nil if invalid annotation is provided instead of panic * fix after review * Update gazelle/parser.go Co-authored-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * Update gazelle/testdata/invalid_annotation/test.yaml Co-authored-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Co-authored-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- gazelle/parser.go | 23 +++++++++++++------ gazelle/testdata/invalid_annotation/BUILD.in | 0 gazelle/testdata/invalid_annotation/BUILD.out | 0 gazelle/testdata/invalid_annotation/README.md | 2 ++ gazelle/testdata/invalid_annotation/WORKSPACE | 1 + .../testdata/invalid_annotation/__init__.py | 1 + gazelle/testdata/invalid_annotation/test.yaml | 5 ++++ 7 files changed, 25 insertions(+), 7 deletions(-) create mode 100644 gazelle/testdata/invalid_annotation/BUILD.in create mode 100644 gazelle/testdata/invalid_annotation/BUILD.out create mode 100644 gazelle/testdata/invalid_annotation/README.md create mode 100644 gazelle/testdata/invalid_annotation/WORKSPACE create mode 100644 gazelle/testdata/invalid_annotation/__init__.py create mode 100644 gazelle/testdata/invalid_annotation/test.yaml diff --git a/gazelle/parser.go b/gazelle/parser.go index d287caf233..6158d38ecf 100644 --- a/gazelle/parser.go +++ b/gazelle/parser.go @@ -128,7 +128,10 @@ func (p *python3Parser) parse(pyFilenames *treeset.Set) (*treeset.Set, error) { } for _, res := range allRes { - annotations := annotationsFromComments(res.Comments) + annotations, err := annotationsFromComments(res.Comments) + if err != nil { + return nil, fmt.Errorf("failed to parse annotations: %w", err) + } for _, m := range res.Modules { // Check for ignored dependencies set via an annotation to the Python @@ -195,17 +198,20 @@ type comment string // asAnnotation returns an annotation object if the comment has the // annotationPrefix. -func (c *comment) asAnnotation() *annotation { +func (c *comment) asAnnotation() (*annotation, error) { uncomment := strings.TrimLeft(string(*c), "# ") if !strings.HasPrefix(uncomment, annotationPrefix) { - return nil + return nil, nil } withoutPrefix := strings.TrimPrefix(uncomment, annotationPrefix) annotationParts := strings.SplitN(withoutPrefix, " ", 2) + if len(annotationParts) < 2 { + return nil, fmt.Errorf("`%s` requires a value", *c) + } return &annotation{ kind: annotationKind(annotationParts[0]), value: annotationParts[1], - } + }, nil } // annotation represents a single Gazelle annotation parsed from a Python @@ -224,10 +230,13 @@ type annotations struct { // annotationsFromComments returns all the annotations parsed out of the // comments of a Python module. -func annotationsFromComments(comments []comment) *annotations { +func annotationsFromComments(comments []comment) (*annotations, error) { ignore := make(map[string]struct{}) for _, comment := range comments { - annotation := comment.asAnnotation() + annotation, err := comment.asAnnotation() + if err != nil { + return nil, err + } if annotation != nil { if annotation.kind == annotationKindIgnore { modules := strings.Split(annotation.value, ",") @@ -243,7 +252,7 @@ func annotationsFromComments(comments []comment) *annotations { } return &annotations{ ignore: ignore, - } + }, nil } // ignored returns true if the given module was ignored via the ignore diff --git a/gazelle/testdata/invalid_annotation/BUILD.in b/gazelle/testdata/invalid_annotation/BUILD.in new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/testdata/invalid_annotation/BUILD.out b/gazelle/testdata/invalid_annotation/BUILD.out new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/testdata/invalid_annotation/README.md b/gazelle/testdata/invalid_annotation/README.md new file mode 100644 index 0000000000..b2544b5bda --- /dev/null +++ b/gazelle/testdata/invalid_annotation/README.md @@ -0,0 +1,2 @@ +# Invalid annotation +This test case asserts that the parse step fails as expected due to invalid annotation format. diff --git a/gazelle/testdata/invalid_annotation/WORKSPACE b/gazelle/testdata/invalid_annotation/WORKSPACE new file mode 100644 index 0000000000..faff6af87a --- /dev/null +++ b/gazelle/testdata/invalid_annotation/WORKSPACE @@ -0,0 +1 @@ +# This is a Bazel workspace for the Gazelle test data. diff --git a/gazelle/testdata/invalid_annotation/__init__.py b/gazelle/testdata/invalid_annotation/__init__.py new file mode 100644 index 0000000000..9968c4af55 --- /dev/null +++ b/gazelle/testdata/invalid_annotation/__init__.py @@ -0,0 +1 @@ +# gazelle:ignore diff --git a/gazelle/testdata/invalid_annotation/test.yaml b/gazelle/testdata/invalid_annotation/test.yaml new file mode 100644 index 0000000000..5e6170b626 --- /dev/null +++ b/gazelle/testdata/invalid_annotation/test.yaml @@ -0,0 +1,5 @@ +--- +expect: + exit_code: 1 + stderr: | + gazelle: ERROR: failed to parse annotations: `# gazelle:ignore` requires a value From 222ec4b98bc5e3a9f0b20f90eb632176f304a8f8 Mon Sep 17 00:00:00 2001 From: Greg Roodt Date: Tue, 20 Dec 2022 08:59:06 +1100 Subject: [PATCH 086/234] Remove unused code (#933) --- python/pip_install/extract_wheels/BUILD | 11 ---- python/pip_install/extract_wheels/bazel.py | 57 ------------------- .../extract_wheels/requirements_bzl_test.py | 19 ------- 3 files changed, 87 deletions(-) delete mode 100644 python/pip_install/extract_wheels/requirements_bzl_test.py diff --git a/python/pip_install/extract_wheels/BUILD b/python/pip_install/extract_wheels/BUILD index bc11885026..1420f4be80 100644 --- a/python/pip_install/extract_wheels/BUILD +++ b/python/pip_install/extract_wheels/BUILD @@ -148,17 +148,6 @@ py_test( ], ) -py_test( - name = "requirements_bzl_test", - size = "small", - srcs = [ - "requirements_bzl_test.py", - ], - deps = [ - ":lib", - ], -) - filegroup( name = "distribution", srcs = glob( diff --git a/python/pip_install/extract_wheels/bazel.py b/python/pip_install/extract_wheels/bazel.py index 8f442c930f..28a229277d 100644 --- a/python/pip_install/extract_wheels/bazel.py +++ b/python/pip_install/extract_wheels/bazel.py @@ -201,63 +201,6 @@ def generate_build_file_contents( ) -def generate_requirements_file_contents(repo_name: str, targets: Iterable[str]) -> str: - """Generate a requirements.bzl file for a given pip repository - - The file allows converting the PyPI name to a bazel label. Additionally, it adds a function which can glob all the - installed dependencies. - - Args: - repo_name: the name of the pip repository - targets: a list of Bazel labels pointing to all the generated targets - - Returns: - A complete requirements.bzl file as a string - """ - - sorted_targets = sorted(targets) - requirement_labels = ",".join(sorted_targets) - whl_requirement_labels = ",".join( - '"{}:whl"'.format(target.strip('"')) for target in sorted_targets - ) - return textwrap.dedent( - """\ - all_requirements = [{requirement_labels}] - - all_whl_requirements = [{whl_requirement_labels}] - - def requirement(name): - name_key = name.replace("-", "_").replace(".", "_").lower() - return "{repo}//pypi__" + name_key - - def whl_requirement(name): - return requirement(name) + ":{whl_file_label}" - - def data_requirement(name): - return requirement(name) + ":{data_label}" - - def dist_info_requirement(name): - return requirement(name) + ":{dist_info_label}" - - def entry_point(pkg, script = None): - if not script: - script = pkg - return requirement(pkg) + ":{entry_point_prefix}_" + script - - def install_deps(): - fail("install_deps() only works if you are creating an incremental repo. Did you mean to use pip_parse()?") - """.format( - repo=repo_name, - requirement_labels=requirement_labels, - whl_requirement_labels=whl_requirement_labels, - whl_file_label=WHEEL_FILE_LABEL, - data_label=DATA_LABEL, - dist_info_label=DIST_INFO_LABEL, - entry_point_prefix=WHEEL_ENTRY_POINT_PREFIX, - ) - ) - - def sanitise_name(name: str, prefix: str) -> str: """Sanitises the name to be compatible with Bazel labels. diff --git a/python/pip_install/extract_wheels/requirements_bzl_test.py b/python/pip_install/extract_wheels/requirements_bzl_test.py deleted file mode 100644 index ae28e1fc38..0000000000 --- a/python/pip_install/extract_wheels/requirements_bzl_test.py +++ /dev/null @@ -1,19 +0,0 @@ -import unittest - -from python.pip_install.extract_wheels import bazel - - -class TestGenerateRequirementsFileContents(unittest.TestCase): - def test_all_wheel_requirements(self) -> None: - contents = bazel.generate_requirements_file_contents( - repo_name="test", - targets=['"@test//pypi__pkg1"', '"@test//pypi__pkg2"'], - ) - expected = ( - 'all_whl_requirements = ["@test//pypi__pkg1:whl","@test//pypi__pkg2:whl"]' - ) - self.assertIn(expected, contents) - - -if __name__ == "__main__": - unittest.main() From fcd0328b7b6e28ac9942729c0376d0034a365e5c Mon Sep 17 00:00:00 2001 From: Chris Love <335402+chrislovecnm@users.noreply.github.com> Date: Wed, 21 Dec 2022 16:49:18 -0700 Subject: [PATCH 087/234] Various updates build_file_generation example (#869) * Various updates build_file_generation example Updating the WORKSPACE file and BUILD file inline documentation. Added new code and new directories for example. Added new unit test for example. Added license headers. * Trying to get CI to run * Updating go and gazelle version - updating gazelle version to 0.28 - updating go version to 1.19.4 * Getting windows to build - added requirements_windows.txt from running //:requirements.update on windows - modified WORKSPACE and BUILD files to include different requirements.update when running the build on Windows --- .bazelrc | 4 +- examples/build_file_generation/BUILD | 42 +++- examples/build_file_generation/WORKSPACE | 78 ++++++- examples/build_file_generation/__init__.py | 28 ++- examples/build_file_generation/__main__.py | 18 +- examples/build_file_generation/__test__.py | 28 +++ .../build_file_generation/gazelle_python.yaml | 209 +++++++++--------- .../random_number_generator/BUILD | 19 ++ .../random_number_generator/__init__.py | 0 .../random_number_generator/__test__.py | 25 +++ .../generate_random_number.py | 19 ++ .../build_file_generation/requirements.txt | 3 +- .../requirements_lock.txt | 106 ++++++--- .../requirements_windows.txt | 82 +++++++ examples/pip_parse_vendored/requirements.bzl | 2 +- 15 files changed, 503 insertions(+), 160 deletions(-) create mode 100644 examples/build_file_generation/__test__.py create mode 100644 examples/build_file_generation/random_number_generator/BUILD create mode 100644 examples/build_file_generation/random_number_generator/__init__.py create mode 100644 examples/build_file_generation/random_number_generator/__test__.py create mode 100644 examples/build_file_generation/random_number_generator/generate_random_number.py create mode 100644 examples/build_file_generation/requirements_windows.txt diff --git a/.bazelrc b/.bazelrc index cb17e8bf1a..2ad0284c3b 100644 --- a/.bazelrc +++ b/.bazelrc @@ -3,8 +3,8 @@ # This lets us glob() up all the files inside the examples to make them inputs to tests # (Note, we cannot use `common --deleted_packages` because the bazel version command doesn't support it) # To update these lines, run tools/bazel_integration_test/update_deleted_packages.sh -build --deleted_packages=examples/build_file_generation,examples/bzlmod,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps -query --deleted_packages=examples/build_file_generation,examples/bzlmod,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps +build --deleted_packages=examples/build_file_generation,examples/build_file_generation/get_url,examples/bzlmod,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps +query --deleted_packages=examples/build_file_generation,examples/build_file_generation/get_url,examples/bzlmod,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps test --test_output=errors diff --git a/examples/build_file_generation/BUILD b/examples/build_file_generation/BUILD index 9204a0ec61..34449f31e6 100644 --- a/examples/build_file_generation/BUILD +++ b/examples/build_file_generation/BUILD @@ -1,9 +1,13 @@ +# Load various rules so that we can have bazel download +# various rulesets and dependencies. +# The `load` statement imports the symbol for the rule, in the defined +# ruleset. When the symbol is loaded you can use the rule. load("@bazel_gazelle//:def.bzl", "gazelle") load("@pip//:requirements.bzl", "all_whl_requirements") load("@rules_python//gazelle:def.bzl", "GAZELLE_PYTHON_RUNTIME_DEPS") load("@rules_python//gazelle/manifest:defs.bzl", "gazelle_python_manifest") load("@rules_python//gazelle/modules_mapping:def.bzl", "modules_mapping") -load("@rules_python//python:defs.bzl", "py_binary", "py_library") +load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test") load("@rules_python//python:pip.bzl", "compile_pip_requirements") compile_pip_requirements( @@ -11,10 +15,13 @@ compile_pip_requirements( extra_args = ["--allow-unsafe"], requirements_in = "requirements.txt", requirements_txt = "requirements_lock.txt", + requirements_windows = "requirements_windows.txt", ) -# This rule fetches the metadata for python packages we depend on. That data is -# required for the gazelle_python_manifest rule to update our manifest file. +# This repository rule fetches the metadata for python packages we +# depend on. That data is required for the gazelle_python_manifest +# rule to update our manifest file. +# To see what this rule does, try `bazel run @modules_map//:print` modules_mapping( name = "modules_map", exclude_patterns = [ @@ -52,13 +59,25 @@ gazelle( # This rule is auto-generated and managed by Gazelle, # because it found the __init__.py file in this folder. +# See: https://bazel.build/reference/be/python#py_library py_library( name = "build_file_generation", srcs = ["__init__.py"], visibility = ["//:__subpackages__"], - deps = ["@pip_requests//:pkg"], + deps = [ + "//random_number_generator", + "@pip_flask//:pkg", + ], ) +# A py_binary is an executable Python program consisting of a collection of .py source files. +# See: https://bazel.build/reference/be/python#py_binary +# +# This rule is auto-generated and managed by Gazelle, +# because it found the __main__.py file in this folder. +# This rule creates a target named //:build_file_generation_bin and you can use +# bazel to run the target: +# `bazel run //:build_file_generation_bin` py_binary( name = "build_file_generation_bin", srcs = ["__main__.py"], @@ -66,3 +85,18 @@ py_binary( visibility = ["//:__subpackages__"], deps = [":build_file_generation"], ) + +# A py_test is a Python unit test. +# See: https://bazel.build/reference/be/python#py_test +# +# This rule is auto-generated and managed by Gazelle, +# because it found the __test__.py file in this folder. +# This rule creates a target named //:build_file_generation_test and you can use +# bazel to run the target: +# `bazel test //:build_file_generation_test` +py_test( + name = "build_file_generation_test", + srcs = ["__test__.py"], + main = "__test__.py", + deps = [":build_file_generation"], +) diff --git a/examples/build_file_generation/WORKSPACE b/examples/build_file_generation/WORKSPACE index ec5c10fb32..1f411d6cb9 100644 --- a/examples/build_file_generation/WORKSPACE +++ b/examples/build_file_generation/WORKSPACE @@ -1,15 +1,22 @@ +# Set the name of the bazel workspace. workspace(name = "build_file_generation_example") +# Load the http_archive rule so that we can have bazel download +# various rulesets and dependencies. +# The `load` statement imports the symbol for http_archive from the http.bzl +# file. When the symbol is loaded you can use the rule. load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") ###################################################################### # We need rules_go and bazel_gazelle, to build the gazelle plugin from source. # Setup instructions for this section are at # https://github.com/bazelbuild/bazel-gazelle#running-gazelle-with-bazel +# You may need to update the version of the rule, which is listed in the above +# documentation. +###################################################################### -# Note, you could omit the rules_go dependency, if you have some way to statically -# compile the gazelle binary for your workspace and distribute it to users on all -# needed platforms. +# Define an http_archive rule that will download the below ruleset, +# test the sha, and extract the ruleset to you local bazel cache. http_archive( name = "io_bazel_rules_go", sha256 = "099a9fb96a376ccbbb7d291ed4ecbdfd42f6bc822ab77ae6f1b5cb9e914e94fa", @@ -19,54 +26,107 @@ http_archive( ], ) +# Download the bazel_gazelle ruleset. http_archive( name = "bazel_gazelle", - sha256 = "efbbba6ac1a4fd342d5122cbdfdb82aeb2cf2862e35022c752eaddffada7c3f3", + sha256 = "448e37e0dbf61d6fa8f00aaa12d191745e14f07c31cabfa731f0c8e8a4f41b97", urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.27.0/bazel-gazelle-v0.27.0.tar.gz", - "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.27.0/bazel-gazelle-v0.27.0.tar.gz", + "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.28.0/bazel-gazelle-v0.28.0.tar.gz", + "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.28.0/bazel-gazelle-v0.28.0.tar.gz", ], ) +# Load rules_go ruleset and expose the toolchain and dep rules. load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies") load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") +# go_rules_dependencies is a function that registers external dependencies +# needed by the Go rules. +# See: https://github.com/bazelbuild/rules_go/blob/master/go/dependencies.rst#go_rules_dependencies go_rules_dependencies() -go_register_toolchains(version = "1.18.3") +# go_rules_dependencies is a function that registers external dependencies +# needed by the Go rules. +# See: https://github.com/bazelbuild/rules_go/blob/master/go/dependencies.rst#go_rules_dependencies +go_register_toolchains(version = "1.19.4") +# The following call configured the gazelle dependencies, Go environment and Go SDK. gazelle_dependencies() -###################################################################### -# Remaining setup is for rules_python +# Remaining setup is for rules_python. +# You do not want to use the following command when you are using a WORKSPACE file +# that is outside of rules_python repository. +# This command allows targets from a local directory to be bound. +# Which allows bazel to use targets defined in base rules_python directory. +# If you are using this example outside of the rules_python git repo, +# use the http_archive command that is commented out below. +# https://bazel.build/reference/be/workspace#local_repository local_repository( name = "rules_python", path = "../..", ) +# When not using this example in the rules_python git repo you would load the python +# ruleset using the following StarLark. +# See https://github.com/bazelbuild/rules_python#getting-started for the latest +# ruleset version. +# +# The following StarLark would replace the `local_repository` rule mentioned above. +# +# load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +# http_archive( +# name = "rules_python", +# sha256 = "497ca47374f48c8b067d786b512ac10a276211810f4a580178ee9b9ad139323a", +# strip_prefix = "rules_python-0.16.1", +# url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/0.16.1.tar.gz", +# ) + +# Next we load the toolchain from rules_python. load("@rules_python//python:repositories.bzl", "python_register_toolchains") +# We now register a hermetic Python interpreter rather than relying on a system-installed interpreter. +# This toolchain will allow bazel to download a specific python version, and use that version +# for compilation. python_register_toolchains( name = "python39", python_version = "3.9", ) +# Load the interpreter and pip_parse rules. load("@python39//:defs.bzl", "interpreter") load("@rules_python//python:pip.bzl", "pip_parse") +# This macro wraps the `pip_repository` rule that invokes `pip`, with `incremental` set. +# Accepts a locked/compiled requirements file and installs the dependencies listed within. +# Those dependencies become available in a generated `requirements.bzl` file. +# You can instead check this `requirements.bzl` file into your repo. pip_parse( name = "pip", + # (Optional) You can provide a python_interpreter (path) or a python_interpreter_target (a Bazel target, that + # acts as an executable). The latter can be anything that could be used as Python interpreter. E.g.: + # 1. Python interpreter that you compile in the build file. + # 2. Pre-compiled python interpreter included with http_archive. + # 3. Wrapper script, like in the autodetecting python toolchain. + # + # Here, we use the interpreter constant that resolves to the host interpreter from the default Python toolchain. python_interpreter_target = interpreter, + # Set the location of the lock file. requirements_lock = "//:requirements_lock.txt", + requirements_windows = "//:requirements_windows.txt", ) +# Load the install_deps macro. load("@pip//:requirements.bzl", "install_deps") +# Initialize repositories for all packages in requirements_lock.txt. install_deps() # The rules_python gazelle extension has some third-party go dependencies # which we need to fetch in order to compile it. load("@rules_python//gazelle:deps.bzl", _py_gazelle_deps = "gazelle_deps") +# See: https://github.com/bazelbuild/rules_python/blob/main/gazelle/README.md +# This rule loads and compiles various go dependencies that running gazelle +# for python requirements. _py_gazelle_deps() diff --git a/examples/build_file_generation/__init__.py b/examples/build_file_generation/__init__.py index 6dfd77cf05..add73dafcc 100644 --- a/examples/build_file_generation/__init__.py +++ b/examples/build_file_generation/__init__.py @@ -1,6 +1,26 @@ -import requests +# Copyright 2022 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from flask import Flask, jsonify +from random_number_generator import generate_random_number -def main(url): - r = requests.get(url) - print(r.text) +app = Flask(__name__) + +@app.route('/random-number', methods=['GET']) +def get_random_number(): + return jsonify({'number': generate_random_number.generate_random_number()}) + +"""Start the python web server""" +def main(): + app.run() diff --git a/examples/build_file_generation/__main__.py b/examples/build_file_generation/__main__.py index 106c8365eb..8f8efbaaa3 100644 --- a/examples/build_file_generation/__main__.py +++ b/examples/build_file_generation/__main__.py @@ -1,4 +1,18 @@ +# Copyright 2022 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from __init__ import main -if __name__ == "__main__": - main("https://example.com") +if __name__ == '__main__': + main() diff --git a/examples/build_file_generation/__test__.py b/examples/build_file_generation/__test__.py new file mode 100644 index 0000000000..c4fa5ef9b5 --- /dev/null +++ b/examples/build_file_generation/__test__.py @@ -0,0 +1,28 @@ +# Copyright 2022 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest +from __init__ import app + +class TestServer(unittest.TestCase): + def setUp(self): + self.app = app.test_client() + + def test_get_random_number(self): + response = self.app.get('/random-number') + self.assertEqual(response.status_code, 200) + self.assertIn('number', response.json) + +if __name__ == '__main__': + unittest.main() diff --git a/examples/build_file_generation/gazelle_python.yaml b/examples/build_file_generation/gazelle_python.yaml index f25f59e4b2..46d1d641de 100644 --- a/examples/build_file_generation/gazelle_python.yaml +++ b/examples/build_file_generation/gazelle_python.yaml @@ -5,107 +5,114 @@ manifest: modules_mapping: - certifi: certifi - certifi.core: certifi - chardet: chardet - chardet.big5freq: chardet - chardet.big5prober: chardet - chardet.chardistribution: chardet - chardet.charsetgroupprober: chardet - chardet.charsetprober: chardet - chardet.cli: chardet - chardet.cli.chardetect: chardet - chardet.codingstatemachine: chardet - chardet.compat: chardet - chardet.cp949prober: chardet - chardet.enums: chardet - chardet.escprober: chardet - chardet.escsm: chardet - chardet.eucjpprober: chardet - chardet.euckrfreq: chardet - chardet.euckrprober: chardet - chardet.euctwfreq: chardet - chardet.euctwprober: chardet - chardet.gb2312freq: chardet - chardet.gb2312prober: chardet - chardet.hebrewprober: chardet - chardet.jisfreq: chardet - chardet.jpcntx: chardet - chardet.langbulgarianmodel: chardet - chardet.langcyrillicmodel: chardet - chardet.langgreekmodel: chardet - chardet.langhebrewmodel: chardet - chardet.langhungarianmodel: chardet - chardet.langthaimodel: chardet - chardet.langturkishmodel: chardet - chardet.latin1prober: chardet - chardet.mbcharsetprober: chardet - chardet.mbcsgroupprober: chardet - chardet.mbcssm: chardet - chardet.sbcharsetprober: chardet - chardet.sbcsgroupprober: chardet - chardet.sjisprober: chardet - chardet.universaldetector: chardet - chardet.utf8prober: chardet - chardet.version: chardet - idna: idna - idna.codec: idna - idna.compat: idna - idna.core: idna - idna.idnadata: idna - idna.intranges: idna - idna.package_data: idna - idna.uts46data: idna - psutil: psutil - requests: requests - requests.adapters: requests - requests.api: requests - requests.auth: requests - requests.certs: requests - requests.compat: requests - requests.cookies: requests - requests.exceptions: requests - requests.help: requests - requests.hooks: requests - requests.models: requests - requests.packages: requests - requests.sessions: requests - requests.status_codes: requests - requests.structures: requests - requests.utils: requests - urllib3: urllib3 - urllib3.connection: urllib3 - urllib3.connectionpool: urllib3 - urllib3.contrib: urllib3 - urllib3.contrib.appengine: urllib3 - urllib3.contrib.ntlmpool: urllib3 - urllib3.contrib.pyopenssl: urllib3 - urllib3.contrib.securetransport: urllib3 - urllib3.contrib.socks: urllib3 - urllib3.exceptions: urllib3 - urllib3.fields: urllib3 - urllib3.filepost: urllib3 - urllib3.packages: urllib3 - urllib3.packages.backports: urllib3 - urllib3.packages.backports.makefile: urllib3 - urllib3.packages.six: urllib3 - urllib3.packages.ssl_match_hostname: urllib3 - urllib3.poolmanager: urllib3 - urllib3.request: urllib3 - urllib3.response: urllib3 - urllib3.util: urllib3 - urllib3.util.connection: urllib3 - urllib3.util.proxy: urllib3 - urllib3.util.queue: urllib3 - urllib3.util.request: urllib3 - urllib3.util.response: urllib3 - urllib3.util.retry: urllib3 - urllib3.util.ssl_: urllib3 - urllib3.util.ssltransport: urllib3 - urllib3.util.timeout: urllib3 - urllib3.util.url: urllib3 - urllib3.util.wait: urllib3 + click: click + click.core: click + click.decorators: click + click.exceptions: click + click.formatting: click + click.globals: click + click.parser: click + click.shell_completion: click + click.termui: click + click.testing: click + click.types: click + click.utils: click + flask: Flask + flask.app: Flask + flask.blueprints: Flask + flask.cli: Flask + flask.config: Flask + flask.ctx: Flask + flask.debughelpers: Flask + flask.globals: Flask + flask.helpers: Flask + flask.json: Flask + flask.json.provider: Flask + flask.json.tag: Flask + flask.logging: Flask + flask.scaffold: Flask + flask.sessions: Flask + flask.signals: Flask + flask.templating: Flask + flask.testing: Flask + flask.typing: Flask + flask.views: Flask + flask.wrappers: Flask + importlib_metadata: importlib_metadata + itsdangerous: itsdangerous + itsdangerous.encoding: itsdangerous + itsdangerous.exc: itsdangerous + itsdangerous.serializer: itsdangerous + itsdangerous.signer: itsdangerous + itsdangerous.timed: itsdangerous + itsdangerous.url_safe: itsdangerous + jinja2: Jinja2 + jinja2.async_utils: Jinja2 + jinja2.bccache: Jinja2 + jinja2.compiler: Jinja2 + jinja2.constants: Jinja2 + jinja2.debug: Jinja2 + jinja2.defaults: Jinja2 + jinja2.environment: Jinja2 + jinja2.exceptions: Jinja2 + jinja2.ext: Jinja2 + jinja2.filters: Jinja2 + jinja2.idtracking: Jinja2 + jinja2.lexer: Jinja2 + jinja2.loaders: Jinja2 + jinja2.meta: Jinja2 + jinja2.nativetypes: Jinja2 + jinja2.nodes: Jinja2 + jinja2.optimizer: Jinja2 + jinja2.parser: Jinja2 + jinja2.runtime: Jinja2 + jinja2.sandbox: Jinja2 + jinja2.utils: Jinja2 + jinja2.visitor: Jinja2 + markupsafe: MarkupSafe + werkzeug: Werkzeug + werkzeug.datastructures: Werkzeug + werkzeug.debug: Werkzeug + werkzeug.debug.console: Werkzeug + werkzeug.debug.repr: Werkzeug + werkzeug.debug.tbtools: Werkzeug + werkzeug.exceptions: Werkzeug + werkzeug.formparser: Werkzeug + werkzeug.http: Werkzeug + werkzeug.local: Werkzeug + werkzeug.middleware: Werkzeug + werkzeug.middleware.dispatcher: Werkzeug + werkzeug.middleware.http_proxy: Werkzeug + werkzeug.middleware.lint: Werkzeug + werkzeug.middleware.profiler: Werkzeug + werkzeug.middleware.proxy_fix: Werkzeug + werkzeug.middleware.shared_data: Werkzeug + werkzeug.routing: Werkzeug + werkzeug.routing.converters: Werkzeug + werkzeug.routing.exceptions: Werkzeug + werkzeug.routing.map: Werkzeug + werkzeug.routing.matcher: Werkzeug + werkzeug.routing.rules: Werkzeug + werkzeug.sansio: Werkzeug + werkzeug.sansio.http: Werkzeug + werkzeug.sansio.multipart: Werkzeug + werkzeug.sansio.request: Werkzeug + werkzeug.sansio.response: Werkzeug + werkzeug.sansio.utils: Werkzeug + werkzeug.security: Werkzeug + werkzeug.serving: Werkzeug + werkzeug.test: Werkzeug + werkzeug.testapp: Werkzeug + werkzeug.urls: Werkzeug + werkzeug.user_agent: Werkzeug + werkzeug.utils: Werkzeug + werkzeug.wrappers: Werkzeug + werkzeug.wrappers.request: Werkzeug + werkzeug.wrappers.response: Werkzeug + werkzeug.wsgi: Werkzeug + zipp: zipp + zipp.py310compat: zipp pip_repository: name: pip incremental: true -integrity: 91adaddb7e2d3eb7234e78979ff40b666101ab4df91c62659b954cc9376c2f86 +integrity: 9bb7b166e9358f3244c9beae2a863084fe4e58c31d3ccb65618dd471512fdb5e diff --git a/examples/build_file_generation/random_number_generator/BUILD b/examples/build_file_generation/random_number_generator/BUILD new file mode 100644 index 0000000000..95e16fd301 --- /dev/null +++ b/examples/build_file_generation/random_number_generator/BUILD @@ -0,0 +1,19 @@ +load("@rules_python//python:defs.bzl", "py_library", "py_test") + +py_library( + name = "random_number_generator", + srcs = [ + "__init__.py", + "generate_random_number.py", + ], + imports = [".."], + visibility = ["//:__subpackages__"], +) + +py_test( + name = "random_number_generator_test", + srcs = ["__test__.py"], + imports = [".."], + main = "__test__.py", + deps = [":random_number_generator"], +) diff --git a/examples/build_file_generation/random_number_generator/__init__.py b/examples/build_file_generation/random_number_generator/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/build_file_generation/random_number_generator/__test__.py b/examples/build_file_generation/random_number_generator/__test__.py new file mode 100644 index 0000000000..8cfb235d57 --- /dev/null +++ b/examples/build_file_generation/random_number_generator/__test__.py @@ -0,0 +1,25 @@ +# Copyright 2022 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest +import random_number_generator.generate_random_number as generate_random_number + +class TestRandomNumberGenerator(unittest.TestCase): + def test_generate_random_number(self): + number = generate_random_number.generate_random_number() + self.assertGreaterEqual(number, 1) + self.assertLessEqual(number, 10) + +if __name__ == '__main__': + unittest.main() diff --git a/examples/build_file_generation/random_number_generator/generate_random_number.py b/examples/build_file_generation/random_number_generator/generate_random_number.py new file mode 100644 index 0000000000..e198b5bbcd --- /dev/null +++ b/examples/build_file_generation/random_number_generator/generate_random_number.py @@ -0,0 +1,19 @@ +# Copyright 2022 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import random + +"""Generate a random number""" +def generate_random_number(): + return random.randint(1, 10) diff --git a/examples/build_file_generation/requirements.txt b/examples/build_file_generation/requirements.txt index 2851c1e65b..7e1060246f 100644 --- a/examples/build_file_generation/requirements.txt +++ b/examples/build_file_generation/requirements.txt @@ -1,2 +1 @@ -requests==2.25.1 -psutil==5.9.4 +flask diff --git a/examples/build_file_generation/requirements_lock.txt b/examples/build_file_generation/requirements_lock.txt index 07ff2eccc4..f4a29bdefc 100644 --- a/examples/build_file_generation/requirements_lock.txt +++ b/examples/build_file_generation/requirements_lock.txt @@ -4,39 +4,75 @@ # # bazel run //:requirements.update # -certifi==2020.12.5 \ - --hash=sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c \ - --hash=sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830 - # via requests -chardet==3.0.4 \ - --hash=sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae \ - --hash=sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691 - # via requests -idna==2.10 \ - --hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 \ - --hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0 - # via requests -psutil==5.9.4 \ - --hash=sha256:149555f59a69b33f056ba1c4eb22bb7bf24332ce631c44a319cec09f876aaeff \ - --hash=sha256:16653106f3b59386ffe10e0bad3bb6299e169d5327d3f187614b1cb8f24cf2e1 \ - --hash=sha256:3d7f9739eb435d4b1338944abe23f49584bde5395f27487d2ee25ad9a8774a62 \ - --hash=sha256:3ff89f9b835100a825b14c2808a106b6fdcc4b15483141482a12c725e7f78549 \ - --hash=sha256:54c0d3d8e0078b7666984e11b12b88af2db11d11249a8ac8920dd5ef68a66e08 \ - --hash=sha256:54d5b184728298f2ca8567bf83c422b706200bcbbfafdc06718264f9393cfeb7 \ - --hash=sha256:6001c809253a29599bc0dfd5179d9f8a5779f9dffea1da0f13c53ee568115e1e \ - --hash=sha256:68908971daf802203f3d37e78d3f8831b6d1014864d7a85937941bb35f09aefe \ - --hash=sha256:6b92c532979bafc2df23ddc785ed116fced1f492ad90a6830cf24f4d1ea27d24 \ - --hash=sha256:852dd5d9f8a47169fe62fd4a971aa07859476c2ba22c2254d4a1baa4e10b95ad \ - --hash=sha256:9120cd39dca5c5e1c54b59a41d205023d436799b1c8c4d3ff71af18535728e94 \ - --hash=sha256:c1ca331af862803a42677c120aff8a814a804e09832f166f226bfd22b56feee8 \ - --hash=sha256:efeae04f9516907be44904cc7ce08defb6b665128992a56957abc9b61dca94b7 \ - --hash=sha256:fd8522436a6ada7b4aad6638662966de0d61d241cb821239b2ae7013d41a43d4 +click==8.1.3 \ + --hash=sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e \ + --hash=sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48 + # via flask +flask==2.2.2 \ + --hash=sha256:642c450d19c4ad482f96729bd2a8f6d32554aa1e231f4f6b4e7e5264b16cca2b \ + --hash=sha256:b9c46cc36662a7949f34b52d8ec7bb59c0d74ba08ba6cb9ce9adc1d8676d9526 # via -r ./requirements.txt -requests==2.25.1 \ - --hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \ - --hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e - # via -r ./requirements.txt -urllib3==1.26.5 \ - --hash=sha256:753a0374df26658f99d826cfe40394a686d05985786d946fbe4165b5148f5a7c \ - --hash=sha256:a7acd0977125325f516bda9735fa7142b909a8d01e8b2e4c8108d0984e6e0098 - # via requests +importlib-metadata==5.1.0 \ + --hash=sha256:d5059f9f1e8e41f80e9c56c2ee58811450c31984dfa625329ffd7c0dad88a73b \ + --hash=sha256:d84d17e21670ec07990e1044a99efe8d615d860fd176fc29ef5c306068fda313 + # via flask +itsdangerous==2.1.2 \ + --hash=sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44 \ + --hash=sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a + # via flask +jinja2==3.1.2 \ + --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \ + --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61 + # via flask +markupsafe==2.1.1 \ + --hash=sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003 \ + --hash=sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88 \ + --hash=sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5 \ + --hash=sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7 \ + --hash=sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a \ + --hash=sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603 \ + --hash=sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1 \ + --hash=sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135 \ + --hash=sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247 \ + --hash=sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6 \ + --hash=sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601 \ + --hash=sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77 \ + --hash=sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02 \ + --hash=sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e \ + --hash=sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63 \ + --hash=sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f \ + --hash=sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980 \ + --hash=sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b \ + --hash=sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812 \ + --hash=sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff \ + --hash=sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96 \ + --hash=sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1 \ + --hash=sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925 \ + --hash=sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a \ + --hash=sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6 \ + --hash=sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e \ + --hash=sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f \ + --hash=sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4 \ + --hash=sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f \ + --hash=sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3 \ + --hash=sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c \ + --hash=sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a \ + --hash=sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417 \ + --hash=sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a \ + --hash=sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a \ + --hash=sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37 \ + --hash=sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452 \ + --hash=sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933 \ + --hash=sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a \ + --hash=sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7 + # via + # jinja2 + # werkzeug +werkzeug==2.2.2 \ + --hash=sha256:7ea2d48322cc7c0f8b3a215ed73eabd7b5d75d0b50e31ab006286ccff9e00b8f \ + --hash=sha256:f979ab81f58d7318e064e99c4506445d60135ac5cd2e177a2de0089bfd4c9bd5 + # via flask +zipp==3.11.0 \ + --hash=sha256:83a28fcb75844b5c0cdaf5aa4003c2d728c77e05f5aeabe8e95e56727005fbaa \ + --hash=sha256:a7a22e05929290a67401440b39690ae6563279bced5f314609d9d03798f56766 + # via importlib-metadata diff --git a/examples/build_file_generation/requirements_windows.txt b/examples/build_file_generation/requirements_windows.txt new file mode 100644 index 0000000000..4f6d590b7c --- /dev/null +++ b/examples/build_file_generation/requirements_windows.txt @@ -0,0 +1,82 @@ +# +# This file is autogenerated by pip-compile with python 3.9 +# To update, run: +# +# bazel run //:requirements.update +# +click==8.1.3 \ + --hash=sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e \ + --hash=sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48 + # via flask +colorama==0.4.6 \ + --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ + --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 + # via click +flask==2.2.2 \ + --hash=sha256:642c450d19c4ad482f96729bd2a8f6d32554aa1e231f4f6b4e7e5264b16cca2b \ + --hash=sha256:b9c46cc36662a7949f34b52d8ec7bb59c0d74ba08ba6cb9ce9adc1d8676d9526 + # via -r ./requirements.txt +importlib-metadata==5.1.0 \ + --hash=sha256:d5059f9f1e8e41f80e9c56c2ee58811450c31984dfa625329ffd7c0dad88a73b \ + --hash=sha256:d84d17e21670ec07990e1044a99efe8d615d860fd176fc29ef5c306068fda313 + # via flask +itsdangerous==2.1.2 \ + --hash=sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44 \ + --hash=sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a + # via flask +jinja2==3.1.2 \ + --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \ + --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61 + # via flask +markupsafe==2.1.1 \ + --hash=sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003 \ + --hash=sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88 \ + --hash=sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5 \ + --hash=sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7 \ + --hash=sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a \ + --hash=sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603 \ + --hash=sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1 \ + --hash=sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135 \ + --hash=sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247 \ + --hash=sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6 \ + --hash=sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601 \ + --hash=sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77 \ + --hash=sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02 \ + --hash=sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e \ + --hash=sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63 \ + --hash=sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f \ + --hash=sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980 \ + --hash=sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b \ + --hash=sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812 \ + --hash=sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff \ + --hash=sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96 \ + --hash=sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1 \ + --hash=sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925 \ + --hash=sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a \ + --hash=sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6 \ + --hash=sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e \ + --hash=sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f \ + --hash=sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4 \ + --hash=sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f \ + --hash=sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3 \ + --hash=sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c \ + --hash=sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a \ + --hash=sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417 \ + --hash=sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a \ + --hash=sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a \ + --hash=sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37 \ + --hash=sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452 \ + --hash=sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933 \ + --hash=sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a \ + --hash=sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7 + # via + # jinja2 + # werkzeug +werkzeug==2.2.2 \ + --hash=sha256:7ea2d48322cc7c0f8b3a215ed73eabd7b5d75d0b50e31ab006286ccff9e00b8f \ + --hash=sha256:f979ab81f58d7318e064e99c4506445d60135ac5cd2e177a2de0089bfd4c9bd5 + # via flask +zipp==3.11.0 \ + --hash=sha256:83a28fcb75844b5c0cdaf5aa4003c2d728c77e05f5aeabe8e95e56727005fbaa \ + --hash=sha256:a7a22e05929290a67401440b39690ae6563279bced5f314609d9d03798f56766 + # via importlib-metadata diff --git a/examples/pip_parse_vendored/requirements.bzl b/examples/pip_parse_vendored/requirements.bzl index 5a0dcf85f5..4febc756fa 100644 --- a/examples/pip_parse_vendored/requirements.bzl +++ b/examples/pip_parse_vendored/requirements.bzl @@ -1,7 +1,7 @@ """Starlark representation of locked requirements. @generated by rules_python pip_parse repository rule -from //:requirements.txt +from @//:requirements.txt """ load("@python39//:defs.bzl", "interpreter") From 833152272add751db2f18c496b401dd9e60de4e8 Mon Sep 17 00:00:00 2001 From: Greg Roodt Date: Thu, 22 Dec 2022 10:54:10 +1100 Subject: [PATCH 088/234] Fix CI after bazel 6.0.0 (#938) --- .bazelversion | 2 +- version.bzl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bazelversion b/.bazelversion index 91ff57278e..09b254e90c 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1 +1 @@ -5.2.0 +6.0.0 diff --git a/version.bzl b/version.bzl index a73ef4d968..91125c21bf 100644 --- a/version.bzl +++ b/version.bzl @@ -17,7 +17,7 @@ # against. # This version should be updated together with the version of Bazel # in .bazelversion. -BAZEL_VERSION = "5.2.0" +BAZEL_VERSION = "6.0.0" # Versions of Bazel which users should be able to use. # Ensures we don't break backwards-compatibility, From 72ac64a9966d3e2017393b9280a4d4575c538235 Mon Sep 17 00:00:00 2001 From: Greg Roodt Date: Sat, 24 Dec 2022 11:38:40 +1100 Subject: [PATCH 089/234] Refactor wheel_installer (#937) * . * . * . * . * . * . --- examples/wheel/wheel_test.py | 6 +- python/pip_install/extract_wheels/BUILD | 34 +- python/pip_install/extract_wheels/bazel.py | 352 ------------- .../pip_install/extract_wheels/bazel_test.py | 26 - .../extract_wheels/extract_single_wheel.py | 105 ---- .../extract_wheels/requirements.py | 47 -- .../extract_wheels/requirements_test.py | 40 -- .../extract_wheels/wheel_installer.py | 488 ++++++++++++++++++ .../extract_wheels/wheel_installer_test.py | 110 ++++ .../extract_wheels/whl_filegroup_test.py | 53 -- python/pip_install/pip_repository.bzl | 2 +- python/pip_install/private/srcs.bzl | 3 +- tools/bazel_integration_test/test_runner.py | 2 +- tools/wheelmaker.py | 15 +- 14 files changed, 618 insertions(+), 665 deletions(-) delete mode 100644 python/pip_install/extract_wheels/bazel_test.py delete mode 100644 python/pip_install/extract_wheels/extract_single_wheel.py delete mode 100644 python/pip_install/extract_wheels/requirements.py delete mode 100644 python/pip_install/extract_wheels/requirements_test.py create mode 100644 python/pip_install/extract_wheels/wheel_installer.py create mode 100644 python/pip_install/extract_wheels/wheel_installer_test.py delete mode 100644 python/pip_install/extract_wheels/whl_filegroup_test.py diff --git a/examples/wheel/wheel_test.py b/examples/wheel/wheel_test.py index cbca0927c3..67aaac5cca 100644 --- a/examples/wheel/wheel_test.py +++ b/examples/wheel/wheel_test.py @@ -109,7 +109,8 @@ def test_customized_wheel(self): examples/wheel/lib/module_with_data.py,sha256=8s0Khhcqz3yVsBKv2IB5u4l4TMKh7-c_V6p65WVHPms,637 examples/wheel/lib/simple_module.py,sha256=z2hwciab_XPNIBNH8B1Q5fYgnJvQTeYf0ZQJpY8yLLY,637 examples/wheel/main.py,sha256=sgg5iWN_9inYBjm6_Zw27hYdmo-l24fA-2rfphT-IlY,909 -""") +""", + ) self.assertEqual( wheel_contents, b"""\ @@ -134,7 +135,8 @@ def test_customized_wheel(self): Requires-Dist: pytest This is a sample description of a wheel. -""") +""", + ) self.assertEqual( entry_point_contents, b"""\ diff --git a/python/pip_install/extract_wheels/BUILD b/python/pip_install/extract_wheels/BUILD index 1420f4be80..1cf7e2e1fa 100644 --- a/python/pip_install/extract_wheels/BUILD +++ b/python/pip_install/extract_wheels/BUILD @@ -8,11 +8,10 @@ py_library( "annotation.py", "arguments.py", "bazel.py", - "extract_single_wheel.py", "namespace_pkgs.py", "parse_requirements_to_bzl.py", - "requirements.py", "wheel.py", + "wheel_installer.py", ], deps = [ requirement("installer"), @@ -21,9 +20,9 @@ py_library( ) py_binary( - name = "extract_single_wheel", + name = "wheel_installer", srcs = [ - "extract_single_wheel.py", + "wheel_installer.py", ], deps = [":lib"], ) @@ -78,18 +77,6 @@ py_test( ], ) -py_test( - name = "bazel_test", - size = "small", - srcs = [ - "bazel_test.py", - ], - tags = ["unit"], - deps = [ - ":lib", - ], -) - py_test( name = "namespace_pkgs_test", size = "small", @@ -103,11 +90,12 @@ py_test( ) py_test( - name = "requirements_test", + name = "wheel_installer_test", size = "small", srcs = [ - "requirements_test.py", + "wheel_installer_test.py", ], + data = ["//examples/wheel:minimal_with_py_package"], tags = ["unit"], deps = [ ":lib", @@ -126,16 +114,6 @@ py_test( ], ) -py_test( - name = "whl_filegroup_test", - size = "small", - srcs = ["whl_filegroup_test.py"], - data = ["//examples/wheel:minimal_with_py_package"], - main = "whl_filegroup_test.py", - tags = ["unit"], - deps = [":lib"], -) - py_test( name = "parse_requirements_to_bzl_test", size = "small", diff --git a/python/pip_install/extract_wheels/bazel.py b/python/pip_install/extract_wheels/bazel.py index 28a229277d..c0a4aec422 100644 --- a/python/pip_install/extract_wheels/bazel.py +++ b/python/pip_install/extract_wheels/bazel.py @@ -1,13 +1,3 @@ -"""Utility functions to manipulate Bazel files""" -import json -import os -import shutil -import textwrap -from pathlib import Path -from typing import Dict, Iterable, List, Optional, Set - -from python.pip_install.extract_wheels import annotation, namespace_pkgs, wheel - WHEEL_FILE_LABEL = "whl" PY_LIBRARY_LABEL = "pkg" DATA_LABEL = "data" @@ -15,192 +5,6 @@ WHEEL_ENTRY_POINT_PREFIX = "rules_python_wheel_entry_point" -def generate_entry_point_contents( - module: str, attribute: str, shebang: str = "#!/usr/bin/env python3" -) -> str: - """Generate the contents of an entry point script. - - Args: - module (str): The name of the module to use. - attribute (str): The name of the attribute to call. - shebang (str, optional): The shebang to use for the entry point python - file. - - Returns: - str: A string of python code. - """ - return textwrap.dedent( - """\ - {shebang} - import sys - from {module} import {attribute} - if __name__ == "__main__": - sys.exit({attribute}()) - """.format( - shebang=shebang, module=module, attribute=attribute - ) - ) - - -def generate_entry_point_rule(name: str, script: str, pkg: str) -> str: - """Generate a Bazel `py_binary` rule for an entry point script. - - Note that the script is used to determine the name of the target. The name of - entry point targets should be uniuqe to avoid conflicts with existing sources or - directories within a wheel. - - Args: - name (str): The name of the generated py_binary. - script (str): The path to the entry point's python file. - pkg (str): The package owning the entry point. This is expected to - match up with the `py_library` defined for each repository. - - - Returns: - str: A `py_binary` instantiation. - """ - return textwrap.dedent( - """\ - py_binary( - name = "{name}", - srcs = ["{src}"], - # This makes this directory a top-level in the python import - # search path for anything that depends on this. - imports = ["."], - deps = ["{pkg}"], - ) - """.format( - name=name, src=str(script).replace("\\", "/"), pkg=pkg - ) - ) - - -def generate_copy_commands(src, dest, is_executable=False) -> str: - """Generate a [@bazel_skylib//rules:copy_file.bzl%copy_file][cf] target - - [cf]: https://github.com/bazelbuild/bazel-skylib/blob/1.1.1/docs/copy_file_doc.md - - Args: - src (str): The label for the `src` attribute of [copy_file][cf] - dest (str): The label for the `out` attribute of [copy_file][cf] - is_executable (bool, optional): Whether or not the file being copied is executable. - sets `is_executable` for [copy_file][cf] - - Returns: - str: A `copy_file` instantiation. - """ - return textwrap.dedent( - """\ - copy_file( - name = "{dest}.copy", - src = "{src}", - out = "{dest}", - is_executable = {is_executable}, - ) - """.format( - src=src, - dest=dest, - is_executable=is_executable, - ) - ) - - -def generate_build_file_contents( - name: str, - dependencies: List[str], - whl_file_deps: List[str], - data_exclude: List[str], - tags: List[str], - srcs_exclude: List[str] = [], - data: List[str] = [], - additional_content: List[str] = [], -) -> str: - """Generate a BUILD file for an unzipped Wheel - - Args: - name: the target name of the py_library - dependencies: a list of Bazel labels pointing to dependencies of the library - whl_file_deps: a list of Bazel labels pointing to wheel file dependencies of this wheel. - data_exclude: more patterns to exclude from the data attribute of generated py_library rules. - tags: list of tags to apply to generated py_library rules. - additional_content: A list of additional content to append to the BUILD file. - - Returns: - A complete BUILD file as a string - - We allow for empty Python sources as for Wheels containing only compiled C code - there may be no Python sources whatsoever (e.g. packages written in Cython: like `pymssql`). - """ - - data_exclude = list( - set( - [ - "**/* *", - "**/*.py", - "**/*.pyc", - # RECORD is known to contain sha256 checksums of files which might include the checksums - # of generated files produced when wheels are installed. The file is ignored to avoid - # Bazel caching issues. - "**/*.dist-info/RECORD", - ] - + data_exclude - ) - ) - - return "\n".join( - [ - textwrap.dedent( - """\ - load("@rules_python//python:defs.bzl", "py_library", "py_binary") - load("@rules_python//third_party/github.com/bazelbuild/bazel-skylib/rules:copy_file.bzl", "copy_file") - - package(default_visibility = ["//visibility:public"]) - - filegroup( - name = "{dist_info_label}", - srcs = glob(["site-packages/*.dist-info/**"], allow_empty = True), - ) - - filegroup( - name = "{data_label}", - srcs = glob(["data/**"], allow_empty = True), - ) - - filegroup( - name = "{whl_file_label}", - srcs = glob(["*.whl"], allow_empty = True), - data = [{whl_file_deps}], - ) - - py_library( - name = "{name}", - srcs = glob(["site-packages/**/*.py"], exclude={srcs_exclude}, allow_empty = True), - data = {data} + glob(["site-packages/**/*"], exclude={data_exclude}), - # This makes this directory a top-level in the python import - # search path for anything that depends on this. - imports = ["site-packages"], - deps = [{dependencies}], - tags = [{tags}], - ) - """.format( - name=name, - dependencies=",".join(sorted(dependencies)), - data_exclude=json.dumps(sorted(data_exclude)), - whl_file_label=WHEEL_FILE_LABEL, - whl_file_deps=",".join(sorted(whl_file_deps)), - tags=",".join(sorted(['"%s"' % t for t in tags])), - data_label=DATA_LABEL, - dist_info_label=DIST_INFO_LABEL, - entry_point_prefix=WHEEL_ENTRY_POINT_PREFIX, - srcs_exclude=json.dumps(sorted(srcs_exclude)), - data=json.dumps(sorted(data)), - ) - ) - ] - + additional_content - ) - - def sanitise_name(name: str, prefix: str) -> str: """Sanitises the name to be compatible with Bazel labels. @@ -221,38 +25,6 @@ def sanitise_name(name: str, prefix: str) -> str: return prefix + name.replace("-", "_").replace(".", "_").lower() -def setup_namespace_pkg_compatibility(wheel_dir: str) -> None: - """Converts native namespace packages to pkgutil-style packages - - Namespace packages can be created in one of three ways. They are detailed here: - https://packaging.python.org/guides/packaging-namespace-packages/#creating-a-namespace-package - - 'pkgutil-style namespace packages' (2) and 'pkg_resources-style namespace packages' (3) works in Bazel, but - 'native namespace packages' (1) do not. - - We ensure compatibility with Bazel of method 1 by converting them into method 2. - - Args: - wheel_dir: the directory of the wheel to convert - """ - - namespace_pkg_dirs = namespace_pkgs.implicit_namespace_packages( - wheel_dir, - ignored_dirnames=["%s/bin" % wheel_dir], - ) - - for ns_pkg_dir in namespace_pkg_dirs: - namespace_pkgs.add_pkgutil_style_namespace_pkg_init(ns_pkg_dir) - - -def sanitised_library_label(whl_name: str, prefix: str) -> str: - return '"//%s"' % sanitise_name(whl_name, prefix) - - -def sanitised_file_label(whl_name: str, prefix: str) -> str: - return '"//%s:%s"' % (sanitise_name(whl_name, prefix), WHEEL_FILE_LABEL) - - def _whl_name_to_repo_root(whl_name: str, repo_prefix: str) -> str: return "@{}//".format(sanitise_name(whl_name, prefix=repo_prefix)) @@ -267,127 +39,3 @@ def sanitised_repo_file_label(whl_name: str, repo_prefix: str) -> str: return '"{}:{}"'.format( _whl_name_to_repo_root(whl_name, repo_prefix), WHEEL_FILE_LABEL ) - - -def extract_wheel( - wheel_file: str, - extras: Dict[str, Set[str]], - pip_data_exclude: List[str], - enable_implicit_namespace_pkgs: bool, - repo_prefix: str, - incremental: bool = False, - incremental_dir: Path = Path("."), - annotation: Optional[annotation.Annotation] = None, -) -> Optional[str]: - """Extracts wheel into given directory and creates py_library and filegroup targets. - - Args: - wheel_file: the filepath of the .whl - extras: a list of extras to add as dependencies for the installed wheel - pip_data_exclude: list of file patterns to exclude from the generated data section of the py_library - enable_implicit_namespace_pkgs: if true, disables conversion of implicit namespace packages and will unzip as-is - incremental: If true the extract the wheel in a format suitable for an external repository. This - effects the names of libraries and their dependencies, which point to other external repositories. - incremental_dir: An optional override for the working directory of incremental builds. - annotation: An optional set of annotations to apply to the BUILD contents of the wheel. - - Returns: - The Bazel label for the extracted wheel, in the form '//path/to/wheel'. - """ - - whl = wheel.Wheel(wheel_file) - if incremental: - directory = incremental_dir - else: - directory = sanitise_name(whl.name, prefix=repo_prefix) - - os.mkdir(directory) - # copy the original wheel - shutil.copy(whl.path, directory) - whl.unzip(directory) - - if not enable_implicit_namespace_pkgs: - setup_namespace_pkg_compatibility(directory) - - extras_requested = extras[whl.name] if whl.name in extras else set() - # Packages may create dependency cycles when specifying optional-dependencies / 'extras'. - # Example: github.com/google/etils/blob/a0b71032095db14acf6b33516bca6d885fe09e35/pyproject.toml#L32. - self_edge_dep = set([whl.name]) - whl_deps = sorted(whl.dependencies(extras_requested) - self_edge_dep) - - if incremental: - sanitised_dependencies = [ - sanitised_repo_library_label(d, repo_prefix=repo_prefix) for d in whl_deps - ] - sanitised_wheel_file_dependencies = [ - sanitised_repo_file_label(d, repo_prefix=repo_prefix) for d in whl_deps - ] - else: - sanitised_dependencies = [ - sanitised_library_label(d, prefix=repo_prefix) for d in whl_deps - ] - sanitised_wheel_file_dependencies = [ - sanitised_file_label(d, prefix=repo_prefix) for d in whl_deps - ] - - library_name = ( - PY_LIBRARY_LABEL if incremental else sanitise_name(whl.name, repo_prefix) - ) - - directory_path = Path(directory) - entry_points = [] - for name, (module, attribute) in sorted(whl.entry_points().items()): - # There is an extreme edge-case with entry_points that end with `.py` - # See: https://github.com/bazelbuild/bazel/blob/09c621e4cf5b968f4c6cdf905ab142d5961f9ddc/src/test/java/com/google/devtools/build/lib/rules/python/PyBinaryConfiguredTargetTest.java#L174 - entry_point_without_py = f"{name[:-3]}_py" if name.endswith(".py") else name - entry_point_target_name = f"{WHEEL_ENTRY_POINT_PREFIX}_{entry_point_without_py}" - entry_point_script_name = f"{entry_point_target_name}.py" - (directory_path / entry_point_script_name).write_text( - generate_entry_point_contents(module, attribute) - ) - entry_points.append( - generate_entry_point_rule( - entry_point_target_name, - entry_point_script_name, - library_name, - ) - ) - - with open(os.path.join(directory, "BUILD.bazel"), "w") as build_file: - additional_content = entry_points - data = [] - data_exclude = pip_data_exclude - srcs_exclude = [] - if annotation: - for src, dest in annotation.copy_files.items(): - data.append(dest) - additional_content.append(generate_copy_commands(src, dest)) - for src, dest in annotation.copy_executables.items(): - data.append(dest) - additional_content.append( - generate_copy_commands(src, dest, is_executable=True) - ) - data.extend(annotation.data) - data_exclude.extend(annotation.data_exclude_glob) - srcs_exclude.extend(annotation.srcs_exclude_glob) - if annotation.additive_build_content: - additional_content.append(annotation.additive_build_content) - - contents = generate_build_file_contents( - name=PY_LIBRARY_LABEL - if incremental - else sanitise_name(whl.name, repo_prefix), - dependencies=sanitised_dependencies, - whl_file_deps=sanitised_wheel_file_dependencies, - data_exclude=data_exclude, - data=data, - srcs_exclude=srcs_exclude, - tags=["pypi_name=" + whl.name, "pypi_version=" + whl.version], - additional_content=additional_content, - ) - build_file.write(contents) - - if not incremental: - os.remove(whl.path) - return f"//{directory}" - return None diff --git a/python/pip_install/extract_wheels/bazel_test.py b/python/pip_install/extract_wheels/bazel_test.py deleted file mode 100644 index 7ecf422227..0000000000 --- a/python/pip_install/extract_wheels/bazel_test.py +++ /dev/null @@ -1,26 +0,0 @@ -import unittest - -from python.pip_install.extract_wheels.bazel import generate_entry_point_contents - - -class BazelTestCase(unittest.TestCase): - def test_generate_entry_point_contents(self): - got = generate_entry_point_contents("sphinx.cmd.build:main") - want = """#!/usr/bin/env python3 -import sys -from sphinx.cmd.build import main -if __name__ == "__main__": - sys.exit(main()) -""" - self.assertEqual(got, want) - - def test_generate_entry_point_contents_with_shebang(self): - got = generate_entry_point_contents( - "sphinx.cmd.build:main", shebang="#!/usr/bin/python" - ) - want = """#!/usr/bin/python -import sys -from sphinx.cmd.build import main -sys.exit(main()) -""" - self.assertEqual(got, want) diff --git a/python/pip_install/extract_wheels/extract_single_wheel.py b/python/pip_install/extract_wheels/extract_single_wheel.py deleted file mode 100644 index ff64291024..0000000000 --- a/python/pip_install/extract_wheels/extract_single_wheel.py +++ /dev/null @@ -1,105 +0,0 @@ -import argparse -import errno -import glob -import os -import subprocess -import sys -from tempfile import NamedTemporaryFile - -from python.pip_install.extract_wheels import arguments, bazel, requirements -from python.pip_install.extract_wheels.annotation import annotation_from_str_path - - -def configure_reproducible_wheels() -> None: - """Modifies the environment to make wheel building reproducible. - Wheels created from sdists are not reproducible by default. We can however workaround this by - patching in some configuration with environment variables. - """ - - # wheel, by default, enables debug symbols in GCC. This incidentally captures the build path in the .so file - # We can override this behavior by disabling debug symbols entirely. - # https://github.com/pypa/pip/issues/6505 - if "CFLAGS" in os.environ: - os.environ["CFLAGS"] += " -g0" - else: - os.environ["CFLAGS"] = "-g0" - - # set SOURCE_DATE_EPOCH to 1980 so that we can use python wheels - # https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/python.section.md#python-setuppy-bdist_wheel-cannot-create-whl - if "SOURCE_DATE_EPOCH" not in os.environ: - os.environ["SOURCE_DATE_EPOCH"] = "315532800" - - # Python wheel metadata files can be unstable. - # See https://bitbucket.org/pypa/wheel/pull-requests/74/make-the-output-of-metadata-files/diff - if "PYTHONHASHSEED" not in os.environ: - os.environ["PYTHONHASHSEED"] = "0" - - -def main() -> None: - parser = argparse.ArgumentParser( - description="Build and/or fetch a single wheel based on the requirement passed in" - ) - parser.add_argument( - "--requirement", - action="store", - required=True, - help="A single PEP508 requirement specifier string.", - ) - parser.add_argument( - "--annotation", - type=annotation_from_str_path, - help="A json encoded file containing annotations for rendered packages.", - ) - arguments.parse_common_args(parser) - args = parser.parse_args() - deserialized_args = dict(vars(args)) - arguments.deserialize_structured_args(deserialized_args) - - configure_reproducible_wheels() - - pip_args = ( - [sys.executable, "-m", "pip"] - + (["--isolated"] if args.isolated else []) - + ["download" if args.download_only else "wheel", "--no-deps"] - + deserialized_args["extra_pip_args"] - ) - - requirement_file = NamedTemporaryFile(mode="wb", delete=False) - try: - requirement_file.write(args.requirement.encode("utf-8")) - requirement_file.flush() - # Close the file so pip is allowed to read it when running on Windows. - # For more information, see: https://bugs.python.org/issue14243 - requirement_file.close() - # Requirement specific args like --hash can only be passed in a requirements file, - # so write our single requirement into a temp file in case it has any of those flags. - pip_args.extend(["-r", requirement_file.name]) - - env = os.environ.copy() - env.update(deserialized_args["environment"]) - # Assumes any errors are logged by pip so do nothing. This command will fail if pip fails - subprocess.run(pip_args, check=True, env=env) - finally: - try: - os.unlink(requirement_file.name) - except OSError as e: - if e.errno != errno.ENOENT: - raise - - name, extras_for_pkg = requirements._parse_requirement_for_extra(args.requirement) - extras = {name: extras_for_pkg} if extras_for_pkg and name else dict() - - whl = next(iter(glob.glob("*.whl"))) - bazel.extract_wheel( - wheel_file=whl, - extras=extras, - pip_data_exclude=deserialized_args["pip_data_exclude"], - enable_implicit_namespace_pkgs=args.enable_implicit_namespace_pkgs, - incremental=True, - repo_prefix=args.repo_prefix, - annotation=args.annotation, - ) - - -if __name__ == "__main__": - main() diff --git a/python/pip_install/extract_wheels/requirements.py b/python/pip_install/extract_wheels/requirements.py deleted file mode 100644 index caf20d0f79..0000000000 --- a/python/pip_install/extract_wheels/requirements.py +++ /dev/null @@ -1,47 +0,0 @@ -import re -from typing import Dict, Optional, Set, Tuple - -from pip._vendor.packaging.utils import canonicalize_name - - -def parse_extras(requirements_path: str) -> Dict[str, Set[str]]: - """Parse over the requirements.txt file to find extras requested. - - Args: - requirements_path: The filepath for the requirements.txt file to parse. - - Returns: - A dictionary mapping the requirement name to a set of extras requested. - """ - - extras_requested = {} - with open(requirements_path, "r") as requirements: - # Merge all backslash line continuations so we parse each requirement as a single line. - for line in requirements.read().replace("\\\n", "").split("\n"): - requirement, extras = _parse_requirement_for_extra(line) - if requirement and extras: - extras_requested[requirement] = extras - - return extras_requested - - -def _parse_requirement_for_extra( - requirement: str, -) -> Tuple[Optional[str], Optional[Set[str]]]: - """Given a requirement string, returns the requirement name and set of extras, if extras specified. - Else, returns (None, None) - """ - - # https://www.python.org/dev/peps/pep-0508/#grammar - extras_pattern = re.compile( - r"^\s*([0-9A-Za-z][0-9A-Za-z_.\-]*)\s*\[\s*([0-9A-Za-z][0-9A-Za-z_.\-]*(?:\s*,\s*[0-9A-Za-z][0-9A-Za-z_.\-]*)*)\s*\]" - ) - - matches = extras_pattern.match(requirement) - if matches: - return ( - canonicalize_name(matches.group(1)), - {extra.strip() for extra in matches.group(2).split(",")}, - ) - - return None, None diff --git a/python/pip_install/extract_wheels/requirements_test.py b/python/pip_install/extract_wheels/requirements_test.py deleted file mode 100644 index 297cd91c38..0000000000 --- a/python/pip_install/extract_wheels/requirements_test.py +++ /dev/null @@ -1,40 +0,0 @@ -import unittest - -from python.pip_install.extract_wheels import requirements - - -class TestRequirementExtrasParsing(unittest.TestCase): - def test_parses_requirement_for_extra(self) -> None: - cases = [ - ("name[foo]", ("name", frozenset(["foo"]))), - ("name[ Foo123 ]", ("name", frozenset(["Foo123"]))), - (" name1[ foo ] ", ("name1", frozenset(["foo"]))), - ("Name[foo]", ("name", frozenset(["foo"]))), - ("name_foo[bar]", ("name-foo", frozenset(["bar"]))), - ( - "name [fred,bar] @ http://foo.com ; python_version=='2.7'", - ("name", frozenset(["fred", "bar"])), - ), - ( - "name[quux, strange];python_version<'2.7' and platform_version=='2'", - ("name", frozenset(["quux", "strange"])), - ), - ( - "name; (os_name=='a' or os_name=='b') and os_name=='c'", - (None, None), - ), - ( - "name@http://foo.com", - (None, None), - ), - ] - - for case, expected in cases: - with self.subTest(): - self.assertTupleEqual( - requirements._parse_requirement_for_extra(case), expected - ) - - -if __name__ == "__main__": - unittest.main() diff --git a/python/pip_install/extract_wheels/wheel_installer.py b/python/pip_install/extract_wheels/wheel_installer.py new file mode 100644 index 0000000000..fe00b5cb66 --- /dev/null +++ b/python/pip_install/extract_wheels/wheel_installer.py @@ -0,0 +1,488 @@ +import argparse +import errno +import glob +import json +import os +import re +import shutil +import subprocess +import sys +import textwrap +from pathlib import Path +from tempfile import NamedTemporaryFile +from typing import Dict, Iterable, List, Optional, Set, Tuple + +from pip._vendor.packaging.utils import canonicalize_name + +from python.pip_install.extract_wheels import ( + annotation, + arguments, + bazel, + namespace_pkgs, + wheel, +) + + +def _configure_reproducible_wheels() -> None: + """Modifies the environment to make wheel building reproducible. + Wheels created from sdists are not reproducible by default. We can however workaround this by + patching in some configuration with environment variables. + """ + + # wheel, by default, enables debug symbols in GCC. This incidentally captures the build path in the .so file + # We can override this behavior by disabling debug symbols entirely. + # https://github.com/pypa/pip/issues/6505 + if "CFLAGS" in os.environ: + os.environ["CFLAGS"] += " -g0" + else: + os.environ["CFLAGS"] = "-g0" + + # set SOURCE_DATE_EPOCH to 1980 so that we can use python wheels + # https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/python.section.md#python-setuppy-bdist_wheel-cannot-create-whl + if "SOURCE_DATE_EPOCH" not in os.environ: + os.environ["SOURCE_DATE_EPOCH"] = "315532800" + + # Python wheel metadata files can be unstable. + # See https://bitbucket.org/pypa/wheel/pull-requests/74/make-the-output-of-metadata-files/diff + if "PYTHONHASHSEED" not in os.environ: + os.environ["PYTHONHASHSEED"] = "0" + + +def _parse_requirement_for_extra( + requirement: str, +) -> Tuple[Optional[str], Optional[Set[str]]]: + """Given a requirement string, returns the requirement name and set of extras, if extras specified. + Else, returns (None, None) + """ + + # https://www.python.org/dev/peps/pep-0508/#grammar + extras_pattern = re.compile( + r"^\s*([0-9A-Za-z][0-9A-Za-z_.\-]*)\s*\[\s*([0-9A-Za-z][0-9A-Za-z_.\-]*(?:\s*,\s*[0-9A-Za-z][0-9A-Za-z_.\-]*)*)\s*\]" + ) + + matches = extras_pattern.match(requirement) + if matches: + return ( + canonicalize_name(matches.group(1)), + {extra.strip() for extra in matches.group(2).split(",")}, + ) + + return None, None + + +def _setup_namespace_pkg_compatibility(wheel_dir: str) -> None: + """Converts native namespace packages to pkgutil-style packages + + Namespace packages can be created in one of three ways. They are detailed here: + https://packaging.python.org/guides/packaging-namespace-packages/#creating-a-namespace-package + + 'pkgutil-style namespace packages' (2) and 'pkg_resources-style namespace packages' (3) works in Bazel, but + 'native namespace packages' (1) do not. + + We ensure compatibility with Bazel of method 1 by converting them into method 2. + + Args: + wheel_dir: the directory of the wheel to convert + """ + + namespace_pkg_dirs = namespace_pkgs.implicit_namespace_packages( + wheel_dir, + ignored_dirnames=["%s/bin" % wheel_dir], + ) + + for ns_pkg_dir in namespace_pkg_dirs: + namespace_pkgs.add_pkgutil_style_namespace_pkg_init(ns_pkg_dir) + + +def _generate_entry_point_contents( + module: str, attribute: str, shebang: str = "#!/usr/bin/env python3" +) -> str: + """Generate the contents of an entry point script. + + Args: + module (str): The name of the module to use. + attribute (str): The name of the attribute to call. + shebang (str, optional): The shebang to use for the entry point python + file. + + Returns: + str: A string of python code. + """ + return textwrap.dedent( + """\ + {shebang} + import sys + from {module} import {attribute} + if __name__ == "__main__": + sys.exit({attribute}()) + """.format( + shebang=shebang, module=module, attribute=attribute + ) + ) + + +def _generate_entry_point_rule(name: str, script: str, pkg: str) -> str: + """Generate a Bazel `py_binary` rule for an entry point script. + + Note that the script is used to determine the name of the target. The name of + entry point targets should be uniuqe to avoid conflicts with existing sources or + directories within a wheel. + + Args: + name (str): The name of the generated py_binary. + script (str): The path to the entry point's python file. + pkg (str): The package owning the entry point. This is expected to + match up with the `py_library` defined for each repository. + + + Returns: + str: A `py_binary` instantiation. + """ + return textwrap.dedent( + """\ + py_binary( + name = "{name}", + srcs = ["{src}"], + # This makes this directory a top-level in the python import + # search path for anything that depends on this. + imports = ["."], + deps = ["{pkg}"], + ) + """.format( + name=name, src=str(script).replace("\\", "/"), pkg=pkg + ) + ) + + +def _generate_copy_commands(src, dest, is_executable=False) -> str: + """Generate a [@bazel_skylib//rules:copy_file.bzl%copy_file][cf] target + + [cf]: https://github.com/bazelbuild/bazel-skylib/blob/1.1.1/docs/copy_file_doc.md + + Args: + src (str): The label for the `src` attribute of [copy_file][cf] + dest (str): The label for the `out` attribute of [copy_file][cf] + is_executable (bool, optional): Whether or not the file being copied is executable. + sets `is_executable` for [copy_file][cf] + + Returns: + str: A `copy_file` instantiation. + """ + return textwrap.dedent( + """\ + copy_file( + name = "{dest}.copy", + src = "{src}", + out = "{dest}", + is_executable = {is_executable}, + ) + """.format( + src=src, + dest=dest, + is_executable=is_executable, + ) + ) + + +def _generate_build_file_contents( + name: str, + dependencies: List[str], + whl_file_deps: List[str], + data_exclude: List[str], + tags: List[str], + srcs_exclude: List[str] = [], + data: List[str] = [], + additional_content: List[str] = [], +) -> str: + """Generate a BUILD file for an unzipped Wheel + + Args: + name: the target name of the py_library + dependencies: a list of Bazel labels pointing to dependencies of the library + whl_file_deps: a list of Bazel labels pointing to wheel file dependencies of this wheel. + data_exclude: more patterns to exclude from the data attribute of generated py_library rules. + tags: list of tags to apply to generated py_library rules. + additional_content: A list of additional content to append to the BUILD file. + + Returns: + A complete BUILD file as a string + + We allow for empty Python sources as for Wheels containing only compiled C code + there may be no Python sources whatsoever (e.g. packages written in Cython: like `pymssql`). + """ + + data_exclude = list( + set( + [ + "**/* *", + "**/*.py", + "**/*.pyc", + # RECORD is known to contain sha256 checksums of files which might include the checksums + # of generated files produced when wheels are installed. The file is ignored to avoid + # Bazel caching issues. + "**/*.dist-info/RECORD", + ] + + data_exclude + ) + ) + + return "\n".join( + [ + textwrap.dedent( + """\ + load("@rules_python//python:defs.bzl", "py_library", "py_binary") + load("@rules_python//third_party/github.com/bazelbuild/bazel-skylib/rules:copy_file.bzl", "copy_file") + + package(default_visibility = ["//visibility:public"]) + + filegroup( + name = "{dist_info_label}", + srcs = glob(["site-packages/*.dist-info/**"], allow_empty = True), + ) + + filegroup( + name = "{data_label}", + srcs = glob(["data/**"], allow_empty = True), + ) + + filegroup( + name = "{whl_file_label}", + srcs = glob(["*.whl"], allow_empty = True), + data = [{whl_file_deps}], + ) + + py_library( + name = "{name}", + srcs = glob(["site-packages/**/*.py"], exclude={srcs_exclude}, allow_empty = True), + data = {data} + glob(["site-packages/**/*"], exclude={data_exclude}), + # This makes this directory a top-level in the python import + # search path for anything that depends on this. + imports = ["site-packages"], + deps = [{dependencies}], + tags = [{tags}], + ) + """.format( + name=name, + dependencies=",".join(sorted(dependencies)), + data_exclude=json.dumps(sorted(data_exclude)), + whl_file_label=bazel.WHEEL_FILE_LABEL, + whl_file_deps=",".join(sorted(whl_file_deps)), + tags=",".join(sorted(['"%s"' % t for t in tags])), + data_label=bazel.DATA_LABEL, + dist_info_label=bazel.DIST_INFO_LABEL, + entry_point_prefix=bazel.WHEEL_ENTRY_POINT_PREFIX, + srcs_exclude=json.dumps(sorted(srcs_exclude)), + data=json.dumps(sorted(data)), + ) + ) + ] + + additional_content + ) + + +def _sanitised_library_label(whl_name: str, prefix: str) -> str: + return '"//%s"' % bazel.sanitise_name(whl_name, prefix) + + +def _sanitised_file_label(whl_name: str, prefix: str) -> str: + return '"//%s:%s"' % (bazel.sanitise_name(whl_name, prefix), bazel.WHEEL_FILE_LABEL) + + +def _extract_wheel( + wheel_file: str, + extras: Dict[str, Set[str]], + pip_data_exclude: List[str], + enable_implicit_namespace_pkgs: bool, + repo_prefix: str, + incremental: bool = False, + incremental_dir: Path = Path("."), + annotation: Optional[annotation.Annotation] = None, +) -> Optional[str]: + """Extracts wheel into given directory and creates py_library and filegroup targets. + + Args: + wheel_file: the filepath of the .whl + extras: a list of extras to add as dependencies for the installed wheel + pip_data_exclude: list of file patterns to exclude from the generated data section of the py_library + enable_implicit_namespace_pkgs: if true, disables conversion of implicit namespace packages and will unzip as-is + incremental: If true the extract the wheel in a format suitable for an external repository. This + effects the names of libraries and their dependencies, which point to other external repositories. + incremental_dir: An optional override for the working directory of incremental builds. + annotation: An optional set of annotations to apply to the BUILD contents of the wheel. + + Returns: + The Bazel label for the extracted wheel, in the form '//path/to/wheel'. + """ + + whl = wheel.Wheel(wheel_file) + if incremental: + directory = incremental_dir + else: + directory = bazel.sanitise_name(whl.name, prefix=repo_prefix) + + os.mkdir(directory) + # copy the original wheel + shutil.copy(whl.path, directory) + whl.unzip(directory) + + if not enable_implicit_namespace_pkgs: + _setup_namespace_pkg_compatibility(directory) + + extras_requested = extras[whl.name] if whl.name in extras else set() + # Packages may create dependency cycles when specifying optional-dependencies / 'extras'. + # Example: github.com/google/etils/blob/a0b71032095db14acf6b33516bca6d885fe09e35/pyproject.toml#L32. + self_edge_dep = set([whl.name]) + whl_deps = sorted(whl.dependencies(extras_requested) - self_edge_dep) + + if incremental: + sanitised_dependencies = [ + bazel.sanitised_repo_library_label(d, repo_prefix=repo_prefix) + for d in whl_deps + ] + sanitised_wheel_file_dependencies = [ + bazel.sanitised_repo_file_label(d, repo_prefix=repo_prefix) + for d in whl_deps + ] + else: + sanitised_dependencies = [ + _sanitised_library_label(d, prefix=repo_prefix) for d in whl_deps + ] + sanitised_wheel_file_dependencies = [ + _sanitised_file_label(d, prefix=repo_prefix) for d in whl_deps + ] + + library_name = ( + bazel.PY_LIBRARY_LABEL + if incremental + else bazel.sanitise_name(whl.name, repo_prefix) + ) + + directory_path = Path(directory) + entry_points = [] + for name, (module, attribute) in sorted(whl.entry_points().items()): + # There is an extreme edge-case with entry_points that end with `.py` + # See: https://github.com/bazelbuild/bazel/blob/09c621e4cf5b968f4c6cdf905ab142d5961f9ddc/src/test/java/com/google/devtools/build/lib/rules/python/PyBinaryConfiguredTargetTest.java#L174 + entry_point_without_py = f"{name[:-3]}_py" if name.endswith(".py") else name + entry_point_target_name = ( + f"{bazel.WHEEL_ENTRY_POINT_PREFIX}_{entry_point_without_py}" + ) + entry_point_script_name = f"{entry_point_target_name}.py" + (directory_path / entry_point_script_name).write_text( + _generate_entry_point_contents(module, attribute) + ) + entry_points.append( + _generate_entry_point_rule( + entry_point_target_name, + entry_point_script_name, + library_name, + ) + ) + + with open(os.path.join(directory, "BUILD.bazel"), "w") as build_file: + additional_content = entry_points + data = [] + data_exclude = pip_data_exclude + srcs_exclude = [] + if annotation: + for src, dest in annotation.copy_files.items(): + data.append(dest) + additional_content.append(_generate_copy_commands(src, dest)) + for src, dest in annotation.copy_executables.items(): + data.append(dest) + additional_content.append( + _generate_copy_commands(src, dest, is_executable=True) + ) + data.extend(annotation.data) + data_exclude.extend(annotation.data_exclude_glob) + srcs_exclude.extend(annotation.srcs_exclude_glob) + if annotation.additive_build_content: + additional_content.append(annotation.additive_build_content) + + contents = _generate_build_file_contents( + name=bazel.PY_LIBRARY_LABEL + if incremental + else bazel.sanitise_name(whl.name, repo_prefix), + dependencies=sanitised_dependencies, + whl_file_deps=sanitised_wheel_file_dependencies, + data_exclude=data_exclude, + data=data, + srcs_exclude=srcs_exclude, + tags=["pypi_name=" + whl.name, "pypi_version=" + whl.version], + additional_content=additional_content, + ) + build_file.write(contents) + + if not incremental: + os.remove(whl.path) + return f"//{directory}" + return None + + +def main() -> None: + parser = argparse.ArgumentParser( + description="Build and/or fetch a single wheel based on the requirement passed in" + ) + parser.add_argument( + "--requirement", + action="store", + required=True, + help="A single PEP508 requirement specifier string.", + ) + parser.add_argument( + "--annotation", + type=annotation.annotation_from_str_path, + help="A json encoded file containing annotations for rendered packages.", + ) + arguments.parse_common_args(parser) + args = parser.parse_args() + deserialized_args = dict(vars(args)) + arguments.deserialize_structured_args(deserialized_args) + + _configure_reproducible_wheels() + + pip_args = ( + [sys.executable, "-m", "pip"] + + (["--isolated"] if args.isolated else []) + + ["download" if args.download_only else "wheel", "--no-deps"] + + deserialized_args["extra_pip_args"] + ) + + requirement_file = NamedTemporaryFile(mode="wb", delete=False) + try: + requirement_file.write(args.requirement.encode("utf-8")) + requirement_file.flush() + # Close the file so pip is allowed to read it when running on Windows. + # For more information, see: https://bugs.python.org/issue14243 + requirement_file.close() + # Requirement specific args like --hash can only be passed in a requirements file, + # so write our single requirement into a temp file in case it has any of those flags. + pip_args.extend(["-r", requirement_file.name]) + + env = os.environ.copy() + env.update(deserialized_args["environment"]) + # Assumes any errors are logged by pip so do nothing. This command will fail if pip fails + subprocess.run(pip_args, check=True, env=env) + finally: + try: + os.unlink(requirement_file.name) + except OSError as e: + if e.errno != errno.ENOENT: + raise + + name, extras_for_pkg = _parse_requirement_for_extra(args.requirement) + extras = {name: extras_for_pkg} if extras_for_pkg and name else dict() + + whl = next(iter(glob.glob("*.whl"))) + _extract_wheel( + wheel_file=whl, + extras=extras, + pip_data_exclude=deserialized_args["pip_data_exclude"], + enable_implicit_namespace_pkgs=args.enable_implicit_namespace_pkgs, + incremental=True, + repo_prefix=args.repo_prefix, + annotation=args.annotation, + ) + + +if __name__ == "__main__": + main() diff --git a/python/pip_install/extract_wheels/wheel_installer_test.py b/python/pip_install/extract_wheels/wheel_installer_test.py new file mode 100644 index 0000000000..59a5ed19bd --- /dev/null +++ b/python/pip_install/extract_wheels/wheel_installer_test.py @@ -0,0 +1,110 @@ +import os +import shutil +import tempfile +import unittest +from pathlib import Path + +from python.pip_install.extract_wheels import wheel_installer + + +class TestRequirementExtrasParsing(unittest.TestCase): + def test_parses_requirement_for_extra(self) -> None: + cases = [ + ("name[foo]", ("name", frozenset(["foo"]))), + ("name[ Foo123 ]", ("name", frozenset(["Foo123"]))), + (" name1[ foo ] ", ("name1", frozenset(["foo"]))), + ("Name[foo]", ("name", frozenset(["foo"]))), + ("name_foo[bar]", ("name-foo", frozenset(["bar"]))), + ( + "name [fred,bar] @ http://foo.com ; python_version=='2.7'", + ("name", frozenset(["fred", "bar"])), + ), + ( + "name[quux, strange];python_version<'2.7' and platform_version=='2'", + ("name", frozenset(["quux", "strange"])), + ), + ( + "name; (os_name=='a' or os_name=='b') and os_name=='c'", + (None, None), + ), + ( + "name@http://foo.com", + (None, None), + ), + ] + + for case, expected in cases: + with self.subTest(): + self.assertTupleEqual( + wheel_installer._parse_requirement_for_extra(case), expected + ) + + +class BazelTestCase(unittest.TestCase): + def test_generate_entry_point_contents(self): + got = wheel_installer._generate_entry_point_contents("sphinx.cmd.build", "main") + want = """#!/usr/bin/env python3 +import sys +from sphinx.cmd.build import main +if __name__ == "__main__": + sys.exit(main()) +""" + self.assertEqual(got, want) + + def test_generate_entry_point_contents_with_shebang(self): + got = wheel_installer._generate_entry_point_contents( + "sphinx.cmd.build", "main", shebang="#!/usr/bin/python" + ) + want = """#!/usr/bin/python +import sys +from sphinx.cmd.build import main +if __name__ == "__main__": + sys.exit(main()) +""" + self.assertEqual(got, want) + + +class TestWhlFilegroup(unittest.TestCase): + def setUp(self) -> None: + self.wheel_name = "example_minimal_package-0.0.1-py3-none-any.whl" + self.wheel_dir = tempfile.mkdtemp() + self.wheel_path = os.path.join(self.wheel_dir, self.wheel_name) + shutil.copy(os.path.join("examples", "wheel", self.wheel_name), self.wheel_dir) + + def tearDown(self): + shutil.rmtree(self.wheel_dir) + + def _run( + self, + repo_prefix: str, + incremental: bool = False, + ) -> None: + generated_bazel_dir = wheel_installer._extract_wheel( + self.wheel_path, + extras={}, + pip_data_exclude=[], + enable_implicit_namespace_pkgs=False, + incremental=incremental, + repo_prefix=repo_prefix, + incremental_dir=Path(self.wheel_dir), + ) + # Take off the leading // from the returned label. + # Assert that the raw wheel ends up in the package. + generated_bazel_dir = ( + generated_bazel_dir[2:] if not incremental else self.wheel_dir + ) + + self.assertIn(self.wheel_name, os.listdir(generated_bazel_dir)) + with open("{}/BUILD.bazel".format(generated_bazel_dir)) as build_file: + build_file_content = build_file.read() + self.assertIn("filegroup", build_file_content) + + def test_nonincremental(self) -> None: + self._run(repo_prefix="prefix_") + + def test_incremental(self) -> None: + self._run(incremental=True, repo_prefix="prefix_") + + +if __name__ == "__main__": + unittest.main() diff --git a/python/pip_install/extract_wheels/whl_filegroup_test.py b/python/pip_install/extract_wheels/whl_filegroup_test.py deleted file mode 100644 index 2a7ade3b27..0000000000 --- a/python/pip_install/extract_wheels/whl_filegroup_test.py +++ /dev/null @@ -1,53 +0,0 @@ -import os -import shutil -import tempfile -import unittest -from pathlib import Path - -from python.pip_install.extract_wheels import bazel - - -class TestWhlFilegroup(unittest.TestCase): - def setUp(self) -> None: - self.wheel_name = "example_minimal_package-0.0.1-py3-none-any.whl" - self.wheel_dir = tempfile.mkdtemp() - self.wheel_path = os.path.join(self.wheel_dir, self.wheel_name) - shutil.copy(os.path.join("examples", "wheel", self.wheel_name), self.wheel_dir) - - def tearDown(self): - shutil.rmtree(self.wheel_dir) - - def _run( - self, - repo_prefix: str, - incremental: bool = False, - ) -> None: - generated_bazel_dir = bazel.extract_wheel( - self.wheel_path, - extras={}, - pip_data_exclude=[], - enable_implicit_namespace_pkgs=False, - incremental=incremental, - repo_prefix=repo_prefix, - incremental_dir=Path(self.wheel_dir), - ) - # Take off the leading // from the returned label. - # Assert that the raw wheel ends up in the package. - generated_bazel_dir = ( - generated_bazel_dir[2:] if not incremental else self.wheel_dir - ) - - self.assertIn(self.wheel_name, os.listdir(generated_bazel_dir)) - with open("{}/BUILD.bazel".format(generated_bazel_dir)) as build_file: - build_file_content = build_file.read() - self.assertIn("filegroup", build_file_content) - - def test_nonincremental(self) -> None: - self._run(repo_prefix="prefix_") - - def test_incremental(self) -> None: - self._run(incremental=True, repo_prefix="prefix_") - - -if __name__ == "__main__": - unittest.main() diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl index 7fbf503992..101ec6a687 100644 --- a/python/pip_install/pip_repository.bzl +++ b/python/pip_install/pip_repository.bzl @@ -522,7 +522,7 @@ def _whl_library_impl(rctx): args = [ python_interpreter, "-m", - "python.pip_install.extract_wheels.extract_single_wheel", + "python.pip_install.extract_wheels.wheel_installer", "--requirement", rctx.attr.requirement, "--repo", diff --git a/python/pip_install/private/srcs.bzl b/python/pip_install/private/srcs.bzl index e42bb8e5ed..89bd55d43c 100644 --- a/python/pip_install/private/srcs.bzl +++ b/python/pip_install/private/srcs.bzl @@ -11,9 +11,8 @@ PIP_INSTALL_PY_SRCS = [ "@rules_python//python/pip_install/extract_wheels:annotation.py", "@rules_python//python/pip_install/extract_wheels:arguments.py", "@rules_python//python/pip_install/extract_wheels:bazel.py", - "@rules_python//python/pip_install/extract_wheels:extract_single_wheel.py", "@rules_python//python/pip_install/extract_wheels:namespace_pkgs.py", "@rules_python//python/pip_install/extract_wheels:parse_requirements_to_bzl.py", - "@rules_python//python/pip_install/extract_wheels:requirements.py", "@rules_python//python/pip_install/extract_wheels:wheel.py", + "@rules_python//python/pip_install/extract_wheels:wheel_installer.py", ] diff --git a/tools/bazel_integration_test/test_runner.py b/tools/bazel_integration_test/test_runner.py index 31bb62792e..fbc27e4d4b 100644 --- a/tools/bazel_integration_test/test_runner.py +++ b/tools/bazel_integration_test/test_runner.py @@ -56,7 +56,7 @@ def main(conf_file): # TODO: --override_module isn't supported in the current BAZEL_VERSION (5.2.0) # This condition and attribute can be removed when bazel is updated for # the rest of rules_python. - if (config["bzlmod"]): + if config["bzlmod"]: bazel_args.append( "--override_module=rules_python=%s/rules_python" % os.environ["TEST_SRCDIR"] diff --git a/tools/wheelmaker.py b/tools/wheelmaker.py index d5179001a6..7d65706f13 100644 --- a/tools/wheelmaker.py +++ b/tools/wheelmaker.py @@ -275,7 +275,7 @@ def parse_args() -> argparse.Namespace: action="append", default=[], help="Path prefix to be stripped from input package files' path. " - "Can be supplied multiple times. Evaluated in order.", + "Can be supplied multiple times. Evaluated in order.", ) wheel_group = parser.add_argument_group("Wheel metadata") @@ -283,7 +283,7 @@ def parse_args() -> argparse.Namespace: "--metadata_file", type=Path, help="Contents of the METADATA file (before appending contents of " - "--description_file)", + "--description_file)", ) wheel_group.add_argument( "--description_file", help="Path to the file with package description" @@ -381,12 +381,12 @@ def main() -> None: description = None if arguments.description_file: if sys.version_info[0] == 2: - with open(arguments.description_file, - "rt") as description_file: + with open(arguments.description_file, "rt") as description_file: description = description_file.read() else: - with open(arguments.description_file, "rt", - encoding="utf-8") as description_file: + with open( + arguments.description_file, "rt", encoding="utf-8" + ) as description_file: description = description_file.read() metadata = None @@ -394,8 +394,7 @@ def main() -> None: with open(arguments.metadata_file, "rt") as metadata_file: metadata = metadata_file.read() else: - with open(arguments.metadata_file, "rt", - encoding="utf-8") as metadata_file: + with open(arguments.metadata_file, "rt", encoding="utf-8") as metadata_file: metadata = metadata_file.read() maker.add_metadata(metadata=metadata, description=description) From bcd71099d16bba08fd321158597424cde907b62c Mon Sep 17 00:00:00 2001 From: Greg Roodt Date: Sat, 24 Dec 2022 11:49:35 +1100 Subject: [PATCH 090/234] Updates lockfiles (#943) --- examples/build_file_generation/BUILD | 2 +- .../build_file_generation/gazelle_python.yaml | 2 +- .../{requirements.txt => requirements.in} | 0 .../requirements_lock.txt | 8 +-- .../requirements_windows.txt | 8 +-- examples/bzlmod/requirements_lock.txt | 55 +++++++++++-------- examples/bzlmod/requirements_windows.txt | 55 +++++++++++-------- examples/pip_install/pip_install_test.py | 14 ++--- examples/pip_install/requirements.txt | 31 +++++++---- examples/pip_install/requirements_windows.txt | 31 +++++++---- examples/pip_parse/requirements_lock.txt | 37 ++++++++----- examples/pip_parse_vendored/requirements.bzl | 2 +- examples/pip_parse_vendored/requirements.txt | 30 +++++----- .../pip_repository_annotations_test.py | 2 +- .../requirements.txt | 18 +++--- 15 files changed, 165 insertions(+), 130 deletions(-) rename examples/build_file_generation/{requirements.txt => requirements.in} (100%) diff --git a/examples/build_file_generation/BUILD b/examples/build_file_generation/BUILD index 34449f31e6..6a921a27b5 100644 --- a/examples/build_file_generation/BUILD +++ b/examples/build_file_generation/BUILD @@ -13,7 +13,7 @@ load("@rules_python//python:pip.bzl", "compile_pip_requirements") compile_pip_requirements( name = "requirements", extra_args = ["--allow-unsafe"], - requirements_in = "requirements.txt", + requirements_in = "requirements.in", requirements_txt = "requirements_lock.txt", requirements_windows = "requirements_windows.txt", ) diff --git a/examples/build_file_generation/gazelle_python.yaml b/examples/build_file_generation/gazelle_python.yaml index 46d1d641de..29ea035bfc 100644 --- a/examples/build_file_generation/gazelle_python.yaml +++ b/examples/build_file_generation/gazelle_python.yaml @@ -115,4 +115,4 @@ manifest: pip_repository: name: pip incremental: true -integrity: 9bb7b166e9358f3244c9beae2a863084fe4e58c31d3ccb65618dd471512fdb5e +integrity: 09dd75cd2f440c85abc6f823ba412331dcad5f348cbb4dc38641122ccf08d1d7 diff --git a/examples/build_file_generation/requirements.txt b/examples/build_file_generation/requirements.in similarity index 100% rename from examples/build_file_generation/requirements.txt rename to examples/build_file_generation/requirements.in diff --git a/examples/build_file_generation/requirements_lock.txt b/examples/build_file_generation/requirements_lock.txt index f4a29bdefc..eb324b2c4a 100644 --- a/examples/build_file_generation/requirements_lock.txt +++ b/examples/build_file_generation/requirements_lock.txt @@ -11,10 +11,10 @@ click==8.1.3 \ flask==2.2.2 \ --hash=sha256:642c450d19c4ad482f96729bd2a8f6d32554aa1e231f4f6b4e7e5264b16cca2b \ --hash=sha256:b9c46cc36662a7949f34b52d8ec7bb59c0d74ba08ba6cb9ce9adc1d8676d9526 - # via -r ./requirements.txt -importlib-metadata==5.1.0 \ - --hash=sha256:d5059f9f1e8e41f80e9c56c2ee58811450c31984dfa625329ffd7c0dad88a73b \ - --hash=sha256:d84d17e21670ec07990e1044a99efe8d615d860fd176fc29ef5c306068fda313 + # via -r ./requirements.in +importlib-metadata==5.2.0 \ + --hash=sha256:0eafa39ba42bf225fc00e67f701d71f85aead9f878569caf13c3724f704b970f \ + --hash=sha256:404d48d62bba0b7a77ff9d405efd91501bef2e67ff4ace0bed40a0cf28c3c7cd # via flask itsdangerous==2.1.2 \ --hash=sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44 \ diff --git a/examples/build_file_generation/requirements_windows.txt b/examples/build_file_generation/requirements_windows.txt index 4f6d590b7c..f1b82f99cb 100644 --- a/examples/build_file_generation/requirements_windows.txt +++ b/examples/build_file_generation/requirements_windows.txt @@ -15,10 +15,10 @@ colorama==0.4.6 \ flask==2.2.2 \ --hash=sha256:642c450d19c4ad482f96729bd2a8f6d32554aa1e231f4f6b4e7e5264b16cca2b \ --hash=sha256:b9c46cc36662a7949f34b52d8ec7bb59c0d74ba08ba6cb9ce9adc1d8676d9526 - # via -r ./requirements.txt -importlib-metadata==5.1.0 \ - --hash=sha256:d5059f9f1e8e41f80e9c56c2ee58811450c31984dfa625329ffd7c0dad88a73b \ - --hash=sha256:d84d17e21670ec07990e1044a99efe8d615d860fd176fc29ef5c306068fda313 + # via -r ./requirements.in +importlib-metadata==5.2.0 \ + --hash=sha256:0eafa39ba42bf225fc00e67f701d71f85aead9f878569caf13c3724f704b970f \ + --hash=sha256:404d48d62bba0b7a77ff9d405efd91501bef2e67ff4ace0bed40a0cf28c3c7cd # via flask itsdangerous==2.1.2 \ --hash=sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44 \ diff --git a/examples/bzlmod/requirements_lock.txt b/examples/bzlmod/requirements_lock.txt index 7126942665..b0023380e9 100644 --- a/examples/bzlmod/requirements_lock.txt +++ b/examples/bzlmod/requirements_lock.txt @@ -8,9 +8,9 @@ astroid==2.12.13 \ --hash=sha256:10e0ad5f7b79c435179d0d0f0df69998c4eef4597534aae44910db060baeb907 \ --hash=sha256:1493fe8bd3dfd73dc35bd53c9d5b6e49ead98497c47b2307662556a5692d29d7 # via pylint -certifi==2021.10.8 \ - --hash=sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872 \ - --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569 +certifi==2022.12.7 \ + --hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \ + --hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18 # via requests chardet==4.0.0 \ --hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa \ @@ -24,9 +24,9 @@ idna==2.10 \ --hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 \ --hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0 # via requests -isort==5.10.1 \ - --hash=sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7 \ - --hash=sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951 +isort==5.11.4 \ + --hash=sha256:6db30c5ded9815d813932c04c2f85a360bcdd35fed496f4d8f35495ef0a261b6 \ + --hash=sha256:c033fd0edb91000a7f09527fe5c75321878f98322a77ddcc81adbd83724afb7b # via pylint lazy-object-proxy==1.8.0 \ --hash=sha256:0c1c7c0433154bb7c54185714c6929acc0ba04ee1b167314a779b9025517eada \ @@ -53,27 +53,28 @@ mccabe==0.7.0 \ --hash=sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325 \ --hash=sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e # via pylint -pathspec==0.9.0 \ - --hash=sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a \ - --hash=sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1 +pathspec==0.10.3 \ + --hash=sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6 \ + --hash=sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6 # via yamllint -platformdirs==2.5.4 \ - --hash=sha256:1006647646d80f16130f052404c6b901e80ee4ed6bef6792e1f238a8969106f7 \ - --hash=sha256:af0276409f9a02373d540bf8480021a048711d572745aef4b7842dad245eba10 +platformdirs==2.6.0 \ + --hash=sha256:1a89a12377800c81983db6be069ec068eee989748799b946cce2a6e80dcc54ca \ + --hash=sha256:b46ffafa316e6b83b47489d240ce17173f123a9b9c83282141c3daf26ad9ac2e # via pylint -pylint==2.15.6 \ - --hash=sha256:15060cc22ed6830a4049cf40bc24977744df2e554d38da1b2657591de5bcd052 \ - --hash=sha256:25b13ddcf5af7d112cf96935e21806c1da60e676f952efb650130f2a4483421c +pylint==2.15.9 \ + --hash=sha256:18783cca3cfee5b83c6c5d10b3cdb66c6594520ffae61890858fe8d932e1c6b4 \ + --hash=sha256:349c8cd36aede4d50a0754a8c0218b43323d13d5d88f4b2952ddfe3e169681eb # via -r ./requirements.in python-dateutil==2.8.2 \ --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 # via s3cmd -python-magic==0.4.24 \ - --hash=sha256:4fec8ee805fea30c07afccd1592c0f17977089895bdfaae5fec870a84e997626 \ - --hash=sha256:de800df9fb50f8ec5974761054a708af6e4246b03b4bdaee993f948947b0ebcf +python-magic==0.4.27 \ + --hash=sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b \ + --hash=sha256:c212960ad306f700aa0d01e5d7a325d20548ff97eb9920dcd29513174f0294d3 # via s3cmd pyyaml==6.0 \ + --hash=sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf \ --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ @@ -85,26 +86,32 @@ pyyaml==6.0 \ --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ + --hash=sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782 \ --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ + --hash=sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1 \ --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ + --hash=sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d \ --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ + --hash=sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7 \ --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ + --hash=sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358 \ --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ + --hash=sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f \ --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 # via yamllint @@ -138,9 +145,9 @@ typing-extensions==4.4.0 \ # via # astroid # pylint -urllib3==1.26.7 \ - --hash=sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece \ - --hash=sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844 +urllib3==1.26.13 \ + --hash=sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc \ + --hash=sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8 # via requests wrapt==1.14.1 \ --hash=sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3 \ @@ -214,7 +221,7 @@ yamllint==1.28.0 \ # via -r ./requirements.in # The following packages are considered to be unsafe in a requirements file: -setuptools==59.6.0 \ - --hash=sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373 \ - --hash=sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e +setuptools==65.6.3 \ + --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ + --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 # via yamllint diff --git a/examples/bzlmod/requirements_windows.txt b/examples/bzlmod/requirements_windows.txt index 55fa92d544..8637fd7958 100644 --- a/examples/bzlmod/requirements_windows.txt +++ b/examples/bzlmod/requirements_windows.txt @@ -8,9 +8,9 @@ astroid==2.12.13 \ --hash=sha256:10e0ad5f7b79c435179d0d0f0df69998c4eef4597534aae44910db060baeb907 \ --hash=sha256:1493fe8bd3dfd73dc35bd53c9d5b6e49ead98497c47b2307662556a5692d29d7 # via pylint -certifi==2021.10.8 \ - --hash=sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872 \ - --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569 +certifi==2022.12.7 \ + --hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \ + --hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18 # via requests chardet==4.0.0 \ --hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa \ @@ -28,9 +28,9 @@ idna==2.10 \ --hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 \ --hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0 # via requests -isort==5.10.1 \ - --hash=sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7 \ - --hash=sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951 +isort==5.11.4 \ + --hash=sha256:6db30c5ded9815d813932c04c2f85a360bcdd35fed496f4d8f35495ef0a261b6 \ + --hash=sha256:c033fd0edb91000a7f09527fe5c75321878f98322a77ddcc81adbd83724afb7b # via pylint lazy-object-proxy==1.8.0 \ --hash=sha256:0c1c7c0433154bb7c54185714c6929acc0ba04ee1b167314a779b9025517eada \ @@ -57,27 +57,28 @@ mccabe==0.7.0 \ --hash=sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325 \ --hash=sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e # via pylint -pathspec==0.9.0 \ - --hash=sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a \ - --hash=sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1 +pathspec==0.10.3 \ + --hash=sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6 \ + --hash=sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6 # via yamllint -platformdirs==2.5.4 \ - --hash=sha256:1006647646d80f16130f052404c6b901e80ee4ed6bef6792e1f238a8969106f7 \ - --hash=sha256:af0276409f9a02373d540bf8480021a048711d572745aef4b7842dad245eba10 +platformdirs==2.6.0 \ + --hash=sha256:1a89a12377800c81983db6be069ec068eee989748799b946cce2a6e80dcc54ca \ + --hash=sha256:b46ffafa316e6b83b47489d240ce17173f123a9b9c83282141c3daf26ad9ac2e # via pylint -pylint==2.15.6 \ - --hash=sha256:15060cc22ed6830a4049cf40bc24977744df2e554d38da1b2657591de5bcd052 \ - --hash=sha256:25b13ddcf5af7d112cf96935e21806c1da60e676f952efb650130f2a4483421c +pylint==2.15.9 \ + --hash=sha256:18783cca3cfee5b83c6c5d10b3cdb66c6594520ffae61890858fe8d932e1c6b4 \ + --hash=sha256:349c8cd36aede4d50a0754a8c0218b43323d13d5d88f4b2952ddfe3e169681eb # via -r ./requirements.in python-dateutil==2.8.2 \ --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 # via s3cmd -python-magic==0.4.24 \ - --hash=sha256:4fec8ee805fea30c07afccd1592c0f17977089895bdfaae5fec870a84e997626 \ - --hash=sha256:de800df9fb50f8ec5974761054a708af6e4246b03b4bdaee993f948947b0ebcf +python-magic==0.4.27 \ + --hash=sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b \ + --hash=sha256:c212960ad306f700aa0d01e5d7a325d20548ff97eb9920dcd29513174f0294d3 # via s3cmd pyyaml==6.0 \ + --hash=sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf \ --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ @@ -89,26 +90,32 @@ pyyaml==6.0 \ --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ + --hash=sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782 \ --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ + --hash=sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1 \ --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ + --hash=sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d \ --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ + --hash=sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7 \ --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ + --hash=sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358 \ --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ + --hash=sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f \ --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 # via yamllint @@ -142,9 +149,9 @@ typing-extensions==4.4.0 \ # via # astroid # pylint -urllib3==1.26.7 \ - --hash=sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece \ - --hash=sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844 +urllib3==1.26.13 \ + --hash=sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc \ + --hash=sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8 # via requests wrapt==1.14.1 \ --hash=sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3 \ @@ -218,7 +225,7 @@ yamllint==1.28.0 \ # via -r ./requirements.in # The following packages are considered to be unsafe in a requirements file: -setuptools==59.6.0 \ - --hash=sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373 \ - --hash=sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e +setuptools==65.6.3 \ + --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ + --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 # via yamllint diff --git a/examples/pip_install/pip_install_test.py b/examples/pip_install/pip_install_test.py index 9fe51fa3a4..1746b5da63 100644 --- a/examples/pip_install/pip_install_test.py +++ b/examples/pip_install/pip_install_test.py @@ -51,13 +51,13 @@ def test_dist_info(self): self.assertListEqual( env.split(" "), [ - "external/pip_boto3/site-packages/boto3-1.14.51.dist-info/DESCRIPTION.rst", - "external/pip_boto3/site-packages/boto3-1.14.51.dist-info/INSTALLER", - "external/pip_boto3/site-packages/boto3-1.14.51.dist-info/METADATA", - "external/pip_boto3/site-packages/boto3-1.14.51.dist-info/RECORD", - "external/pip_boto3/site-packages/boto3-1.14.51.dist-info/WHEEL", - "external/pip_boto3/site-packages/boto3-1.14.51.dist-info/metadata.json", - "external/pip_boto3/site-packages/boto3-1.14.51.dist-info/top_level.txt", + "external/pip_boto3/site-packages/boto3-1.14.63.dist-info/DESCRIPTION.rst", + "external/pip_boto3/site-packages/boto3-1.14.63.dist-info/INSTALLER", + "external/pip_boto3/site-packages/boto3-1.14.63.dist-info/METADATA", + "external/pip_boto3/site-packages/boto3-1.14.63.dist-info/RECORD", + "external/pip_boto3/site-packages/boto3-1.14.63.dist-info/WHEEL", + "external/pip_boto3/site-packages/boto3-1.14.63.dist-info/metadata.json", + "external/pip_boto3/site-packages/boto3-1.14.63.dist-info/top_level.txt", ], ) diff --git a/examples/pip_install/requirements.txt b/examples/pip_install/requirements.txt index 8a06da02b6..89fd989acb 100644 --- a/examples/pip_install/requirements.txt +++ b/examples/pip_install/requirements.txt @@ -4,9 +4,9 @@ # # bazel run //:requirements.update # -boto3==1.14.51 \ - --hash=sha256:a6bdb808e948bd264af135af50efb76253e85732c451fa605b7a287faf022432 \ - --hash=sha256:f9dbccbcec916051c6588adbccae86547308ac4cd154f1eb7cf6422f0e391a71 +boto3==1.14.63 \ + --hash=sha256:25c716b7c01d4664027afc6a6418a06459e311a610c7fd39a030a1ced1b72ce4 \ + --hash=sha256:37158c37a151eab5b9080968305621a40168171fda9584d50a309ceb4e5e6964 # via -r ./requirements.in botocore==1.17.63 \ --hash=sha256:40f13f6c9c29c307a9dc5982739e537ddce55b29787b90c3447b507e3283bcd6 \ @@ -25,9 +25,9 @@ jmespath==0.10.0 \ # via # boto3 # botocore -pathspec==0.9.0 \ - --hash=sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a \ - --hash=sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1 +pathspec==0.10.3 \ + --hash=sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6 \ + --hash=sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6 # via yamllint python-dateutil==2.8.2 \ --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ @@ -35,11 +35,12 @@ python-dateutil==2.8.2 \ # via # botocore # s3cmd -python-magic==0.4.24 \ - --hash=sha256:4fec8ee805fea30c07afccd1592c0f17977089895bdfaae5fec870a84e997626 \ - --hash=sha256:de800df9fb50f8ec5974761054a708af6e4246b03b4bdaee993f948947b0ebcf +python-magic==0.4.27 \ + --hash=sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b \ + --hash=sha256:c212960ad306f700aa0d01e5d7a325d20548ff97eb9920dcd29513174f0294d3 # via s3cmd pyyaml==6.0 \ + --hash=sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf \ --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ @@ -51,26 +52,32 @@ pyyaml==6.0 \ --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ + --hash=sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782 \ --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ + --hash=sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1 \ --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ + --hash=sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d \ --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ + --hash=sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7 \ --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ + --hash=sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358 \ --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ + --hash=sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f \ --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 # via yamllint @@ -99,7 +106,7 @@ yamllint==1.26.3 \ # via -r ./requirements.in # The following packages are considered to be unsafe in a requirements file: -setuptools==59.6.0 \ - --hash=sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373 \ - --hash=sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e +setuptools==65.6.3 \ + --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ + --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 # via yamllint diff --git a/examples/pip_install/requirements_windows.txt b/examples/pip_install/requirements_windows.txt index 09a6a83c5d..6badd5951e 100644 --- a/examples/pip_install/requirements_windows.txt +++ b/examples/pip_install/requirements_windows.txt @@ -4,9 +4,9 @@ # # bazel run //:requirements.update # -boto3==1.14.51 \ - --hash=sha256:a6bdb808e948bd264af135af50efb76253e85732c451fa605b7a287faf022432 \ - --hash=sha256:f9dbccbcec916051c6588adbccae86547308ac4cd154f1eb7cf6422f0e391a71 +boto3==1.14.63 \ + --hash=sha256:25c716b7c01d4664027afc6a6418a06459e311a610c7fd39a030a1ced1b72ce4 \ + --hash=sha256:37158c37a151eab5b9080968305621a40168171fda9584d50a309ceb4e5e6964 # via -r ./requirements.in botocore==1.17.63 \ --hash=sha256:40f13f6c9c29c307a9dc5982739e537ddce55b29787b90c3447b507e3283bcd6 \ @@ -25,9 +25,9 @@ jmespath==0.10.0 \ # via # boto3 # botocore -pathspec==0.9.0 \ - --hash=sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a \ - --hash=sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1 +pathspec==0.10.3 \ + --hash=sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6 \ + --hash=sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6 # via yamllint python-dateutil==2.8.2 \ --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ @@ -35,11 +35,12 @@ python-dateutil==2.8.2 \ # via # botocore # s3cmd -python-magic==0.4.24 \ - --hash=sha256:4fec8ee805fea30c07afccd1592c0f17977089895bdfaae5fec870a84e997626 \ - --hash=sha256:de800df9fb50f8ec5974761054a708af6e4246b03b4bdaee993f948947b0ebcf +python-magic==0.4.27 \ + --hash=sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b \ + --hash=sha256:c212960ad306f700aa0d01e5d7a325d20548ff97eb9920dcd29513174f0294d3 # via s3cmd pyyaml==6.0 \ + --hash=sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf \ --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ @@ -51,26 +52,32 @@ pyyaml==6.0 \ --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ + --hash=sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782 \ --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ + --hash=sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1 \ --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ + --hash=sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d \ --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ + --hash=sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7 \ --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ + --hash=sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358 \ --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ + --hash=sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f \ --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 # via yamllint @@ -95,7 +102,7 @@ yamllint==1.26.3 \ # via -r ./requirements.in # The following packages are considered to be unsafe in a requirements file: -setuptools==59.6.0 \ - --hash=sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373 \ - --hash=sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e +setuptools==65.6.3 \ + --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ + --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 # via yamllint diff --git a/examples/pip_parse/requirements_lock.txt b/examples/pip_parse/requirements_lock.txt index a54d912d6a..8d68996a85 100644 --- a/examples/pip_parse/requirements_lock.txt +++ b/examples/pip_parse/requirements_lock.txt @@ -4,9 +4,9 @@ # # bazel run //:requirements.update # -certifi==2021.10.8 \ - --hash=sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872 \ - --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569 +certifi==2022.12.7 \ + --hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \ + --hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18 # via requests chardet==4.0.0 \ --hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa \ @@ -16,19 +16,20 @@ idna==2.10 \ --hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 \ --hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0 # via requests -pathspec==0.9.0 \ - --hash=sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a \ - --hash=sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1 +pathspec==0.10.3 \ + --hash=sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6 \ + --hash=sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6 # via yamllint python-dateutil==2.8.2 \ --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 # via s3cmd -python-magic==0.4.24 \ - --hash=sha256:4fec8ee805fea30c07afccd1592c0f17977089895bdfaae5fec870a84e997626 \ - --hash=sha256:de800df9fb50f8ec5974761054a708af6e4246b03b4bdaee993f948947b0ebcf +python-magic==0.4.27 \ + --hash=sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b \ + --hash=sha256:c212960ad306f700aa0d01e5d7a325d20548ff97eb9920dcd29513174f0294d3 # via s3cmd pyyaml==6.0 \ + --hash=sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf \ --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ @@ -40,26 +41,32 @@ pyyaml==6.0 \ --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ + --hash=sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782 \ --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ + --hash=sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1 \ --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ + --hash=sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d \ --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ + --hash=sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7 \ --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ + --hash=sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358 \ --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ + --hash=sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f \ --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 # via yamllint @@ -75,16 +82,16 @@ six==1.16.0 \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 # via python-dateutil -urllib3==1.26.7 \ - --hash=sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece \ - --hash=sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844 +urllib3==1.26.13 \ + --hash=sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc \ + --hash=sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8 # via requests yamllint==1.26.3 \ --hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e # via -r ./requirements.in # The following packages are considered to be unsafe in a requirements file: -setuptools==59.6.0 \ - --hash=sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373 \ - --hash=sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e +setuptools==65.6.3 \ + --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ + --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 # via yamllint diff --git a/examples/pip_parse_vendored/requirements.bzl b/examples/pip_parse_vendored/requirements.bzl index 4febc756fa..cc24aa63ca 100644 --- a/examples/pip_parse_vendored/requirements.bzl +++ b/examples/pip_parse_vendored/requirements.bzl @@ -11,7 +11,7 @@ all_requirements = ["@pip_certifi//:pkg", "@pip_charset_normalizer//:pkg", "@pip all_whl_requirements = ["@pip_certifi//:whl", "@pip_charset_normalizer//:whl", "@pip_idna//:whl", "@pip_requests//:whl", "@pip_urllib3//:whl"] -_packages = [("pip_certifi", "certifi==2021.10.8 --hash=sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872 --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"), ("pip_charset_normalizer", "charset-normalizer==2.0.12 --hash=sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597 --hash=sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"), ("pip_idna", "idna==3.3 --hash=sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff --hash=sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"), ("pip_requests", "requests==2.27.1 --hash=sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61 --hash=sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"), ("pip_urllib3", "urllib3==1.26.9 --hash=sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14 --hash=sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e")] +_packages = [("pip_certifi", "certifi==2022.12.7 --hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 --hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"), ("pip_charset_normalizer", "charset-normalizer==2.1.1 --hash=sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845 --hash=sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"), ("pip_idna", "idna==3.4 --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"), ("pip_requests", "requests==2.28.1 --hash=sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983 --hash=sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"), ("pip_urllib3", "urllib3==1.26.13 --hash=sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc --hash=sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8")] _config = {"download_only": False, "enable_implicit_namespace_pkgs": False, "environment": {}, "extra_pip_args": [], "isolated": True, "pip_data_exclude": [], "python_interpreter": "python3", "python_interpreter_target": interpreter, "quiet": True, "repo": "pip", "repo_prefix": "pip_", "timeout": 600} _annotations = {} _bzlmod = False diff --git a/examples/pip_parse_vendored/requirements.txt b/examples/pip_parse_vendored/requirements.txt index d2dfc20576..71037279ce 100644 --- a/examples/pip_parse_vendored/requirements.txt +++ b/examples/pip_parse_vendored/requirements.txt @@ -4,23 +4,23 @@ # # bazel run //:requirements.update # -certifi==2021.10.8 \ - --hash=sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872 \ - --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569 +certifi==2022.12.7 \ + --hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \ + --hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18 # via requests -charset-normalizer==2.0.12 \ - --hash=sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597 \ - --hash=sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df +charset-normalizer==2.1.1 \ + --hash=sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845 \ + --hash=sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f # via requests -idna==3.3 \ - --hash=sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff \ - --hash=sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d +idna==3.4 \ + --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ + --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 # via requests -requests==2.27.1 \ - --hash=sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61 \ - --hash=sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d +requests==2.28.1 \ + --hash=sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983 \ + --hash=sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349 # via -r ./requirements.in -urllib3==1.26.9 \ - --hash=sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14 \ - --hash=sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e +urllib3==1.26.13 \ + --hash=sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc \ + --hash=sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8 # via requests diff --git a/examples/pip_repository_annotations/pip_repository_annotations_test.py b/examples/pip_repository_annotations/pip_repository_annotations_test.py index d53b9bccaa..b49fd34b33 100644 --- a/examples/pip_repository_annotations/pip_repository_annotations_test.py +++ b/examples/pip_repository_annotations/pip_repository_annotations_test.py @@ -65,7 +65,7 @@ def test_copy_executables(self): self.assertEqual(stdout, "Hello world from copied executable") def test_data_exclude_glob(self): - current_wheel_version = "0.37.1" + current_wheel_version = "0.38.4" r = runfiles.Create() dist_info_dir = "pip_repository_annotations_example/external/{}/site-packages/wheel-{}.dist-info".format( diff --git a/examples/pip_repository_annotations/requirements.txt b/examples/pip_repository_annotations/requirements.txt index 44dcbdfccf..79ad25a6c3 100644 --- a/examples/pip_repository_annotations/requirements.txt +++ b/examples/pip_repository_annotations/requirements.txt @@ -6,9 +6,9 @@ # --extra-index-url https://pypi.python.org/simple/ -certifi==2022.9.24 \ - --hash=sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14 \ - --hash=sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382 +certifi==2022.12.7 \ + --hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \ + --hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18 # via requests charset-normalizer==2.1.1 \ --hash=sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845 \ @@ -22,11 +22,11 @@ requests[security]==2.28.1 \ --hash=sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983 \ --hash=sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349 # via -r ./requirements.in -urllib3==1.26.12 \ - --hash=sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e \ - --hash=sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997 +urllib3==1.26.13 \ + --hash=sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc \ + --hash=sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8 # via requests -wheel==0.37.1 \ - --hash=sha256:4bdcd7d840138086126cd09254dc6195fb4fc6f01c050a1d7236f2630db1d22a \ - --hash=sha256:e9a504e793efbca1b8e0e9cb979a249cf4a0a7b5b8c9e8b65a5e39d49529c1c4 +wheel==0.38.4 \ + --hash=sha256:965f5259b566725405b05e7cf774052044b1ed30119b5d586b2703aafe8719ac \ + --hash=sha256:b60533f3f5d530e971d6737ca6d58681ee434818fab630c83a734bb10c083ce8 # via -r ./requirements.in From b45526736b30d10e76562fe1d79512df996c4964 Mon Sep 17 00:00:00 2001 From: Matt Oberle Date: Fri, 23 Dec 2022 20:13:23 -0500 Subject: [PATCH 091/234] fix: embed stamped version in py_wheel METADATA (#935) * fix: add test for stamped Version in METADATA * fix: resolve stamps in wheel Version METADATA * run //:vendor_requirements This seems unrelated to the #845 issue fix. CI wants `requirements.bzl` to list `@//:requirements.txt` not `//:requirements.txt`? * fix: simplify line breaks Co-authored-by: Matt Oberle Co-authored-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- examples/wheel/BUILD | 1 + examples/wheel/wheel_test.py | 33 +++++++++++++++++++++++++++++---- python/packaging.bzl | 3 +-- tools/wheelmaker.py | 7 ++++--- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/examples/wheel/BUILD b/examples/wheel/BUILD index 2c572761cf..c3dec29c01 100644 --- a/examples/wheel/BUILD +++ b/examples/wheel/BUILD @@ -243,6 +243,7 @@ py_test( ":customized", ":filename_escaping", ":minimal_with_py_library", + ":minimal_with_py_library_with_stamp", ":minimal_with_py_package", ":python_abi3_binary_wheel", ":python_requires_in_a_package", diff --git a/examples/wheel/wheel_test.py b/examples/wheel/wheel_test.py index 67aaac5cca..c292c87132 100644 --- a/examples/wheel/wheel_test.py +++ b/examples/wheel/wheel_test.py @@ -99,7 +99,7 @@ def test_customized_wheel(self): record_contents, # The entries are guaranteed to be sorted. b"""\ -example_customized-0.0.1.dist-info/METADATA,sha256=TeeEmokHE2NWjkaMcVJuSAq4_AXUoIad2-SLuquRmbg,372 +example_customized-0.0.1.dist-info/METADATA,sha256=YUnzQ9gTMXspIBURe90Ct3aL_CCn8fwC3SiZe6MMTs8,372 example_customized-0.0.1.dist-info/NOTICE,sha256=Xpdw-FXET1IRgZ_wTkx1YQfo1-alET0FVf6V1LXO4js,76 example_customized-0.0.1.dist-info/README,sha256=WmOFwZ3Jga1bHG3JiGRsUheb4UbLffUxyTdHczS27-o,40 example_customized-0.0.1.dist-info/RECORD,, @@ -125,7 +125,6 @@ def test_customized_wheel(self): b"""\ Metadata-Version: 2.1 Name: example_customized -Version: 0.0.1 Author: Example Author with non-ascii characters: \xc5\xbc\xc3\xb3\xc5\x82w Author-email: example@example.com Home-page: www.example.com @@ -133,6 +132,7 @@ def test_customized_wheel(self): Classifier: License :: OSI Approved :: Apache Software License Classifier: Intended Audience :: Developers Requires-Dist: pytest +Version: 0.0.1 This is a sample description of a wheel. """, @@ -299,8 +299,8 @@ def test_python_requires_wheel(self): b"""\ Metadata-Version: 2.1 Name: example_python_requires_in_a_package -Version: 0.0.1 Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.* +Version: 0.0.1 UNKNOWN """, @@ -334,8 +334,8 @@ def test_python_abi3_binary_wheel(self): b"""\ Metadata-Version: 2.1 Name: example_python_abi3_binary_wheel -Version: 0.0.1 Requires-Python: >=3.8 +Version: 0.0.1 UNKNOWN """, @@ -374,6 +374,31 @@ def test_rule_creates_directory_and_is_included_in_wheel(self): ], ) + def test_rule_sets_stamped_version_in_wheel_metadata(self): + filename = os.path.join( + os.environ["TEST_SRCDIR"], + "rules_python", + "examples", + "wheel", + "example_minimal_library-0.1._BUILD_TIMESTAMP_-py3-none-any.whl", + ) + + with zipfile.ZipFile(filename) as zf: + metadata_file = None + for f in zf.namelist(): + self.assertNotIn("_BUILD_TIMESTAMP_", f) + if os.path.basename(f) == "METADATA": + metadata_file = f + self.assertIsNotNone(metadata_file) + + version = None + with zf.open(metadata_file) as fp: + for line in fp: + if line.startswith(b'Version:'): + version = line.decode().split()[-1] + self.assertIsNotNone(version) + self.assertNotIn("{BUILD_TIMESTAMP}", version) + if __name__ == "__main__": unittest.main() diff --git a/python/packaging.bzl b/python/packaging.bzl index 6d7a901f53..5bb50173cf 100644 --- a/python/packaging.bzl +++ b/python/packaging.bzl @@ -167,12 +167,11 @@ def _py_wheel_impl(ctx): args.add("--input_file_list", packageinputfile) - # Note: Description file is not embedded into metadata.txt yet, + # Note: Description file and version are not embedded into metadata.txt yet, # it will be done later by wheelmaker script. metadata_file = ctx.actions.declare_file(ctx.attr.name + ".metadata.txt") metadata_contents = ["Metadata-Version: 2.1"] metadata_contents.append("Name: %s" % ctx.attr.distribution) - metadata_contents.append("Version: %s" % version) if ctx.attr.author: metadata_contents.append("Author: %s" % ctx.attr.author) diff --git a/tools/wheelmaker.py b/tools/wheelmaker.py index 7d65706f13..6138c934d5 100644 --- a/tools/wheelmaker.py +++ b/tools/wheelmaker.py @@ -167,11 +167,12 @@ def add_wheelfile(self): wheel_contents += "Tag: %s\n" % tag self.add_string(self.distinfo_path("WHEEL"), wheel_contents) - def add_metadata(self, metadata, description): + def add_metadata(self, metadata, description, version): """Write METADATA file to the distribution.""" # https://www.python.org/dev/peps/pep-0566/ # https://packaging.python.org/specifications/core-metadata/ - metadata += "\n" + metadata += "Version: " + version + metadata += "\n\n" # setuptools seems to insert UNKNOWN as description when none is # provided. metadata += description if description else "UNKNOWN" @@ -397,7 +398,7 @@ def main() -> None: with open(arguments.metadata_file, "rt", encoding="utf-8") as metadata_file: metadata = metadata_file.read() - maker.add_metadata(metadata=metadata, description=description) + maker.add_metadata(metadata=metadata, description=description, version=version) if arguments.entry_points_file: maker.add_file( From 1ceb620aeb0819baa8546b5f9ed1c03d7d555b21 Mon Sep 17 00:00:00 2001 From: "Sean R. Abraham" Date: Sat, 24 Dec 2022 13:48:20 -0700 Subject: [PATCH 092/234] chore(gazelle): clarify a particular failure message (#939) --- gazelle/manifest/test/test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gazelle/manifest/test/test.go b/gazelle/manifest/test/test.go index 8b580b14fc..207923c3ff 100644 --- a/gazelle/manifest/test/test.go +++ b/gazelle/manifest/test/test.go @@ -77,7 +77,7 @@ func main() { log.Fatalf("ERROR: %v\n", err) } log.Fatalf( - "ERROR: %q is out-of-date, follow the intructions on this file for updating.\n", + "ERROR: %q is out-of-date. Follow the update instructions in that file to resolve this.\n", manifestRealpath) } } From 8a6b15d64eae7a43d8ed45cea06a48431348a29d Mon Sep 17 00:00:00 2001 From: Greg Roodt Date: Mon, 26 Dec 2022 19:28:37 +1100 Subject: [PATCH 093/234] pip: 22.2.1 -> 22.3.1; build: 0.8.0 -> 0.9.0; installer: 0.5.1 -> 0.6.0; pip-tools: 6.8.0 -> 6.12.1 (#944) --- MODULE.bazel | 1 - .../build_file_generation/gazelle_python.yaml | 2 +- .../requirements_lock.txt | 4 +- .../requirements_windows.txt | 4 +- examples/bzlmod/requirements_lock.txt | 14 +++---- examples/bzlmod/requirements_windows.txt | 14 +++---- .../requirements/requirements_lock_3_10.txt | 4 +- .../requirements/requirements_lock_3_8.txt | 4 +- .../requirements/requirements_lock_3_9.txt | 4 +- examples/pip_install/requirements.txt | 14 +++---- examples/pip_install/requirements_windows.txt | 14 +++---- examples/pip_parse/requirements_lock.txt | 14 +++---- examples/pip_parse_vendored/requirements.txt | 4 +- .../requirements.txt | 4 +- python/pip_install/repositories.bzl | 37 ++++++++----------- .../requirements_lock.txt | 6 +-- .../requirements.txt | 20 +++++----- .../requirements_windows.txt | 20 +++++----- 18 files changed, 81 insertions(+), 103 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index e007d0c2d9..e1be99374c 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -22,7 +22,6 @@ use_repo( "pypi__pep517", "pypi__pip", "pypi__pip_tools", - "pypi__pyparsing", "pypi__setuptools", "pypi__tomli", "pypi__wheel", diff --git a/examples/build_file_generation/gazelle_python.yaml b/examples/build_file_generation/gazelle_python.yaml index 29ea035bfc..20e76652b6 100644 --- a/examples/build_file_generation/gazelle_python.yaml +++ b/examples/build_file_generation/gazelle_python.yaml @@ -115,4 +115,4 @@ manifest: pip_repository: name: pip incremental: true -integrity: 09dd75cd2f440c85abc6f823ba412331dcad5f348cbb4dc38641122ccf08d1d7 +integrity: de2beca77b2b1e9c3ef24b56aab589fc05486abf1e0c08b51ea723621360ec73 diff --git a/examples/build_file_generation/requirements_lock.txt b/examples/build_file_generation/requirements_lock.txt index eb324b2c4a..f73827a36e 100644 --- a/examples/build_file_generation/requirements_lock.txt +++ b/examples/build_file_generation/requirements_lock.txt @@ -1,6 +1,6 @@ # -# This file is autogenerated by pip-compile with python 3.9 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: # # bazel run //:requirements.update # diff --git a/examples/build_file_generation/requirements_windows.txt b/examples/build_file_generation/requirements_windows.txt index f1b82f99cb..fc097141c5 100644 --- a/examples/build_file_generation/requirements_windows.txt +++ b/examples/build_file_generation/requirements_windows.txt @@ -1,6 +1,6 @@ # -# This file is autogenerated by pip-compile with python 3.9 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: # # bazel run //:requirements.update # diff --git a/examples/bzlmod/requirements_lock.txt b/examples/bzlmod/requirements_lock.txt index b0023380e9..99905ad00b 100644 --- a/examples/bzlmod/requirements_lock.txt +++ b/examples/bzlmod/requirements_lock.txt @@ -1,6 +1,6 @@ # -# This file is autogenerated by pip-compile with python 3.9 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: # # bazel run //:requirements.update # @@ -123,6 +123,10 @@ s3cmd==2.1.0 \ --hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \ --hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03 # via -r ./requirements.in +setuptools==65.6.3 \ + --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ + --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 + # via yamllint six==1.16.0 \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 @@ -219,9 +223,3 @@ yamllint==1.28.0 \ --hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \ --hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b # via -r ./requirements.in - -# The following packages are considered to be unsafe in a requirements file: -setuptools==65.6.3 \ - --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ - --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 - # via yamllint diff --git a/examples/bzlmod/requirements_windows.txt b/examples/bzlmod/requirements_windows.txt index 8637fd7958..875dbcaeb4 100644 --- a/examples/bzlmod/requirements_windows.txt +++ b/examples/bzlmod/requirements_windows.txt @@ -1,6 +1,6 @@ # -# This file is autogenerated by pip-compile with python 3.9 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: # # bazel run //:requirements.update # @@ -127,6 +127,10 @@ s3cmd==2.1.0 \ --hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \ --hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03 # via -r ./requirements.in +setuptools==65.6.3 \ + --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ + --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 + # via yamllint six==1.16.0 \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 @@ -223,9 +227,3 @@ yamllint==1.28.0 \ --hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \ --hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b # via -r ./requirements.in - -# The following packages are considered to be unsafe in a requirements file: -setuptools==65.6.3 \ - --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ - --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 - # via yamllint diff --git a/examples/multi_python_versions/requirements/requirements_lock_3_10.txt b/examples/multi_python_versions/requirements/requirements_lock_3_10.txt index 0e332bfa3e..6bee4e0030 100644 --- a/examples/multi_python_versions/requirements/requirements_lock_3_10.txt +++ b/examples/multi_python_versions/requirements/requirements_lock_3_10.txt @@ -1,6 +1,6 @@ # -# This file is autogenerated by pip-compile with python 3.10 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.10 +# by the following command: # # bazel run //requirements:requirements_3_10.update # diff --git a/examples/multi_python_versions/requirements/requirements_lock_3_8.txt b/examples/multi_python_versions/requirements/requirements_lock_3_8.txt index 30419da431..19303f8eff 100644 --- a/examples/multi_python_versions/requirements/requirements_lock_3_8.txt +++ b/examples/multi_python_versions/requirements/requirements_lock_3_8.txt @@ -1,6 +1,6 @@ # -# This file is autogenerated by pip-compile with python 3.8 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.8 +# by the following command: # # bazel run //requirements:requirements_3_8.update # diff --git a/examples/multi_python_versions/requirements/requirements_lock_3_9.txt b/examples/multi_python_versions/requirements/requirements_lock_3_9.txt index 124355e4d2..4af42ca277 100644 --- a/examples/multi_python_versions/requirements/requirements_lock_3_9.txt +++ b/examples/multi_python_versions/requirements/requirements_lock_3_9.txt @@ -1,6 +1,6 @@ # -# This file is autogenerated by pip-compile with python 3.9 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: # # bazel run //requirements:requirements_3_9.update # diff --git a/examples/pip_install/requirements.txt b/examples/pip_install/requirements.txt index 89fd989acb..ca8d5943a7 100644 --- a/examples/pip_install/requirements.txt +++ b/examples/pip_install/requirements.txt @@ -1,6 +1,6 @@ # -# This file is autogenerated by pip-compile with python 3.9 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: # # bazel run //:requirements.update # @@ -89,6 +89,10 @@ s3transfer==0.3.7 \ --hash=sha256:35627b86af8ff97e7ac27975fe0a98a312814b46c6333d8a6b889627bcd80994 \ --hash=sha256:efa5bd92a897b6a8d5c1383828dca3d52d0790e0756d49740563a3fb6ed03246 # via boto3 +setuptools==65.6.3 \ + --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ + --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 + # via yamllint six==1.16.0 \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 @@ -104,9 +108,3 @@ urllib3==1.25.11 \ yamllint==1.26.3 \ --hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e # via -r ./requirements.in - -# The following packages are considered to be unsafe in a requirements file: -setuptools==65.6.3 \ - --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ - --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 - # via yamllint diff --git a/examples/pip_install/requirements_windows.txt b/examples/pip_install/requirements_windows.txt index 6badd5951e..c4279cb6d7 100644 --- a/examples/pip_install/requirements_windows.txt +++ b/examples/pip_install/requirements_windows.txt @@ -1,6 +1,6 @@ # -# This file is autogenerated by pip-compile with python 3.9 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: # # bazel run //:requirements.update # @@ -89,6 +89,10 @@ s3transfer==0.3.7 \ --hash=sha256:35627b86af8ff97e7ac27975fe0a98a312814b46c6333d8a6b889627bcd80994 \ --hash=sha256:efa5bd92a897b6a8d5c1383828dca3d52d0790e0756d49740563a3fb6ed03246 # via boto3 +setuptools==65.6.3 \ + --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ + --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 + # via yamllint six==1.16.0 \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 @@ -100,9 +104,3 @@ urllib3==1.25.11 \ yamllint==1.26.3 \ --hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e # via -r ./requirements.in - -# The following packages are considered to be unsafe in a requirements file: -setuptools==65.6.3 \ - --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ - --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 - # via yamllint diff --git a/examples/pip_parse/requirements_lock.txt b/examples/pip_parse/requirements_lock.txt index 8d68996a85..d60295c0bf 100644 --- a/examples/pip_parse/requirements_lock.txt +++ b/examples/pip_parse/requirements_lock.txt @@ -1,6 +1,6 @@ # -# This file is autogenerated by pip-compile with python 3.9 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: # # bazel run //:requirements.update # @@ -78,6 +78,10 @@ s3cmd==2.1.0 \ --hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \ --hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03 # via -r ./requirements.in +setuptools==65.6.3 \ + --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ + --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 + # via yamllint six==1.16.0 \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 @@ -89,9 +93,3 @@ urllib3==1.26.13 \ yamllint==1.26.3 \ --hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e # via -r ./requirements.in - -# The following packages are considered to be unsafe in a requirements file: -setuptools==65.6.3 \ - --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ - --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 - # via yamllint diff --git a/examples/pip_parse_vendored/requirements.txt b/examples/pip_parse_vendored/requirements.txt index 71037279ce..6a70e036b4 100644 --- a/examples/pip_parse_vendored/requirements.txt +++ b/examples/pip_parse_vendored/requirements.txt @@ -1,6 +1,6 @@ # -# This file is autogenerated by pip-compile with python 3.9 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: # # bazel run //:requirements.update # diff --git a/examples/pip_repository_annotations/requirements.txt b/examples/pip_repository_annotations/requirements.txt index 79ad25a6c3..f599f7a457 100644 --- a/examples/pip_repository_annotations/requirements.txt +++ b/examples/pip_repository_annotations/requirements.txt @@ -1,6 +1,6 @@ # -# This file is autogenerated by pip-compile with python 3.9 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: # # bazel run //:requirements.update # diff --git a/python/pip_install/repositories.bzl b/python/pip_install/repositories.bzl index 8b027672df..845da49981 100644 --- a/python/pip_install/repositories.bzl +++ b/python/pip_install/repositories.bzl @@ -9,8 +9,8 @@ load("//third_party/github.com/bazelbuild/bazel-skylib/lib:versions.bzl", "versi _RULE_DEPS = [ ( "pypi__build", - "https://files.pythonhosted.org/packages/7a/24/ee8271da317b692fcb9d026ff7f344ac6c4ec661a97f0e2a11fa7992544a/build-0.8.0-py3-none-any.whl", - "19b0ed489f92ace6947698c3ca8436cb0556a66e2aa2d34cd70e2a5d27cd0437", + "https://files.pythonhosted.org/packages/03/97/f58c723ff036a8d8b4d3115377c0a37ed05c1f68dd9a0d66dab5e82c5c1c/build-0.9.0-py3-none-any.whl", + "38a7a2b7a0bdc61a42a0a67509d88c71ecfc37b393baba770fae34e20929ff69", ), ( "pypi__click", @@ -19,38 +19,33 @@ _RULE_DEPS = [ ), ( "pypi__colorama", - "https://files.pythonhosted.org/packages/44/98/5b86278fbbf250d239ae0ecb724f8572af1c91f4a11edf4d36a206189440/colorama-0.4.4-py2.py3-none-any.whl", - "9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2", + "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", + "4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", ), ( "pypi__installer", - "https://files.pythonhosted.org/packages/1b/21/3e6ebd12d8dccc55bcb7338db462c75ac86dbd0ac7439ac114616b21667b/installer-0.5.1-py3-none-any.whl", - "1d6c8d916ed82771945b9c813699e6f57424ded970c9d8bf16bbc23e1e826ed3", + "https://files.pythonhosted.org/packages/bf/42/fe5f10fd0d58d5d8231a0bc39e664de09992f960597e9fbd3753f84423a3/installer-0.6.0-py3-none-any.whl", + "ae7c62d1d6158b5c096419102ad0d01fdccebf857e784cee57f94165635fe038", ), ( "pypi__packaging", - "https://files.pythonhosted.org/packages/05/8e/8de486cbd03baba4deef4142bd643a3e7bbe954a784dc1bb17142572d127/packaging-21.3-py3-none-any.whl", - "ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522", + "https://files.pythonhosted.org/packages/8f/7b/42582927d281d7cb035609cd3a543ffac89b74f3f4ee8e1c50914bcb57eb/packaging-22.0-py3-none-any.whl", + "957e2148ba0e1a3b282772e791ef1d8083648bc131c8ab0c1feba110ce1146c3", ), ( "pypi__pep517", - "https://files.pythonhosted.org/packages/f4/67/846c08e18fefb265a66e6fd5a34269d649b779718d9bf59622085dabd370/pep517-0.12.0-py2.py3-none-any.whl", - "dd884c326898e2c6e11f9e0b64940606a93eb10ea022a2e067959f3a110cf161", + "https://files.pythonhosted.org/packages/ee/2f/ef63e64e9429111e73d3d6cbee80591672d16f2725e648ebc52096f3d323/pep517-0.13.0-py3-none-any.whl", + "4ba4446d80aed5b5eac6509ade100bff3e7943a8489de249654a5ae9b33ee35b", ), ( "pypi__pip", - "https://files.pythonhosted.org/packages/84/25/5734a44897751d8bac6822efb819acda2d969bcc1b915bbd7d48102952cb/pip-22.2.1-py3-none-any.whl", - "0bbbc87dfbe6eed217beff0021f8b7dea04c8f4a0baa9d31dc4cff281ffc5b2b", + "https://files.pythonhosted.org/packages/09/bd/2410905c76ee14c62baf69e3f4aa780226c1bbfc9485731ad018e35b0cb5/pip-22.3.1-py3-none-any.whl", + "908c78e6bc29b676ede1c4d57981d490cb892eb45cd8c214ab6298125119e077", ), ( "pypi__pip_tools", - "https://files.pythonhosted.org/packages/bf/3a/a8b09ca5ea24e4ddfa4d2cdf885e8c6618a4b658b32553f897f948aa0f67/pip_tools-6.8.0-py3-none-any.whl", - "3e5cd4acbf383d19bdfdeab04738b6313ebf4ad22ce49bf529c729061eabfab8", - ), - ( - "pypi__pyparsing", - "https://files.pythonhosted.org/packages/6c/10/a7d0fa5baea8fe7b50f448ab742f26f52b80bfca85ac2be9d35cdd9a3246/pyparsing-3.0.9-py3-none-any.whl", - "5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc", + "https://files.pythonhosted.org/packages/5e/e8/f6d7d1847c7351048da870417724ace5c4506e816b38db02f4d7c675c189/pip_tools-6.12.1-py3-none-any.whl", + "f0c0c0ec57b58250afce458e2e6058b1f30a4263db895b7d72fd6311bf1dc6f7", ), ( "pypi__setuptools", @@ -64,8 +59,8 @@ _RULE_DEPS = [ ), ( "pypi__wheel", - "https://files.pythonhosted.org/packages/27/d6/003e593296a85fd6ed616ed962795b2f87709c3eee2bca4f6d0fe55c6d00/wheel-0.37.1-py2.py3-none-any.whl", - "4bdcd7d840138086126cd09254dc6195fb4fc6f01c050a1d7236f2630db1d22a", + "https://files.pythonhosted.org/packages/bd/7c/d38a0b30ce22fc26ed7dbc087c6d00851fb3395e9d0dac40bec1f905030c/wheel-0.38.4-py3-none-any.whl", + "b60533f3f5d530e971d6737ca6d58681ee434818fab630c83a734bb10c083ce8", ), ( "pypi__importlib_metadata", diff --git a/tests/compile_pip_requirements/requirements_lock.txt b/tests/compile_pip_requirements/requirements_lock.txt index 78ced94440..f1af5a0937 100644 --- a/tests/compile_pip_requirements/requirements_lock.txt +++ b/tests/compile_pip_requirements/requirements_lock.txt @@ -1,11 +1,9 @@ # -# This file is autogenerated by pip-compile with python 3.9 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: # # bazel run //:pip_dependencies.update # - -# The following packages are considered to be unsafe in a requirements file: pip==22.3.1 \ --hash=sha256:65fd48317359f3af8e593943e6ae1506b66325085ea64b706a998c6e83eeaf38 \ --hash=sha256:908c78e6bc29b676ede1c4d57981d490cb892eb45cd8c214ab6298125119e077 diff --git a/tests/pip_repository_entry_points/requirements.txt b/tests/pip_repository_entry_points/requirements.txt index 5491a4b791..90b717e7a7 100644 --- a/tests/pip_repository_entry_points/requirements.txt +++ b/tests/pip_repository_entry_points/requirements.txt @@ -1,6 +1,6 @@ # -# This file is autogenerated by pip-compile with python 3.10 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.10 +# by the following command: # # bazel run //:requirements.update # @@ -166,6 +166,13 @@ requests==2.27.1 \ --hash=sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61 \ --hash=sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d # via sphinx +setuptools==59.6.0 \ + --hash=sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373 \ + --hash=sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e + # via + # -r ./requirements.in + # sphinx + # yamllint snowballstemmer==2.2.0 \ --hash=sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1 \ --hash=sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a @@ -206,12 +213,3 @@ yamllint==1.28.0 \ --hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \ --hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b # via -r ./requirements.in - -# The following packages are considered to be unsafe in a requirements file: -setuptools==59.6.0 \ - --hash=sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373 \ - --hash=sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e - # via - # -r ./requirements.in - # sphinx - # yamllint diff --git a/tests/pip_repository_entry_points/requirements_windows.txt b/tests/pip_repository_entry_points/requirements_windows.txt index 8522898099..14c3dc3274 100644 --- a/tests/pip_repository_entry_points/requirements_windows.txt +++ b/tests/pip_repository_entry_points/requirements_windows.txt @@ -1,6 +1,6 @@ # -# This file is autogenerated by pip-compile with python 3.10 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.10 +# by the following command: # # bazel run //:requirements.update # @@ -170,6 +170,13 @@ requests==2.27.1 \ --hash=sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61 \ --hash=sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d # via sphinx +setuptools==59.6.0 \ + --hash=sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373 \ + --hash=sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e + # via + # -r ./requirements.in + # sphinx + # yamllint snowballstemmer==2.2.0 \ --hash=sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1 \ --hash=sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a @@ -210,12 +217,3 @@ yamllint==1.28.0 \ --hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \ --hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b # via -r ./requirements.in - -# The following packages are considered to be unsafe in a requirements file: -setuptools==59.6.0 \ - --hash=sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373 \ - --hash=sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e - # via - # -r ./requirements.in - # sphinx - # yamllint From 7e59c5caf33d2c0737b7c49c978f73b754887499 Mon Sep 17 00:00:00 2001 From: Greg Roodt Date: Mon, 26 Dec 2022 19:47:16 +1100 Subject: [PATCH 094/234] Update name of `compile_pip_requirements` (#945) --- tests/compile_pip_requirements/BUILD.bazel | 2 +- tests/compile_pip_requirements/requirements_lock.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/compile_pip_requirements/BUILD.bazel b/tests/compile_pip_requirements/BUILD.bazel index 258bb71ad5..3a67dcca47 100644 --- a/tests/compile_pip_requirements/BUILD.bazel +++ b/tests/compile_pip_requirements/BUILD.bazel @@ -20,7 +20,7 @@ EOF ) compile_pip_requirements( - name = "pip_dependencies", + name = "requirements", data = [ "requirements_extra.in", ], diff --git a/tests/compile_pip_requirements/requirements_lock.txt b/tests/compile_pip_requirements/requirements_lock.txt index f1af5a0937..8f7037ce7a 100644 --- a/tests/compile_pip_requirements/requirements_lock.txt +++ b/tests/compile_pip_requirements/requirements_lock.txt @@ -2,7 +2,7 @@ # This file is autogenerated by pip-compile with Python 3.9 # by the following command: # -# bazel run //:pip_dependencies.update +# bazel run //:requirements.update # pip==22.3.1 \ --hash=sha256:65fd48317359f3af8e593943e6ae1506b66325085ea64b706a998c6e83eeaf38 \ From 50ba3ed843b710259b9a4ca4634f4026a2294af2 Mon Sep 17 00:00:00 2001 From: Greg Roodt Date: Tue, 27 Dec 2022 05:44:48 +1100 Subject: [PATCH 095/234] Rename `BUILD` -> `BUILD.bazel` (#946) --- BUILD => BUILD.bazel | 2 +- docs/{BUILD => BUILD.bazel} | 0 examples/{BUILD => BUILD.bazel} | 0 examples/build_file_generation/{BUILD => BUILD.bazel} | 0 .../random_number_generator/{BUILD => BUILD.bazel} | 0 examples/pip_install/{BUILD => BUILD.bazel} | 0 examples/pip_parse/{BUILD => BUILD.bazel} | 0 examples/pip_parse_vendored/{BUILD => BUILD.bazel} | 0 examples/pip_repository_annotations/{BUILD => BUILD.bazel} | 0 examples/wheel/{BUILD => BUILD.bazel} | 0 examples/wheel/lib/{BUILD => BUILD.bazel} | 0 examples/wheel/private/{BUILD => BUILD.bazel} | 0 python/{BUILD => BUILD.bazel} | 0 python/constraints/{BUILD => BUILD.bazel} | 0 python/pip_install/{BUILD => BUILD.bazel} | 2 +- python/pip_install/extract_wheels/{BUILD => BUILD.bazel} | 0 python/pip_install/pip_repository.bzl | 2 +- python/pip_install/private/{BUILD => BUILD.bazel} | 0 python/pip_install/private/test/{BUILD => BUILD.bazel} | 0 python/private/{BUILD => BUILD.bazel} | 0 python/runfiles/{BUILD => BUILD.bazel} | 0 tests/{BUILD => BUILD.bazel} | 0 tests/load_from_macro/{BUILD => BUILD.bazel} | 0 tests/pip_repository_entry_points/{BUILD => BUILD.bazel} | 0 tools/{BUILD => BUILD.bazel} | 2 +- tools/bazel_integration_test/{BUILD => BUILD.bazel} | 0 26 files changed, 4 insertions(+), 4 deletions(-) rename BUILD => BUILD.bazel (99%) rename docs/{BUILD => BUILD.bazel} (100%) rename examples/{BUILD => BUILD.bazel} (100%) rename examples/build_file_generation/{BUILD => BUILD.bazel} (100%) rename examples/build_file_generation/random_number_generator/{BUILD => BUILD.bazel} (100%) rename examples/pip_install/{BUILD => BUILD.bazel} (100%) rename examples/pip_parse/{BUILD => BUILD.bazel} (100%) rename examples/pip_parse_vendored/{BUILD => BUILD.bazel} (100%) rename examples/pip_repository_annotations/{BUILD => BUILD.bazel} (100%) rename examples/wheel/{BUILD => BUILD.bazel} (100%) rename examples/wheel/lib/{BUILD => BUILD.bazel} (100%) rename examples/wheel/private/{BUILD => BUILD.bazel} (100%) rename python/{BUILD => BUILD.bazel} (100%) rename python/constraints/{BUILD => BUILD.bazel} (100%) rename python/pip_install/{BUILD => BUILD.bazel} (96%) rename python/pip_install/extract_wheels/{BUILD => BUILD.bazel} (100%) rename python/pip_install/private/{BUILD => BUILD.bazel} (100%) rename python/pip_install/private/test/{BUILD => BUILD.bazel} (100%) rename python/private/{BUILD => BUILD.bazel} (100%) rename python/runfiles/{BUILD => BUILD.bazel} (100%) rename tests/{BUILD => BUILD.bazel} (100%) rename tests/load_from_macro/{BUILD => BUILD.bazel} (100%) rename tests/pip_repository_entry_points/{BUILD => BUILD.bazel} (100%) rename tools/{BUILD => BUILD.bazel} (97%) rename tools/bazel_integration_test/{BUILD => BUILD.bazel} (100%) diff --git a/BUILD b/BUILD.bazel similarity index 99% rename from BUILD rename to BUILD.bazel index cb92935561..654e0149b4 100644 --- a/BUILD +++ b/BUILD.bazel @@ -27,7 +27,7 @@ exports_files([ filegroup( name = "distribution", srcs = [ - "BUILD", + "BUILD.bazel", "MODULE.bazel", "WORKSPACE", "internal_deps.bzl", diff --git a/docs/BUILD b/docs/BUILD.bazel similarity index 100% rename from docs/BUILD rename to docs/BUILD.bazel diff --git a/examples/BUILD b/examples/BUILD.bazel similarity index 100% rename from examples/BUILD rename to examples/BUILD.bazel diff --git a/examples/build_file_generation/BUILD b/examples/build_file_generation/BUILD.bazel similarity index 100% rename from examples/build_file_generation/BUILD rename to examples/build_file_generation/BUILD.bazel diff --git a/examples/build_file_generation/random_number_generator/BUILD b/examples/build_file_generation/random_number_generator/BUILD.bazel similarity index 100% rename from examples/build_file_generation/random_number_generator/BUILD rename to examples/build_file_generation/random_number_generator/BUILD.bazel diff --git a/examples/pip_install/BUILD b/examples/pip_install/BUILD.bazel similarity index 100% rename from examples/pip_install/BUILD rename to examples/pip_install/BUILD.bazel diff --git a/examples/pip_parse/BUILD b/examples/pip_parse/BUILD.bazel similarity index 100% rename from examples/pip_parse/BUILD rename to examples/pip_parse/BUILD.bazel diff --git a/examples/pip_parse_vendored/BUILD b/examples/pip_parse_vendored/BUILD.bazel similarity index 100% rename from examples/pip_parse_vendored/BUILD rename to examples/pip_parse_vendored/BUILD.bazel diff --git a/examples/pip_repository_annotations/BUILD b/examples/pip_repository_annotations/BUILD.bazel similarity index 100% rename from examples/pip_repository_annotations/BUILD rename to examples/pip_repository_annotations/BUILD.bazel diff --git a/examples/wheel/BUILD b/examples/wheel/BUILD.bazel similarity index 100% rename from examples/wheel/BUILD rename to examples/wheel/BUILD.bazel diff --git a/examples/wheel/lib/BUILD b/examples/wheel/lib/BUILD.bazel similarity index 100% rename from examples/wheel/lib/BUILD rename to examples/wheel/lib/BUILD.bazel diff --git a/examples/wheel/private/BUILD b/examples/wheel/private/BUILD.bazel similarity index 100% rename from examples/wheel/private/BUILD rename to examples/wheel/private/BUILD.bazel diff --git a/python/BUILD b/python/BUILD.bazel similarity index 100% rename from python/BUILD rename to python/BUILD.bazel diff --git a/python/constraints/BUILD b/python/constraints/BUILD.bazel similarity index 100% rename from python/constraints/BUILD rename to python/constraints/BUILD.bazel diff --git a/python/pip_install/BUILD b/python/pip_install/BUILD.bazel similarity index 96% rename from python/pip_install/BUILD rename to python/pip_install/BUILD.bazel index 9ff51375da..9fbc8e8289 100644 --- a/python/pip_install/BUILD +++ b/python/pip_install/BUILD.bazel @@ -3,7 +3,7 @@ exports_files(["pip_compile.py"]) filegroup( name = "distribution", srcs = glob(["*.bzl"]) + [ - "BUILD", + "BUILD.bazel", "pip_compile.py", "//python/pip_install/extract_wheels:distribution", "//python/pip_install/private:distribution", diff --git a/python/pip_install/extract_wheels/BUILD b/python/pip_install/extract_wheels/BUILD.bazel similarity index 100% rename from python/pip_install/extract_wheels/BUILD rename to python/pip_install/extract_wheels/BUILD.bazel diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl index 101ec6a687..9c233441ee 100644 --- a/python/pip_install/pip_repository.bzl +++ b/python/pip_install/pip_repository.bzl @@ -21,7 +21,7 @@ def _construct_pypath(rctx): """ # Get the root directory of these rules - rules_root = rctx.path(Label("//:BUILD")).dirname + rules_root = rctx.path(Label("//:BUILD.bazel")).dirname thirdparty_roots = [ # Includes all the external dependencies from repositories.bzl rctx.path(Label("@" + repo + "//:BUILD.bazel")).dirname diff --git a/python/pip_install/private/BUILD b/python/pip_install/private/BUILD.bazel similarity index 100% rename from python/pip_install/private/BUILD rename to python/pip_install/private/BUILD.bazel diff --git a/python/pip_install/private/test/BUILD b/python/pip_install/private/test/BUILD.bazel similarity index 100% rename from python/pip_install/private/test/BUILD rename to python/pip_install/private/test/BUILD.bazel diff --git a/python/private/BUILD b/python/private/BUILD.bazel similarity index 100% rename from python/private/BUILD rename to python/private/BUILD.bazel diff --git a/python/runfiles/BUILD b/python/runfiles/BUILD.bazel similarity index 100% rename from python/runfiles/BUILD rename to python/runfiles/BUILD.bazel diff --git a/tests/BUILD b/tests/BUILD.bazel similarity index 100% rename from tests/BUILD rename to tests/BUILD.bazel diff --git a/tests/load_from_macro/BUILD b/tests/load_from_macro/BUILD.bazel similarity index 100% rename from tests/load_from_macro/BUILD rename to tests/load_from_macro/BUILD.bazel diff --git a/tests/pip_repository_entry_points/BUILD b/tests/pip_repository_entry_points/BUILD.bazel similarity index 100% rename from tests/pip_repository_entry_points/BUILD rename to tests/pip_repository_entry_points/BUILD.bazel diff --git a/tools/BUILD b/tools/BUILD.bazel similarity index 97% rename from tools/BUILD rename to tools/BUILD.bazel index 789bc2b53f..7c9b492a3c 100644 --- a/tools/BUILD +++ b/tools/BUILD.bazel @@ -26,7 +26,7 @@ py_binary( filegroup( name = "distribution", srcs = [ - "BUILD", + "BUILD.bazel", "wheelmaker.py", ], visibility = ["//:__pkg__"], diff --git a/tools/bazel_integration_test/BUILD b/tools/bazel_integration_test/BUILD.bazel similarity index 100% rename from tools/bazel_integration_test/BUILD rename to tools/bazel_integration_test/BUILD.bazel From b3bf1243926b674d7041fd49da4865c658b4bddb Mon Sep 17 00:00:00 2001 From: Greg Roodt Date: Tue, 27 Dec 2022 05:45:21 +1100 Subject: [PATCH 096/234] Add missing .gitignore for //examples/pip_parse_vendored (#947) --- examples/pip_parse_vendored/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 examples/pip_parse_vendored/.gitignore diff --git a/examples/pip_parse_vendored/.gitignore b/examples/pip_parse_vendored/.gitignore new file mode 100644 index 0000000000..ac51a054d2 --- /dev/null +++ b/examples/pip_parse_vendored/.gitignore @@ -0,0 +1 @@ +bazel-* From d400f6bf37aacbc9ceb04f7395cc048a1f811611 Mon Sep 17 00:00:00 2001 From: Greg Roodt Date: Tue, 27 Dec 2022 11:34:30 +1100 Subject: [PATCH 097/234] Removes unused "incremental" property (#948) --- docs/pip.md | 2 +- examples/build_file_generation/BUILD.bazel | 1 - .../build_file_generation/gazelle_python.yaml | 3 +- gazelle/README.md | 2 - gazelle/manifest/defs.bzl | 4 -- gazelle/manifest/generate/generate.go | 7 --- gazelle/manifest/manifest.go | 2 - gazelle/pythonconfig/pythonconfig.go | 12 ++--- .../dependency_resolution_order/BUILD.out | 2 +- .../BUILD.out | 2 +- .../ignored_invalid_imported_module/BUILD.out | 2 +- .../monorepo/coarse_grained/BUILD.out | 2 +- gazelle/testdata/monorepo/one/BUILD.out | 2 +- gazelle/testdata/monorepo/one/bar/BUILD.out | 2 +- gazelle/testdata/monorepo/three/BUILD.out | 2 +- .../monorepo/three/gazelle_python.yaml | 1 - gazelle/testdata/monorepo/two/BUILD.out | 2 +- .../BUILD.out | 2 +- .../python_target_with_test_in_name/BUILD.out | 2 +- .../with_nested_import_statements/BUILD.out | 2 +- .../with_third_party_requirements/BUILD.out | 8 +-- .../gazelle_python.yaml | 1 - python/pip.bzl | 2 +- .../extract_wheels/wheel_installer.py | 54 ++++--------------- .../extract_wheels/wheel_installer_test.py | 26 ++------- 25 files changed, 36 insertions(+), 111 deletions(-) diff --git a/docs/pip.md b/docs/pip.md index 5f6c1d8565..1ffd4222a0 100644 --- a/docs/pip.md +++ b/docs/pip.md @@ -175,7 +175,7 @@ Accepts a locked/compiled requirements file and installs the dependencies listed Those dependencies become available in a generated `requirements.bzl` file. You can instead check this `requirements.bzl` file into your repo, see the "vendoring" section below. -This macro wraps the [`pip_repository`](./pip_repository.md) rule that invokes `pip`, with `incremental` set. +This macro wraps the [`pip_repository`](./pip_repository.md) rule that invokes `pip`. In your WORKSPACE file: ```python diff --git a/examples/build_file_generation/BUILD.bazel b/examples/build_file_generation/BUILD.bazel index 6a921a27b5..6bd1a929de 100644 --- a/examples/build_file_generation/BUILD.bazel +++ b/examples/build_file_generation/BUILD.bazel @@ -41,7 +41,6 @@ modules_mapping( gazelle_python_manifest( name = "gazelle_python_manifest", modules_mapping = ":modules_map", - pip_repository_incremental = True, pip_repository_name = "pip", requirements = "//:requirements_lock.txt", ) diff --git a/examples/build_file_generation/gazelle_python.yaml b/examples/build_file_generation/gazelle_python.yaml index 20e76652b6..0be959a67e 100644 --- a/examples/build_file_generation/gazelle_python.yaml +++ b/examples/build_file_generation/gazelle_python.yaml @@ -114,5 +114,4 @@ manifest: zipp.py310compat: zipp pip_repository: name: pip - incremental: true -integrity: de2beca77b2b1e9c3ef24b56aab589fc05486abf1e0c08b51ea723621360ec73 +integrity: 4153df7683d64d7d6ad56c14ea1c7f7bec84a2ddf9ef8f075d1bb9313b8d11aa diff --git a/gazelle/README.md b/gazelle/README.md index e622db991a..a54db64ed8 100644 --- a/gazelle/README.md +++ b/gazelle/README.md @@ -63,8 +63,6 @@ gazelle_python_manifest( # This is what we called our `pip_install` rule, where third-party # python libraries are loaded in BUILD files. pip_repository_name = "pip", - # When using pip_parse instead of pip_install, set the following. - # pip_repository_incremental = True, # This should point to wherever we declare our python dependencies # (the same as what we passed to the modules_mapping rule in WORKSPACE) requirements = "//:requirements_lock.txt", diff --git a/gazelle/manifest/defs.bzl b/gazelle/manifest/defs.bzl index a5bbe56353..57f52f986e 100644 --- a/gazelle/manifest/defs.bzl +++ b/gazelle/manifest/defs.bzl @@ -9,7 +9,6 @@ def gazelle_python_manifest( requirements, modules_mapping, pip_repository_name = "", - pip_repository_incremental = False, pip_deps_repository_name = "", manifest = ":gazelle_python.yaml"): """A macro for defining the updating and testing targets for the Gazelle manifest file. @@ -18,7 +17,6 @@ def gazelle_python_manifest( name: the name used as a base for the targets. requirements: the target for the requirements.txt file. pip_repository_name: the name of the pip_install or pip_repository target. - pip_repository_incremental: the incremental property of pip_repository. pip_deps_repository_name: deprecated - the old pip_install target name. modules_mapping: the target for the generated modules_mapping.json file. manifest: the target for the Gazelle manifest file. @@ -54,8 +52,6 @@ def gazelle_python_manifest( "--update-target", update_target_label, ] - if pip_repository_incremental: - update_args.append("--pip-repository-incremental") go_binary( name = update_target, diff --git a/gazelle/manifest/generate/generate.go b/gazelle/manifest/generate/generate.go index 54e88132e6..7c2e064d93 100644 --- a/gazelle/manifest/generate/generate.go +++ b/gazelle/manifest/generate/generate.go @@ -27,7 +27,6 @@ func main() { var manifestGeneratorHashPath string var requirementsPath string var pipRepositoryName string - var pipRepositoryIncremental bool var modulesMappingPath string var outputPath string var updateTarget string @@ -47,11 +46,6 @@ func main() { "pip-repository-name", "", "The name of the pip_install or pip_repository target.") - flag.BoolVar( - &pipRepositoryIncremental, - "pip-repository-incremental", - false, - "The value for the incremental option in pip_repository.") flag.StringVar( &modulesMappingPath, "modules-mapping", @@ -96,7 +90,6 @@ func main() { ModulesMapping: modulesMapping, PipRepository: &manifest.PipRepository{ Name: pipRepositoryName, - Incremental: pipRepositoryIncremental, }, }) if err := writeOutput( diff --git a/gazelle/manifest/manifest.go b/gazelle/manifest/manifest.go index 640effc8c7..5668d9ce88 100644 --- a/gazelle/manifest/manifest.go +++ b/gazelle/manifest/manifest.go @@ -130,6 +130,4 @@ type Manifest struct { type PipRepository struct { // The name of the pip_install or pip_repository target. Name string - // The incremental property of pip_repository. - Incremental bool } diff --git a/gazelle/pythonconfig/pythonconfig.go b/gazelle/pythonconfig/pythonconfig.go index 7e65fd98d7..64f6264323 100644 --- a/gazelle/pythonconfig/pythonconfig.go +++ b/gazelle/pythonconfig/pythonconfig.go @@ -207,15 +207,9 @@ func (c *Config) FindThirdPartyDependency(modName string) (string, bool) { sanitizedDistribution := strings.ToLower(distributionName) sanitizedDistribution = strings.ReplaceAll(sanitizedDistribution, "-", "_") var lbl label.Label - if gazelleManifest.PipRepository != nil && gazelleManifest.PipRepository.Incremental { - // @_//:pkg - distributionRepositoryName = distributionRepositoryName + "_" + sanitizedDistribution - lbl = label.New(distributionRepositoryName, "", "pkg") - } else { - // @//pypi__ - distributionPackage := "pypi__" + sanitizedDistribution - lbl = label.New(distributionRepositoryName, distributionPackage, distributionPackage) - } + // @_//:pkg + distributionRepositoryName = distributionRepositoryName + "_" + sanitizedDistribution + lbl = label.New(distributionRepositoryName, "", "pkg") return lbl.String(), true } } diff --git a/gazelle/testdata/dependency_resolution_order/BUILD.out b/gazelle/testdata/dependency_resolution_order/BUILD.out index 2ba2c84c9a..3ea83eb5f1 100644 --- a/gazelle/testdata/dependency_resolution_order/BUILD.out +++ b/gazelle/testdata/dependency_resolution_order/BUILD.out @@ -9,6 +9,6 @@ py_library( deps = [ "//baz", "//somewhere/bar", - "@gazelle_python_test//pypi__some_foo", + "@gazelle_python_test_some_foo//:pkg", ], ) diff --git a/gazelle/testdata/file_name_matches_import_statement/BUILD.out b/gazelle/testdata/file_name_matches_import_statement/BUILD.out index fd6c48559d..0216e4b2e3 100644 --- a/gazelle/testdata/file_name_matches_import_statement/BUILD.out +++ b/gazelle/testdata/file_name_matches_import_statement/BUILD.out @@ -7,5 +7,5 @@ py_library( "rest_framework.py", ], visibility = ["//:__subpackages__"], - deps = ["@gazelle_python_test//pypi__djangorestframework"], + deps = ["@gazelle_python_test_djangorestframework//:pkg"], ) diff --git a/gazelle/testdata/ignored_invalid_imported_module/BUILD.out b/gazelle/testdata/ignored_invalid_imported_module/BUILD.out index 3cd47a6fe0..b8c936a7dd 100644 --- a/gazelle/testdata/ignored_invalid_imported_module/BUILD.out +++ b/gazelle/testdata/ignored_invalid_imported_module/BUILD.out @@ -4,5 +4,5 @@ py_library( name = "ignored_invalid_imported_module", srcs = ["__init__.py"], visibility = ["//:__subpackages__"], - deps = ["@gazelle_python_test//pypi__foo"], + deps = ["@gazelle_python_test_foo//:pkg"], ) diff --git a/gazelle/testdata/monorepo/coarse_grained/BUILD.out b/gazelle/testdata/monorepo/coarse_grained/BUILD.out index 0fba9515a1..b11cbbdaad 100644 --- a/gazelle/testdata/monorepo/coarse_grained/BUILD.out +++ b/gazelle/testdata/monorepo/coarse_grained/BUILD.out @@ -16,5 +16,5 @@ py_library( "foo/__init__.py", ], visibility = ["//:__subpackages__"], - deps = ["@root_pip_deps//pypi__rootboto3"], + deps = ["@root_pip_deps_rootboto3//:pkg"], ) diff --git a/gazelle/testdata/monorepo/one/BUILD.out b/gazelle/testdata/monorepo/one/BUILD.out index a957227a9a..5098cc9a08 100644 --- a/gazelle/testdata/monorepo/one/BUILD.out +++ b/gazelle/testdata/monorepo/one/BUILD.out @@ -12,6 +12,6 @@ py_binary( "//one/bar", "//one/bar/baz:modified_name_baz", "//one/foo", - "@one_pip_deps//pypi__oneboto3", + "@one_pip_deps_oneboto3//:pkg", ], ) diff --git a/gazelle/testdata/monorepo/one/bar/BUILD.out b/gazelle/testdata/monorepo/one/bar/BUILD.out index 0e85623394..6ee6515eec 100644 --- a/gazelle/testdata/monorepo/one/bar/BUILD.out +++ b/gazelle/testdata/monorepo/one/bar/BUILD.out @@ -8,5 +8,5 @@ py_library( "//one:__subpackages__", "//three:__subpackages__", ], - deps = ["@one_pip_deps//pypi__oneboto3"], + deps = ["@one_pip_deps_oneboto3//:pkg"], ) diff --git a/gazelle/testdata/monorepo/three/BUILD.out b/gazelle/testdata/monorepo/three/BUILD.out index 0da269d644..78a3927db9 100644 --- a/gazelle/testdata/monorepo/three/BUILD.out +++ b/gazelle/testdata/monorepo/three/BUILD.out @@ -15,7 +15,7 @@ py_library( "//one/bar", "//one/bar/baz:modified_name_baz", "//one/foo", - "@root_pip_deps//pypi__rootboto4", + "@root_pip_deps_rootboto4//:pkg", "@three_pip_deps_threeboto3//:pkg", ], ) diff --git a/gazelle/testdata/monorepo/three/gazelle_python.yaml b/gazelle/testdata/monorepo/three/gazelle_python.yaml index d46a88f444..860416933e 100644 --- a/gazelle/testdata/monorepo/three/gazelle_python.yaml +++ b/gazelle/testdata/monorepo/three/gazelle_python.yaml @@ -3,4 +3,3 @@ manifest: boto3: threeboto3 pip_repository: name: three_pip_deps - incremental: true diff --git a/gazelle/testdata/monorepo/two/BUILD.out b/gazelle/testdata/monorepo/two/BUILD.out index 4b638edea2..9cda007e59 100644 --- a/gazelle/testdata/monorepo/two/BUILD.out +++ b/gazelle/testdata/monorepo/two/BUILD.out @@ -10,6 +10,6 @@ py_library( visibility = ["//two:__subpackages__"], deps = [ "//one/foo", - "@two_pip_deps//pypi__twoboto3", + "@two_pip_deps_twoboto3//:pkg", ], ) diff --git a/gazelle/testdata/python_ignore_dependencies_directive/BUILD.out b/gazelle/testdata/python_ignore_dependencies_directive/BUILD.out index 37ae4f9aa1..3fb91f5964 100644 --- a/gazelle/testdata/python_ignore_dependencies_directive/BUILD.out +++ b/gazelle/testdata/python_ignore_dependencies_directive/BUILD.out @@ -7,5 +7,5 @@ py_library( name = "python_ignore_dependencies_directive", srcs = ["__init__.py"], visibility = ["//:__subpackages__"], - deps = ["@gazelle_python_test//pypi__boto3"], + deps = ["@gazelle_python_test_boto3//:pkg"], ) diff --git a/gazelle/testdata/python_target_with_test_in_name/BUILD.out b/gazelle/testdata/python_target_with_test_in_name/BUILD.out index bdde605c09..72a648ffe5 100644 --- a/gazelle/testdata/python_target_with_test_in_name/BUILD.out +++ b/gazelle/testdata/python_target_with_test_in_name/BUILD.out @@ -8,5 +8,5 @@ py_library( "test_not_a_real.py", ], visibility = ["//:__subpackages__"], - deps = ["@gazelle_python_test//pypi__boto3"], + deps = ["@gazelle_python_test_boto3//:pkg"], ) diff --git a/gazelle/testdata/with_nested_import_statements/BUILD.out b/gazelle/testdata/with_nested_import_statements/BUILD.out index bb2f34db55..45bf265180 100644 --- a/gazelle/testdata/with_nested_import_statements/BUILD.out +++ b/gazelle/testdata/with_nested_import_statements/BUILD.out @@ -4,5 +4,5 @@ py_library( name = "with_nested_import_statements", srcs = ["__init__.py"], visibility = ["//:__subpackages__"], - deps = ["@gazelle_python_test//pypi__boto3"], + deps = ["@gazelle_python_test_boto3//:pkg"], ) diff --git a/gazelle/testdata/with_third_party_requirements/BUILD.out b/gazelle/testdata/with_third_party_requirements/BUILD.out index 9854730a2e..a8261a9fae 100644 --- a/gazelle/testdata/with_third_party_requirements/BUILD.out +++ b/gazelle/testdata/with_third_party_requirements/BUILD.out @@ -9,9 +9,9 @@ py_library( ], visibility = ["//:__subpackages__"], deps = [ - "@gazelle_python_test//pypi__baz", - "@gazelle_python_test//pypi__boto3", - "@gazelle_python_test//pypi__djangorestframework", + "@gazelle_python_test_baz//:pkg", + "@gazelle_python_test_boto3//:pkg", + "@gazelle_python_test_djangorestframework//:pkg", ], ) @@ -22,6 +22,6 @@ py_binary( visibility = ["//:__subpackages__"], deps = [ ":with_third_party_requirements", - "@gazelle_python_test//pypi__baz", + "@gazelle_python_test_baz//:pkg", ], ) diff --git a/gazelle/testdata/with_third_party_requirements_from_imports/gazelle_python.yaml b/gazelle/testdata/with_third_party_requirements_from_imports/gazelle_python.yaml index 21edbc0a0d..0e4a6d2316 100644 --- a/gazelle/testdata/with_third_party_requirements_from_imports/gazelle_python.yaml +++ b/gazelle/testdata/with_third_party_requirements_from_imports/gazelle_python.yaml @@ -1661,5 +1661,4 @@ manifest: urllib3.util.wait: urllib3 pip_repository: name: gazelle_python_test - incremental: true integrity: 32e38932043eca090a64ca741758d8e4a5817c2cd7dc821fc927914c32fb3114 diff --git a/python/pip.bzl b/python/pip.bzl index a3c9b6975a..6939daf0d6 100644 --- a/python/pip.bzl +++ b/python/pip.bzl @@ -53,7 +53,7 @@ def pip_parse(requirements = None, requirements_lock = None, name = "pip_parsed_ Those dependencies become available in a generated `requirements.bzl` file. You can instead check this `requirements.bzl` file into your repo, see the "vendoring" section below. - This macro wraps the [`pip_repository`](./pip_repository.md) rule that invokes `pip`, with `incremental` set. + This macro wraps the [`pip_repository`](./pip_repository.md) rule that invokes `pip`. In your WORKSPACE file: ```python diff --git a/python/pip_install/extract_wheels/wheel_installer.py b/python/pip_install/extract_wheels/wheel_installer.py index fe00b5cb66..87fe1fd9a2 100644 --- a/python/pip_install/extract_wheels/wheel_installer.py +++ b/python/pip_install/extract_wheels/wheel_installer.py @@ -294,10 +294,9 @@ def _extract_wheel( pip_data_exclude: List[str], enable_implicit_namespace_pkgs: bool, repo_prefix: str, - incremental: bool = False, incremental_dir: Path = Path("."), annotation: Optional[annotation.Annotation] = None, -) -> Optional[str]: +) -> None: """Extracts wheel into given directory and creates py_library and filegroup targets. Args: @@ -305,8 +304,6 @@ def _extract_wheel( extras: a list of extras to add as dependencies for the installed wheel pip_data_exclude: list of file patterns to exclude from the generated data section of the py_library enable_implicit_namespace_pkgs: if true, disables conversion of implicit namespace packages and will unzip as-is - incremental: If true the extract the wheel in a format suitable for an external repository. This - effects the names of libraries and their dependencies, which point to other external repositories. incremental_dir: An optional override for the working directory of incremental builds. annotation: An optional set of annotations to apply to the BUILD contents of the wheel. @@ -315,14 +312,7 @@ def _extract_wheel( """ whl = wheel.Wheel(wheel_file) - if incremental: - directory = incremental_dir - else: - directory = bazel.sanitise_name(whl.name, prefix=repo_prefix) - - os.mkdir(directory) - # copy the original wheel - shutil.copy(whl.path, directory) + directory = incremental_dir whl.unzip(directory) if not enable_implicit_namespace_pkgs: @@ -334,28 +324,12 @@ def _extract_wheel( self_edge_dep = set([whl.name]) whl_deps = sorted(whl.dependencies(extras_requested) - self_edge_dep) - if incremental: - sanitised_dependencies = [ - bazel.sanitised_repo_library_label(d, repo_prefix=repo_prefix) - for d in whl_deps - ] - sanitised_wheel_file_dependencies = [ - bazel.sanitised_repo_file_label(d, repo_prefix=repo_prefix) - for d in whl_deps - ] - else: - sanitised_dependencies = [ - _sanitised_library_label(d, prefix=repo_prefix) for d in whl_deps - ] - sanitised_wheel_file_dependencies = [ - _sanitised_file_label(d, prefix=repo_prefix) for d in whl_deps - ] - - library_name = ( - bazel.PY_LIBRARY_LABEL - if incremental - else bazel.sanitise_name(whl.name, repo_prefix) - ) + sanitised_dependencies = [ + bazel.sanitised_repo_library_label(d, repo_prefix=repo_prefix) for d in whl_deps + ] + sanitised_wheel_file_dependencies = [ + bazel.sanitised_repo_file_label(d, repo_prefix=repo_prefix) for d in whl_deps + ] directory_path = Path(directory) entry_points = [] @@ -374,7 +348,7 @@ def _extract_wheel( _generate_entry_point_rule( entry_point_target_name, entry_point_script_name, - library_name, + bazel.PY_LIBRARY_LABEL, ) ) @@ -399,9 +373,7 @@ def _extract_wheel( additional_content.append(annotation.additive_build_content) contents = _generate_build_file_contents( - name=bazel.PY_LIBRARY_LABEL - if incremental - else bazel.sanitise_name(whl.name, repo_prefix), + name=bazel.PY_LIBRARY_LABEL, dependencies=sanitised_dependencies, whl_file_deps=sanitised_wheel_file_dependencies, data_exclude=data_exclude, @@ -412,11 +384,6 @@ def _extract_wheel( ) build_file.write(contents) - if not incremental: - os.remove(whl.path) - return f"//{directory}" - return None - def main() -> None: parser = argparse.ArgumentParser( @@ -478,7 +445,6 @@ def main() -> None: extras=extras, pip_data_exclude=deserialized_args["pip_data_exclude"], enable_implicit_namespace_pkgs=args.enable_implicit_namespace_pkgs, - incremental=True, repo_prefix=args.repo_prefix, annotation=args.annotation, ) diff --git a/python/pip_install/extract_wheels/wheel_installer_test.py b/python/pip_install/extract_wheels/wheel_installer_test.py index 59a5ed19bd..ff667d7280 100644 --- a/python/pip_install/extract_wheels/wheel_installer_test.py +++ b/python/pip_install/extract_wheels/wheel_installer_test.py @@ -74,37 +74,21 @@ def setUp(self) -> None: def tearDown(self): shutil.rmtree(self.wheel_dir) - def _run( - self, - repo_prefix: str, - incremental: bool = False, - ) -> None: - generated_bazel_dir = wheel_installer._extract_wheel( + def test_wheel_exists(self) -> None: + wheel_installer._extract_wheel( self.wheel_path, extras={}, pip_data_exclude=[], enable_implicit_namespace_pkgs=False, - incremental=incremental, - repo_prefix=repo_prefix, + repo_prefix="prefix_", incremental_dir=Path(self.wheel_dir), ) - # Take off the leading // from the returned label. - # Assert that the raw wheel ends up in the package. - generated_bazel_dir = ( - generated_bazel_dir[2:] if not incremental else self.wheel_dir - ) - self.assertIn(self.wheel_name, os.listdir(generated_bazel_dir)) - with open("{}/BUILD.bazel".format(generated_bazel_dir)) as build_file: + self.assertIn(self.wheel_name, os.listdir(self.wheel_dir)) + with open("{}/BUILD.bazel".format(self.wheel_dir)) as build_file: build_file_content = build_file.read() self.assertIn("filegroup", build_file_content) - def test_nonincremental(self) -> None: - self._run(repo_prefix="prefix_") - - def test_incremental(self) -> None: - self._run(incremental=True, repo_prefix="prefix_") - if __name__ == "__main__": unittest.main() From 9a9c8440132ad1487d9615c8647ceb85ff20f619 Mon Sep 17 00:00:00 2001 From: Greg Roodt Date: Tue, 27 Dec 2022 14:39:46 +1100 Subject: [PATCH 098/234] Disable bytecode optimization during wheel installation (#949) --- python/pip_install/extract_wheels/wheel.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python/pip_install/extract_wheels/wheel.py b/python/pip_install/extract_wheels/wheel.py index 024d6e5fa2..f3d5f21200 100644 --- a/python/pip_install/extract_wheels/wheel.py +++ b/python/pip_install/extract_wheels/wheel.py @@ -84,6 +84,7 @@ def unzip(self, directory: str) -> None: interpreter="/dev/null", script_kind="posix", destdir=directory, + bytecode_optimization_levels=[], ) with installer.sources.WheelFile.open(self.path) as wheel_source: From def63add6e256da8ed641ed24d4340d6381bdd61 Mon Sep 17 00:00:00 2001 From: Philipp Stephani Date: Thu, 29 Dec 2022 21:19:12 +0100 Subject: [PATCH 099/234] Fix broken link. (#955) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c1ba8f1699..53f195672e 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ You may also find some quirks while using this toolchain. Please refer to [pytho ### Toolchain usage in other rules -Python toolchains can be utilised in other bazel rules, such as `genrule()`, by adding the `toolchains=["@rules_python//python:current_py_toolchain"]` attribute. The path to the python interpreter can be obtained by using the `$(PYTHON2)` and `$(PYTHON3)` ["Make" Variables](https://bazel.build/reference/be/make-variables). See the [`test_current_py_toolchain`](tests/load_from_macro/BUILD) target for an example. +Python toolchains can be utilised in other bazel rules, such as `genrule()`, by adding the `toolchains=["@rules_python//python:current_py_toolchain"]` attribute. The path to the python interpreter can be obtained by using the `$(PYTHON2)` and `$(PYTHON3)` ["Make" Variables](https://bazel.build/reference/be/make-variables). See the [`test_current_py_toolchain`](tests/load_from_macro/BUILD.bazel) target for an example. ### "Hello World" From 7262403c85c31b810b860dedbf06254916d20fe2 Mon Sep 17 00:00:00 2001 From: Philipp Stephani Date: Thu, 29 Dec 2022 21:21:04 +0100 Subject: [PATCH 100/234] =?UTF-8?q?Don=E2=80=99t=20use=20keyword=20argumen?= =?UTF-8?q?t=20for=20TestEnvironment.=20(#954)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- python/config_settings/transition.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/config_settings/transition.bzl b/python/config_settings/transition.bzl index e87e2c9c22..35ba9a8ede 100644 --- a/python/config_settings/transition.bzl +++ b/python/config_settings/transition.bzl @@ -62,7 +62,7 @@ def _transition_py_impl(ctx): # RunEnvironmentInfo is not exposed in Bazel < 5.3. # https://github.com/bazelbuild/rules_python/issues/901 # https://github.com/bazelbuild/bazel/commit/dbdfa07e92f99497be9c14265611ad2920161483 - testing.TestEnvironment(environment = env), + testing.TestEnvironment(env), ] return providers From 2c29f401dcab6e6b84b56d9b4e9849fe0cf0a550 Mon Sep 17 00:00:00 2001 From: Arne-Christian Rundereim Date: Fri, 30 Dec 2022 21:26:14 +0100 Subject: [PATCH 101/234] Fix hyphen in requirement didn't work with bzlmod (#952) (#957) --- examples/bzlmod/BUILD.bazel | 1 + examples/bzlmod/requirements.in | 1 + examples/bzlmod/requirements_lock.txt | 4 +++- examples/bzlmod/requirements_windows.txt | 4 +++- python/pip_install/pip_repository.bzl | 6 +++++- 5 files changed, 13 insertions(+), 3 deletions(-) diff --git a/examples/bzlmod/BUILD.bazel b/examples/bzlmod/BUILD.bazel index a00c96dbaf..2094567362 100644 --- a/examples/bzlmod/BUILD.bazel +++ b/examples/bzlmod/BUILD.bazel @@ -16,6 +16,7 @@ py_library( deps = [ requirement("pylint"), requirement("tabulate"), + requirement("python-dateutil"), ], ) diff --git a/examples/bzlmod/requirements.in b/examples/bzlmod/requirements.in index 069f7caf85..a709195442 100644 --- a/examples/bzlmod/requirements.in +++ b/examples/bzlmod/requirements.in @@ -3,3 +3,4 @@ s3cmd~=2.1.0 yamllint>=1.28.0 tabulate~=0.9.0 pylint~=2.15.5 +python-dateutil>=2.8.2 diff --git a/examples/bzlmod/requirements_lock.txt b/examples/bzlmod/requirements_lock.txt index 99905ad00b..482402ffb8 100644 --- a/examples/bzlmod/requirements_lock.txt +++ b/examples/bzlmod/requirements_lock.txt @@ -68,7 +68,9 @@ pylint==2.15.9 \ python-dateutil==2.8.2 \ --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 - # via s3cmd + # via + # -r ./requirements.in + # s3cmd python-magic==0.4.27 \ --hash=sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b \ --hash=sha256:c212960ad306f700aa0d01e5d7a325d20548ff97eb9920dcd29513174f0294d3 diff --git a/examples/bzlmod/requirements_windows.txt b/examples/bzlmod/requirements_windows.txt index 875dbcaeb4..41187b9475 100644 --- a/examples/bzlmod/requirements_windows.txt +++ b/examples/bzlmod/requirements_windows.txt @@ -72,7 +72,9 @@ pylint==2.15.9 \ python-dateutil==2.8.2 \ --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 - # via s3cmd + # via + # -r ./requirements.in + # s3cmd python-magic==0.4.27 \ --hash=sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b \ --hash=sha256:c212960ad306f700aa0d01e5d7a325d20548ff97eb9920dcd29513174f0294d3 diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl index 9c233441ee..60b84d398e 100644 --- a/python/pip_install/pip_repository.bzl +++ b/python/pip_install/pip_repository.bzl @@ -287,7 +287,11 @@ alias( name = "{name}_dist_info", actual = "@{repo_prefix}{dep}//:dist_info", ) -""".format(name = _clean_pkg_name(requirement[0]), repo_prefix = rctx.attr.repo_prefix, dep = requirement[0]) +""".format( + name = _clean_pkg_name(requirement[0]), + repo_prefix = rctx.attr.repo_prefix, + dep = _clean_pkg_name(requirement[0]), + ) return build_content From 3c4ed56db7de85b76d870ffab9852e376197d30f Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Sun, 1 Jan 2023 22:58:44 -0800 Subject: [PATCH 102/234] chore(docs): fix bad html formatting (#959) --- docs/pip.md | 2 +- docs/pip_repository.md | 8 ++++---- python/pip.bzl | 2 +- python/pip_install/pip_repository.bzl | 6 ++---- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/docs/pip.md b/docs/pip.md index 1ffd4222a0..93bc7f0c15 100644 --- a/docs/pip.md +++ b/docs/pip.md @@ -262,7 +262,7 @@ See the example in rules_python/examples/pip_parse_vendored. | :------------- | :------------- | :------------- | | requirements | Deprecated. See requirements_lock. | None | | requirements_lock | A fully resolved 'requirements.txt' pip requirement file containing the transitive set of your dependencies. If this file is passed instead of 'requirements' no resolve will take place and pip_repository will create individual repositories for each of your dependencies so that wheels are fetched/built only for the targets specified by 'build/run/test'. Note that if your lockfile is platform-dependent, you can use the requirements_[platform] attributes. | None | -| name | The name of the generated repository. The generated repositories containing each requirement will be of the form <name>_<requirement-name>. | "pip_parsed_deps" | +| name | The name of the generated repository. The generated repositories containing each requirement will be of the form <name>_<requirement-name>. | "pip_parsed_deps" | | bzlmod | Whether this rule is being run under a bzlmod module extension. | False | | kwargs | Additional arguments to the [pip_repository](./pip_repository.md) repository rule. | none | diff --git a/docs/pip_repository.md b/docs/pip_repository.md index ae9100a315..7abb503c78 100644 --- a/docs/pip_repository.md +++ b/docs/pip_repository.md @@ -63,7 +63,7 @@ py_binary( | bzlmod | Whether this repository rule is invoked under bzlmod, in which case we do not create the install_deps() macro. | Boolean | optional | False | | download_only | Whether to use "pip download" instead of "pip wheel". Disables building wheels from source, but allows use of --platform, --python-version, --implementation, and --abi in --extra_pip_args to download wheels for a different platform from the host platform. | Boolean | optional | False | | enable_implicit_namespace_pkgs | If true, disables conversion of native namespace packages into pkg-util style namespace packages. When set all py_binary and py_test targets must specify either legacy_create_init=False or the global Bazel option --incompatible_default_to_explicit_init_py to prevent __init__.py being automatically generated in every directory.

This option is required to support some packages which cannot handle the conversion to pkg-util style. | Boolean | optional | False | -| environment | Environment variables to set in the pip subprocess. Can be used to set common variables such as http_proxy, https_proxy and no_proxy Note that pip is run with "--isolated" on the CLI so PIP_<VAR>_<NAME> style env vars are ignored, but env vars that control requests and urllib3 can be passed. | Dictionary: String -> String | optional | {} | +| environment | Environment variables to set in the pip subprocess. Can be used to set common variables such as http_proxy, https_proxy and no_proxy Note that pip is run with "--isolated" on the CLI so PIP_<VAR>_<NAME> style env vars are ignored, but env vars that control requests and urllib3 can be passed. | Dictionary: String -> String | optional | {} | | extra_pip_args | Extra arguments to pass on to pip. Must not contain spaces. | List of strings | optional | [] | | isolated | Whether or not to pass the [--isolated](https://pip.pypa.io/en/stable/cli/pip/#cmdoption-isolated) flag to the underlying pip command. Alternatively, the RULES_PYTHON_PIP_ISOLATED enviornment varaible can be used to control this flag. | Boolean | optional | True | | pip_data_exclude | Additional data exclusion parameters to add to the pip packages BUILD file. | List of strings | optional | [] | @@ -71,7 +71,7 @@ py_binary( | python_interpreter_target | If you are using a custom python interpreter built by another repository rule, use this attribute to specify its BUILD target. This allows pip_repository to invoke pip using the same interpreter as your toolchain. If set, takes precedence over python_interpreter. | Label | optional | None | | quiet | If True, suppress printing stdout and stderr output to the terminal. | Boolean | optional | True | | repo_mapping | A dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.<p>For example, an entry "@foo": "@bar" declares that, for any time this repository depends on @foo (such as a dependency on @foo//some:target, it should actually resolve that dependency within globally-declared @bar (@bar//some:target). | Dictionary: String -> String | required | | -| repo_prefix | Prefix for the generated packages will be of the form

@<prefix><sanitized-package-name>//... | String | optional | "" | +| repo_prefix | Prefix for the generated packages will be of the form @<prefix><sanitized-package-name>//... | String | optional | "" | | requirements_darwin | Override the requirements_lock attribute when the host platform is Mac OS | Label | optional | None | | requirements_linux | Override the requirements_lock attribute when the host platform is Linux | Label | optional | None | | requirements_lock | A fully resolved 'requirements.txt' pip requirement file containing the transitive set of your dependencies. If this file is passed instead of 'requirements' no resolve will take place and pip_repository will create individual repositories for each of your dependencies so that wheels are fetched/built only for the targets specified by 'build/run/test'. | Label | optional | None | @@ -102,7 +102,7 @@ Instantiated from pip_repository and inherits config options from there. | annotation | Optional json encoded file containing annotation to apply to the extracted wheel. See package_annotation | Label | optional | None | | download_only | Whether to use "pip download" instead of "pip wheel". Disables building wheels from source, but allows use of --platform, --python-version, --implementation, and --abi in --extra_pip_args to download wheels for a different platform from the host platform. | Boolean | optional | False | | enable_implicit_namespace_pkgs | If true, disables conversion of native namespace packages into pkg-util style namespace packages. When set all py_binary and py_test targets must specify either legacy_create_init=False or the global Bazel option --incompatible_default_to_explicit_init_py to prevent __init__.py being automatically generated in every directory.

This option is required to support some packages which cannot handle the conversion to pkg-util style. | Boolean | optional | False | -| environment | Environment variables to set in the pip subprocess. Can be used to set common variables such as http_proxy, https_proxy and no_proxy Note that pip is run with "--isolated" on the CLI so PIP_<VAR>_<NAME> style env vars are ignored, but env vars that control requests and urllib3 can be passed. | Dictionary: String -> String | optional | {} | +| environment | Environment variables to set in the pip subprocess. Can be used to set common variables such as http_proxy, https_proxy and no_proxy Note that pip is run with "--isolated" on the CLI so PIP_<VAR>_<NAME> style env vars are ignored, but env vars that control requests and urllib3 can be passed. | Dictionary: String -> String | optional | {} | | extra_pip_args | Extra arguments to pass on to pip. Must not contain spaces. | List of strings | optional | [] | | isolated | Whether or not to pass the [--isolated](https://pip.pypa.io/en/stable/cli/pip/#cmdoption-isolated) flag to the underlying pip command. Alternatively, the RULES_PYTHON_PIP_ISOLATED enviornment varaible can be used to control this flag. | Boolean | optional | True | | pip_data_exclude | Additional data exclusion parameters to add to the pip packages BUILD file. | List of strings | optional | [] | @@ -111,7 +111,7 @@ Instantiated from pip_repository and inherits config options from there. | quiet | If True, suppress printing stdout and stderr output to the terminal. | Boolean | optional | True | | repo | Pointer to parent repo name. Used to make these rules rerun if the parent repo changes. | String | required | | | repo_mapping | A dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.<p>For example, an entry "@foo": "@bar" declares that, for any time this repository depends on @foo (such as a dependency on @foo//some:target, it should actually resolve that dependency within globally-declared @bar (@bar//some:target). | Dictionary: String -> String | required | | -| repo_prefix | Prefix for the generated packages will be of the form

@<prefix><sanitized-package-name>//... | String | optional | "" | +| repo_prefix | Prefix for the generated packages will be of the form @<prefix><sanitized-package-name>//... | String | optional | "" | | requirement | Python requirement string describing the package to make available | String | required | | | timeout | Timeout (in seconds) on the rule's execution duration. | Integer | optional | 600 | diff --git a/python/pip.bzl b/python/pip.bzl index 6939daf0d6..3d45aed61e 100644 --- a/python/pip.bzl +++ b/python/pip.bzl @@ -142,7 +142,7 @@ def pip_parse(requirements = None, requirements_lock = None, name = "pip_parsed_ attributes. requirements (Label): Deprecated. See requirements_lock. name (str, optional): The name of the generated repository. The generated repositories - containing each requirement will be of the form _. + containing each requirement will be of the form `_`. bzlmod (bool, optional): Whether this rule is being run under a bzlmod module extension. **kwargs (dict): Additional arguments to the [`pip_repository`](./pip_repository.md) repository rule. """ diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl index 60b84d398e..afd9c1875c 100644 --- a/python/pip_install/pip_repository.bzl +++ b/python/pip_install/pip_repository.bzl @@ -380,7 +380,7 @@ This option is required to support some packages which cannot handle the convers doc = """ Environment variables to set in the pip subprocess. Can be used to set common variables such as `http_proxy`, `https_proxy` and `no_proxy` -Note that pip is run with "--isolated" on the CLI so PIP__ +Note that pip is run with "--isolated" on the CLI so `PIP__` style env vars are ignored, but env vars that control requests and urllib3 can be passed. """, @@ -424,9 +424,7 @@ python_interpreter. ), "repo_prefix": attr.string( doc = """ -Prefix for the generated packages will be of the form - -@//... +Prefix for the generated packages will be of the form `@//...` """, ), # 600 is documented as default here: https://docs.bazel.build/versions/master/skylark/lib/repository_ctx.html#execute From 4dde14729a1771188b7d316605a13f2c1b2cfbbf Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius Date: Mon, 2 Jan 2023 16:00:21 +0900 Subject: [PATCH 103/234] Fully switch to bazel 6.0.0 in all places (#960) --- examples/BUILD.bazel | 2 +- examples/bzlmod/.bazelversion | 2 +- internal_setup.bzl | 7 ------- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/examples/BUILD.bazel b/examples/BUILD.bazel index 4f99e2b819..e0a7e5a72d 100644 --- a/examples/BUILD.bazel +++ b/examples/BUILD.bazel @@ -51,5 +51,5 @@ bazel_integration_test( bazel_integration_test( name = "bzlmod_example", bzlmod = True, - override_bazel_version = "6.0.0rc1", + override_bazel_version = "6.0.0", ) diff --git a/examples/bzlmod/.bazelversion b/examples/bzlmod/.bazelversion index 6b4ab2c84d..09b254e90c 100644 --- a/examples/bzlmod/.bazelversion +++ b/examples/bzlmod/.bazelversion @@ -1 +1 @@ -6.0.0rc1 \ No newline at end of file +6.0.0 diff --git a/internal_setup.bzl b/internal_setup.bzl index beb26e8a81..f4d3a1a8db 100644 --- a/internal_setup.bzl +++ b/internal_setup.bzl @@ -31,13 +31,6 @@ def rules_python_internal_setup(): # Depend on the Bazel binaries for running bazel-in-bazel tests bazel_binaries(versions = SUPPORTED_BAZEL_VERSIONS) - # Bazel 5.3.0 has bzlmod bugs so we use 6.0 prerelease for the bzlmod example. - # SUPPORTED_BAZEL_VERSIONS doesn't currently support multiple versions. For now, - # we only want to run the bzlmod example with a separate version. - bazel_binaries(versions = [ - "6.0.0rc1", - ]) - bazel_skylib_workspace() # gazelle:repository_macro gazelle/deps.bzl%gazelle_deps From 902229113a284ef47db22d3c6acd934ecee4e539 Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius Date: Tue, 3 Jan 2023 06:18:02 +0900 Subject: [PATCH 104/234] Use 'os' instead of 'ioutil' in gazelle tests (#962) --- gazelle/manifest/manifest_test.go | 3 +-- gazelle/python_test.go | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/gazelle/manifest/manifest_test.go b/gazelle/manifest/manifest_test.go index 174d999a43..d3873e3881 100644 --- a/gazelle/manifest/manifest_test.go +++ b/gazelle/manifest/manifest_test.go @@ -2,7 +2,6 @@ package manifest_test import ( "bytes" - "io/ioutil" "log" "os" "reflect" @@ -44,7 +43,7 @@ func TestFile(t *testing.T) { log.Println(err) t.FailNow() } - expected, err := ioutil.ReadFile("testdata/gazelle_python.yaml") + expected, err := os.ReadFile("testdata/gazelle_python.yaml") if err != nil { log.Println(err) t.FailNow() diff --git a/gazelle/python_test.go b/gazelle/python_test.go index 99656552dd..4fac7c003a 100644 --- a/gazelle/python_test.go +++ b/gazelle/python_test.go @@ -24,7 +24,6 @@ import ( "context" "errors" "fmt" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -94,9 +93,9 @@ func testPath(t *testing.T, name string, files []bazel.RunfileEntry) { continue } - content, err := ioutil.ReadFile(path) + content, err := os.ReadFile(path) if err != nil { - t.Errorf("ioutil.ReadFile(%q) error: %v", path, err) + t.Errorf("os.ReadFile(%q) error: %v", path, err) } if filepath.Base(shortPath) == "test.yaml" { From 70cce26432187a60b4e950118791385e6fb3c26f Mon Sep 17 00:00:00 2001 From: Greg Roodt Date: Wed, 11 Jan 2023 09:00:51 +1100 Subject: [PATCH 105/234] Refactor and separate concerns of external python package handling code (#953) --- .pre-commit-config.yaml | 2 +- MODULE.bazel | 4 +- examples/bzlmod/MODULE.bazel | 7 +- python/extensions.bzl | 2 +- python/pip_install/BUILD.bazel | 13 ++-- python/pip_install/pip_repository.bzl | 4 +- .../pip_install/private/pip_install_utils.bzl | 4 +- python/pip_install/private/srcs.bzl | 23 ++++--- python/pip_install/repositories.bzl | 2 +- python/pip_install/requirements.bzl | 2 +- .../tools/dependency_resolver/BUILD.bazel | 19 ++++++ .../dependency_resolver}/__init__.py | 0 .../dependency_resolver.py} | 0 .../{extract_wheels => tools/lib}/BUILD.bazel | 67 +------------------ python/pip_install/tools/lib/__init__.py | 0 .../lib}/annotation.py | 0 .../lib}/annotations_test.py | 2 +- .../lib}/annotations_test_helpers.bzl | 2 +- .../lib}/arguments.py | 0 .../lib}/arguments_test.py | 2 +- .../{extract_wheels => tools/lib}/bazel.py | 0 .../tools/lock_file_generator/BUILD.bazel | 50 ++++++++++++++ .../tools/lock_file_generator/__init__.py | 0 .../lock_file_generator.py} | 2 +- .../lock_file_generator_test.py} | 14 ++-- .../tools/wheel_installer/BUILD.bazel | 66 ++++++++++++++++++ .../wheel_installer}/namespace_pkgs.py | 0 .../wheel_installer}/namespace_pkgs_test.py | 2 +- .../wheel_installer}/wheel.py | 0 .../wheel_installer}/wheel_installer.py | 9 +-- .../wheel_installer}/wheel_installer_test.py | 2 +- 31 files changed, 181 insertions(+), 119 deletions(-) create mode 100644 python/pip_install/tools/dependency_resolver/BUILD.bazel rename python/pip_install/{extract_wheels => tools/dependency_resolver}/__init__.py (100%) rename python/pip_install/{pip_compile.py => tools/dependency_resolver/dependency_resolver.py} (100%) rename python/pip_install/{extract_wheels => tools/lib}/BUILD.bazel (58%) create mode 100644 python/pip_install/tools/lib/__init__.py rename python/pip_install/{extract_wheels => tools/lib}/annotation.py (100%) rename python/pip_install/{extract_wheels => tools/lib}/annotations_test.py (97%) rename python/pip_install/{extract_wheels => tools/lib}/annotations_test_helpers.bzl (97%) rename python/pip_install/{extract_wheels => tools/lib}/arguments.py (100%) rename python/pip_install/{extract_wheels => tools/lib}/arguments_test.py (96%) rename python/pip_install/{extract_wheels => tools/lib}/bazel.py (100%) create mode 100644 python/pip_install/tools/lock_file_generator/BUILD.bazel create mode 100644 python/pip_install/tools/lock_file_generator/__init__.py rename python/pip_install/{extract_wheels/parse_requirements_to_bzl.py => tools/lock_file_generator/lock_file_generator.py} (99%) rename python/pip_install/{extract_wheels/parse_requirements_to_bzl_test.py => tools/lock_file_generator/lock_file_generator_test.py} (93%) create mode 100644 python/pip_install/tools/wheel_installer/BUILD.bazel rename python/pip_install/{extract_wheels => tools/wheel_installer}/namespace_pkgs.py (100%) rename python/pip_install/{extract_wheels => tools/wheel_installer}/namespace_pkgs_test.py (98%) rename python/pip_install/{extract_wheels => tools/wheel_installer}/wheel.py (100%) rename python/pip_install/{extract_wheels => tools/wheel_installer}/wheel_installer.py (99%) rename python/pip_install/{extract_wheels => tools/wheel_installer}/wheel_installer_test.py (97%) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a84d531488..9836759a79 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,7 +3,7 @@ # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/keith/pre-commit-buildifier - rev: 5.1.0.1 + rev: 6.0.0 hooks: - id: buildifier args: &args diff --git a/MODULE.bazel b/MODULE.bazel index e1be99374c..6afe365f69 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -1,15 +1,13 @@ module( name = "rules_python", - compatibility_level = 1, version = "0.0.0", + compatibility_level = 1, ) bazel_dep(name = "platforms", version = "0.0.4") internal_deps = use_extension("@rules_python//python:extensions.bzl", "internal_deps") - internal_deps.install() - use_repo( internal_deps, "pypi__build", diff --git a/examples/bzlmod/MODULE.bazel b/examples/bzlmod/MODULE.bazel index 14a338cc52..bbace8674f 100644 --- a/examples/bzlmod/MODULE.bazel +++ b/examples/bzlmod/MODULE.bazel @@ -1,23 +1,20 @@ module( name = "example_bzlmod", - compatibility_level = 1, version = "0.0.0", + compatibility_level = 1, ) bazel_dep(name = "rules_python", version = "0.0.0") - local_path_override( module_name = "rules_python", path = "../..", ) python = use_extension("@rules_python//python:extensions.bzl", "python") - python.toolchain( name = "python3_9", python_version = "3.9", ) - use_repo(python, "python3_9_toolchains") register_toolchains( @@ -25,11 +22,9 @@ register_toolchains( ) pip = use_extension("@rules_python//python:extensions.bzl", "pip") - pip.parse( name = "pip", requirements_lock = "//:requirements_lock.txt", requirements_windows = "//:requirements_windows.txt", ) - use_repo(pip, "pip") diff --git a/python/extensions.bzl b/python/extensions.bzl index 4699cdd84a..8b4fc0b7b4 100644 --- a/python/extensions.bzl +++ b/python/extensions.bzl @@ -78,7 +78,7 @@ def _pip_impl(module_ctx): environment = attr.environment, ) -# Keep in sync with python/pip_install/extract_wheels/bazel.py +# Keep in sync with python/pip_install/tools/bazel.py def _sanitize_name(name): return name.replace("-", "_").replace(".", "_").lower() diff --git a/python/pip_install/BUILD.bazel b/python/pip_install/BUILD.bazel index 9fbc8e8289..451e7fab70 100644 --- a/python/pip_install/BUILD.bazel +++ b/python/pip_install/BUILD.bazel @@ -1,11 +1,11 @@ -exports_files(["pip_compile.py"]) - filegroup( name = "distribution", srcs = glob(["*.bzl"]) + [ "BUILD.bazel", - "pip_compile.py", - "//python/pip_install/extract_wheels:distribution", + "//python/pip_install/tools/dependency_resolver:distribution", + "//python/pip_install/tools/lib:distribution", + "//python/pip_install/tools/lock_file_generator:distribution", + "//python/pip_install/tools/wheel_installer:distribution", "//python/pip_install/private:distribution", ], visibility = ["//:__pkg__"], @@ -22,7 +22,10 @@ filegroup( filegroup( name = "py_srcs", srcs = [ - "//python/pip_install/extract_wheels:py_srcs", + "//python/pip_install/tools/dependency_resolver:py_srcs", + "//python/pip_install/tools/lib:py_srcs", + "//python/pip_install/tools/lock_file_generator:py_srcs", + "//python/pip_install/tools/wheel_installer:py_srcs", ], visibility = ["//python/pip_install/private:__pkg__"], ) diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl index afd9c1875c..f5a2da2b0a 100644 --- a/python/pip_install/pip_repository.bzl +++ b/python/pip_install/pip_repository.bzl @@ -307,7 +307,7 @@ def _pip_repository_impl(rctx): args = [ python_interpreter, "-m", - "python.pip_install.extract_wheels.parse_requirements_to_bzl", + "python.pip_install.tools.lock_file_generator.lock_file_generator", "--requirements_lock", rctx.path(requirements_txt), "--requirements_lock_label", @@ -524,7 +524,7 @@ def _whl_library_impl(rctx): args = [ python_interpreter, "-m", - "python.pip_install.extract_wheels.wheel_installer", + "python.pip_install.tools.wheel_installer.wheel_installer", "--requirement", rctx.attr.requirement, "--repo", diff --git a/python/pip_install/private/pip_install_utils.bzl b/python/pip_install/private/pip_install_utils.bzl index 038ee0e8c8..aaf1600d6d 100644 --- a/python/pip_install/private/pip_install_utils.bzl +++ b/python/pip_install/private/pip_install_utils.bzl @@ -1,9 +1,9 @@ """Utilities for `rules_python` pip rules""" _SRCS_TEMPLATE = """\ -\"\"\"A generate file containing all source files used for `@rules_python//python/pip_install:pip_repository.bzl` rules +\"\"\"A generated file containing all source files used for `@rules_python//python/pip_install:pip_repository.bzl` rules -This file is auto-generated from the `@rules_python//python/pip_install/private:srcs_module.install` target. Please +This file is auto-generated from the `@rules_python//python/pip_install/private:srcs_module.update` target. Please `bazel run` this target to apply any updates. Note that doing so will discard any local modifications. "\"\" diff --git a/python/pip_install/private/srcs.bzl b/python/pip_install/private/srcs.bzl index 89bd55d43c..57644f612f 100644 --- a/python/pip_install/private/srcs.bzl +++ b/python/pip_install/private/srcs.bzl @@ -1,18 +1,21 @@ -"""A generate file containing all source files used for `@rules_python//python/pip_install:pip_repository.bzl` rules +"""A generated file containing all source files used for `@rules_python//python/pip_install:pip_repository.bzl` rules -This file is auto-generated from the `@rules_python//python/pip_install/private:srcs_module.install` target. Please +This file is auto-generated from the `@rules_python//python/pip_install/private:srcs_module.update` target. Please `bazel run` this target to apply any updates. Note that doing so will discard any local modifications. """ # Each source file is tracked as a target so `pip_repository` rules will know to automatically rebuild if any of the # sources changed. PIP_INSTALL_PY_SRCS = [ - "@rules_python//python/pip_install/extract_wheels:__init__.py", - "@rules_python//python/pip_install/extract_wheels:annotation.py", - "@rules_python//python/pip_install/extract_wheels:arguments.py", - "@rules_python//python/pip_install/extract_wheels:bazel.py", - "@rules_python//python/pip_install/extract_wheels:namespace_pkgs.py", - "@rules_python//python/pip_install/extract_wheels:parse_requirements_to_bzl.py", - "@rules_python//python/pip_install/extract_wheels:wheel.py", - "@rules_python//python/pip_install/extract_wheels:wheel_installer.py", + "@rules_python//python/pip_install/tools/dependency_resolver:__init__.py", + "@rules_python//python/pip_install/tools/dependency_resolver:dependency_resolver.py", + "@rules_python//python/pip_install/tools/lib:__init__.py", + "@rules_python//python/pip_install/tools/lib:annotation.py", + "@rules_python//python/pip_install/tools/lib:arguments.py", + "@rules_python//python/pip_install/tools/lib:bazel.py", + "@rules_python//python/pip_install/tools/lock_file_generator:__init__.py", + "@rules_python//python/pip_install/tools/lock_file_generator:lock_file_generator.py", + "@rules_python//python/pip_install/tools/wheel_installer:namespace_pkgs.py", + "@rules_python//python/pip_install/tools/wheel_installer:wheel.py", + "@rules_python//python/pip_install/tools/wheel_installer:wheel_installer.py", ] diff --git a/python/pip_install/repositories.bzl b/python/pip_install/repositories.bzl index 845da49981..5ce427dc8e 100644 --- a/python/pip_install/repositories.bzl +++ b/python/pip_install/repositories.bzl @@ -89,7 +89,7 @@ py_library( srcs = glob(["**/*.py"]), data = glob(["**/*"], exclude=[ # These entries include those put into user-installed dependencies by - # data_exclude in /python/pip_install/extract_wheels/bazel.py + # data_exclude in /python/pip_install/tools/bazel.py # to avoid non-determinism following pip install's behavior. "**/*.py", "**/*.pyc", diff --git a/python/pip_install/requirements.bzl b/python/pip_install/requirements.bzl index 7e248f625f..043edd49c3 100644 --- a/python/pip_install/requirements.bzl +++ b/python/pip_install/requirements.bzl @@ -57,7 +57,7 @@ def compile_pip_requirements( # Use the Label constructor so this is expanded in the context of the file # where it appears, which is to say, in @rules_python - pip_compile = Label("//python/pip_install:pip_compile.py") + pip_compile = Label("//python/pip_install/tools/dependency_resolver:dependency_resolver.py") loc = "$(rootpath {})" diff --git a/python/pip_install/tools/dependency_resolver/BUILD.bazel b/python/pip_install/tools/dependency_resolver/BUILD.bazel new file mode 100644 index 0000000000..c2cfb39509 --- /dev/null +++ b/python/pip_install/tools/dependency_resolver/BUILD.bazel @@ -0,0 +1,19 @@ +exports_files(["dependency_resolver.py"]) + +filegroup( + name = "distribution", + srcs = glob( + ["*"], + exclude = ["*_test.py"], + ), + visibility = ["//python/pip_install:__subpackages__"], +) + +filegroup( + name = "py_srcs", + srcs = glob( + include = ["**/*.py"], + exclude = ["**/*_test.py"], + ), + visibility = ["//python/pip_install:__subpackages__"], +) diff --git a/python/pip_install/extract_wheels/__init__.py b/python/pip_install/tools/dependency_resolver/__init__.py similarity index 100% rename from python/pip_install/extract_wheels/__init__.py rename to python/pip_install/tools/dependency_resolver/__init__.py diff --git a/python/pip_install/pip_compile.py b/python/pip_install/tools/dependency_resolver/dependency_resolver.py similarity index 100% rename from python/pip_install/pip_compile.py rename to python/pip_install/tools/dependency_resolver/dependency_resolver.py diff --git a/python/pip_install/extract_wheels/BUILD.bazel b/python/pip_install/tools/lib/BUILD.bazel similarity index 58% rename from python/pip_install/extract_wheels/BUILD.bazel rename to python/pip_install/tools/lib/BUILD.bazel index 1cf7e2e1fa..37a8b09be2 100644 --- a/python/pip_install/extract_wheels/BUILD.bazel +++ b/python/pip_install/tools/lib/BUILD.bazel @@ -1,5 +1,4 @@ -load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test") -load("//python/pip_install:repositories.bzl", "requirement") +load("//python:defs.bzl", "py_library", "py_test") load(":annotations_test_helpers.bzl", "package_annotation", "package_annotations_file") py_library( @@ -8,31 +7,8 @@ py_library( "annotation.py", "arguments.py", "bazel.py", - "namespace_pkgs.py", - "parse_requirements_to_bzl.py", - "wheel.py", - "wheel_installer.py", ], - deps = [ - requirement("installer"), - requirement("setuptools"), - ], -) - -py_binary( - name = "wheel_installer", - srcs = [ - "wheel_installer.py", - ], - deps = [":lib"], -) - -py_binary( - name = "parse_requirements_to_bzl", - srcs = [ - "parse_requirements_to_bzl.py", - ], - deps = [":lib"], + visibility = ["//python/pip_install:__subpackages__"], ) package_annotations_file( @@ -70,57 +46,18 @@ py_test( srcs = ["annotations_test.py"], data = [":mock_annotations"], env = {"MOCK_ANNOTATIONS": "$(rootpath :mock_annotations)"}, - tags = ["unit"], deps = [ ":lib", "//python/runfiles", ], ) -py_test( - name = "namespace_pkgs_test", - size = "small", - srcs = [ - "namespace_pkgs_test.py", - ], - tags = ["unit"], - deps = [ - ":lib", - ], -) - -py_test( - name = "wheel_installer_test", - size = "small", - srcs = [ - "wheel_installer_test.py", - ], - data = ["//examples/wheel:minimal_with_py_package"], - tags = ["unit"], - deps = [ - ":lib", - ], -) - py_test( name = "arguments_test", size = "small", srcs = [ "arguments_test.py", ], - tags = ["unit"], - deps = [ - ":lib", - ], -) - -py_test( - name = "parse_requirements_to_bzl_test", - size = "small", - srcs = [ - "parse_requirements_to_bzl_test.py", - ], - tags = ["unit"], deps = [ ":lib", ], diff --git a/python/pip_install/tools/lib/__init__.py b/python/pip_install/tools/lib/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/python/pip_install/extract_wheels/annotation.py b/python/pip_install/tools/lib/annotation.py similarity index 100% rename from python/pip_install/extract_wheels/annotation.py rename to python/pip_install/tools/lib/annotation.py diff --git a/python/pip_install/extract_wheels/annotations_test.py b/python/pip_install/tools/lib/annotations_test.py similarity index 97% rename from python/pip_install/extract_wheels/annotations_test.py rename to python/pip_install/tools/lib/annotations_test.py index 0c41bf70a4..e181c6d93e 100644 --- a/python/pip_install/extract_wheels/annotations_test.py +++ b/python/pip_install/tools/lib/annotations_test.py @@ -5,7 +5,7 @@ import unittest from pathlib import Path -from python.pip_install.extract_wheels.annotation import Annotation, AnnotationsMap +from python.pip_install.tools.lib.annotation import Annotation, AnnotationsMap from python.runfiles import runfiles diff --git a/python/pip_install/extract_wheels/annotations_test_helpers.bzl b/python/pip_install/tools/lib/annotations_test_helpers.bzl similarity index 97% rename from python/pip_install/extract_wheels/annotations_test_helpers.bzl rename to python/pip_install/tools/lib/annotations_test_helpers.bzl index dbd1124670..cef9aebaed 100644 --- a/python/pip_install/extract_wheels/annotations_test_helpers.bzl +++ b/python/pip_install/tools/lib/annotations_test_helpers.bzl @@ -1,4 +1,4 @@ -"""Helper macros and rules for testing the `annotations` module of `extract_wheels`""" +"""Helper macros and rules for testing the `annotations` module of `tools`""" load("//python:pip.bzl", _package_annotation = "package_annotation") diff --git a/python/pip_install/extract_wheels/arguments.py b/python/pip_install/tools/lib/arguments.py similarity index 100% rename from python/pip_install/extract_wheels/arguments.py rename to python/pip_install/tools/lib/arguments.py diff --git a/python/pip_install/extract_wheels/arguments_test.py b/python/pip_install/tools/lib/arguments_test.py similarity index 96% rename from python/pip_install/extract_wheels/arguments_test.py rename to python/pip_install/tools/lib/arguments_test.py index 8a3aec7a37..8c546baee5 100644 --- a/python/pip_install/extract_wheels/arguments_test.py +++ b/python/pip_install/tools/lib/arguments_test.py @@ -2,7 +2,7 @@ import json import unittest -from python.pip_install.extract_wheels import arguments +from python.pip_install.tools.lib import arguments class ArgumentsTestCase(unittest.TestCase): diff --git a/python/pip_install/extract_wheels/bazel.py b/python/pip_install/tools/lib/bazel.py similarity index 100% rename from python/pip_install/extract_wheels/bazel.py rename to python/pip_install/tools/lib/bazel.py diff --git a/python/pip_install/tools/lock_file_generator/BUILD.bazel b/python/pip_install/tools/lock_file_generator/BUILD.bazel new file mode 100644 index 0000000000..804f36a946 --- /dev/null +++ b/python/pip_install/tools/lock_file_generator/BUILD.bazel @@ -0,0 +1,50 @@ +load("//python:defs.bzl", "py_binary", "py_library", "py_test") +load("//python/pip_install:repositories.bzl", "requirement") + +py_library( + name = "lib", + srcs = [ + "lock_file_generator.py", + ], + deps = [ + "//python/pip_install/tools/lib", + requirement("pip"), + ], +) + +py_binary( + name = "lock_file_generator", + srcs = [ + "lock_file_generator.py", + ], + deps = [":lib"], +) + +py_test( + name = "lock_file_generator_test", + size = "small", + srcs = [ + "lock_file_generator_test.py", + ], + deps = [ + ":lib", + ], +) + +filegroup( + name = "distribution", + srcs = glob( + ["*"], + exclude = ["*_test.py"], + ), + visibility = ["//python/pip_install:__subpackages__"], +) + +filegroup( + name = "py_srcs", + srcs = glob( + include = ["**/*.py"], + exclude = ["**/*_test.py"], + ), + visibility = ["//python/pip_install:__subpackages__"], +) diff --git a/python/pip_install/tools/lock_file_generator/__init__.py b/python/pip_install/tools/lock_file_generator/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/python/pip_install/extract_wheels/parse_requirements_to_bzl.py b/python/pip_install/tools/lock_file_generator/lock_file_generator.py similarity index 99% rename from python/pip_install/extract_wheels/parse_requirements_to_bzl.py rename to python/pip_install/tools/lock_file_generator/lock_file_generator.py index 686a57d8b2..18136bfbe5 100644 --- a/python/pip_install/extract_wheels/parse_requirements_to_bzl.py +++ b/python/pip_install/tools/lock_file_generator/lock_file_generator.py @@ -16,7 +16,7 @@ ) from pip._internal.req.req_install import InstallRequirement -from python.pip_install.extract_wheels import annotation, arguments, bazel +from python.pip_install.tools.lib import annotation, arguments, bazel def parse_install_requirements( diff --git a/python/pip_install/extract_wheels/parse_requirements_to_bzl_test.py b/python/pip_install/tools/lock_file_generator/lock_file_generator_test.py similarity index 93% rename from python/pip_install/extract_wheels/parse_requirements_to_bzl_test.py rename to python/pip_install/tools/lock_file_generator/lock_file_generator_test.py index c4879f65c1..0e36f6b0db 100644 --- a/python/pip_install/extract_wheels/parse_requirements_to_bzl_test.py +++ b/python/pip_install/tools/lock_file_generator/lock_file_generator_test.py @@ -7,11 +7,7 @@ from pip._internal.req.req_install import InstallRequirement -from python.pip_install.extract_wheels.parse_requirements_to_bzl import ( - generate_parsed_requirements_contents, - parse_install_requirements, - parse_whl_library_args, -) +from python.pip_install.tools.lock_file_generator import lock_file_generator class TestParseRequirementsToBzl(unittest.TestCase): @@ -36,8 +32,8 @@ def test_generated_requirements_bzl(self) -> None: args.python_interpreter = "/custom/python3" args.python_interpreter_target = "@custom_python//:exec" args.environment = json.dumps({"arg": {}}) - whl_library_args = parse_whl_library_args(args) - contents = generate_parsed_requirements_contents( + whl_library_args = lock_file_generator.parse_whl_library_args(args) + contents = lock_file_generator.generate_parsed_requirements_contents( requirements_lock=args.requirements_lock, repo=args.repo, repo_prefix=args.repo_prefix, @@ -96,7 +92,7 @@ def test_parse_install_requirements_with_args(self): ) ) - install_req_and_lines = parse_install_requirements( + install_req_and_lines = lock_file_generator.parse_install_requirements( str(requirements_lock), ["-v"] ) @@ -134,7 +130,7 @@ def test_parse_install_requirements_pinned_direct_reference(self): ) ) - install_req_and_lines = parse_install_requirements( + install_req_and_lines = lock_file_generator.parse_install_requirements( str(requirements_lock), ["-v"] ) diff --git a/python/pip_install/tools/wheel_installer/BUILD.bazel b/python/pip_install/tools/wheel_installer/BUILD.bazel new file mode 100644 index 0000000000..54bbc46546 --- /dev/null +++ b/python/pip_install/tools/wheel_installer/BUILD.bazel @@ -0,0 +1,66 @@ +load("//python:defs.bzl", "py_binary", "py_library", "py_test") +load("//python/pip_install:repositories.bzl", "requirement") + +py_library( + name = "lib", + srcs = [ + "namespace_pkgs.py", + "wheel.py", + "wheel_installer.py", + ], + deps = [ + "//python/pip_install/tools/lib", + requirement("installer"), + requirement("pip"), + requirement("setuptools"), + ], +) + +py_binary( + name = "wheel_installer", + srcs = [ + "wheel_installer.py", + ], + deps = [":lib"], +) + +py_test( + name = "namespace_pkgs_test", + size = "small", + srcs = [ + "namespace_pkgs_test.py", + ], + deps = [ + ":lib", + ], +) + +py_test( + name = "wheel_installer_test", + size = "small", + srcs = [ + "wheel_installer_test.py", + ], + data = ["//examples/wheel:minimal_with_py_package"], + deps = [ + ":lib", + ], +) + +filegroup( + name = "distribution", + srcs = glob( + ["*"], + exclude = ["*_test.py"], + ), + visibility = ["//python/pip_install:__subpackages__"], +) + +filegroup( + name = "py_srcs", + srcs = glob( + include = ["**/*.py"], + exclude = ["**/*_test.py"], + ), + visibility = ["//python/pip_install:__subpackages__"], +) diff --git a/python/pip_install/extract_wheels/namespace_pkgs.py b/python/pip_install/tools/wheel_installer/namespace_pkgs.py similarity index 100% rename from python/pip_install/extract_wheels/namespace_pkgs.py rename to python/pip_install/tools/wheel_installer/namespace_pkgs.py diff --git a/python/pip_install/extract_wheels/namespace_pkgs_test.py b/python/pip_install/tools/wheel_installer/namespace_pkgs_test.py similarity index 98% rename from python/pip_install/extract_wheels/namespace_pkgs_test.py rename to python/pip_install/tools/wheel_installer/namespace_pkgs_test.py index 8a9d97ca39..5ac3390338 100644 --- a/python/pip_install/extract_wheels/namespace_pkgs_test.py +++ b/python/pip_install/tools/wheel_installer/namespace_pkgs_test.py @@ -5,7 +5,7 @@ import unittest from typing import Optional, Set -from python.pip_install.extract_wheels import namespace_pkgs +from python.pip_install.tools.wheel_installer import namespace_pkgs class TempDir: diff --git a/python/pip_install/extract_wheels/wheel.py b/python/pip_install/tools/wheel_installer/wheel.py similarity index 100% rename from python/pip_install/extract_wheels/wheel.py rename to python/pip_install/tools/wheel_installer/wheel.py diff --git a/python/pip_install/extract_wheels/wheel_installer.py b/python/pip_install/tools/wheel_installer/wheel_installer.py similarity index 99% rename from python/pip_install/extract_wheels/wheel_installer.py rename to python/pip_install/tools/wheel_installer/wheel_installer.py index 87fe1fd9a2..d525da8077 100644 --- a/python/pip_install/extract_wheels/wheel_installer.py +++ b/python/pip_install/tools/wheel_installer/wheel_installer.py @@ -14,13 +14,8 @@ from pip._vendor.packaging.utils import canonicalize_name -from python.pip_install.extract_wheels import ( - annotation, - arguments, - bazel, - namespace_pkgs, - wheel, -) +from python.pip_install.tools.lib import annotation, arguments, bazel +from python.pip_install.tools.wheel_installer import namespace_pkgs, wheel def _configure_reproducible_wheels() -> None: diff --git a/python/pip_install/extract_wheels/wheel_installer_test.py b/python/pip_install/tools/wheel_installer/wheel_installer_test.py similarity index 97% rename from python/pip_install/extract_wheels/wheel_installer_test.py rename to python/pip_install/tools/wheel_installer/wheel_installer_test.py index ff667d7280..878867f51e 100644 --- a/python/pip_install/extract_wheels/wheel_installer_test.py +++ b/python/pip_install/tools/wheel_installer/wheel_installer_test.py @@ -4,7 +4,7 @@ import unittest from pathlib import Path -from python.pip_install.extract_wheels import wheel_installer +from python.pip_install.tools.wheel_installer import wheel_installer class TestRequirementExtrasParsing(unittest.TestCase): From 7e2d4ecb456229cf03e1ef7985c2e9a50ae99615 Mon Sep 17 00:00:00 2001 From: Fabian Meumertzheim Date: Thu, 12 Jan 2023 04:46:30 +0100 Subject: [PATCH 106/234] Update runfiles lib (#982) * runfiles: Find runfiles in directories that are themselves runfiles Cherry-picks a fix added to the Bazel version of the runfiles library in https://github.com/bazelbuild/bazel/commit/486d153d1981c3f47129f675de20189667667fa7 * runfiles: Add tests from Bazel --- python/runfiles/runfiles.py | 17 +- tests/runfiles/BUILD.bazel | 7 + tests/runfiles/runfiles_test.py | 375 ++++++++++++++++++++++++++++++++ 3 files changed, 398 insertions(+), 1 deletion(-) create mode 100644 tests/runfiles/BUILD.bazel create mode 100644 tests/runfiles/runfiles_test.py diff --git a/python/runfiles/runfiles.py b/python/runfiles/runfiles.py index d7417ec7d1..293af3a49b 100644 --- a/python/runfiles/runfiles.py +++ b/python/runfiles/runfiles.py @@ -200,7 +200,22 @@ def __init__(self, path): def RlocationChecked(self, path): # type: (str) -> Optional[str] - return self._runfiles.get(path) + """Returns the runtime path of a runfile.""" + exact_match = self._runfiles.get(path) + if exact_match: + return exact_match + # If path references a runfile that lies under a directory that + # itself is a runfile, then only the directory is listed in the + # manifest. Look up all prefixes of path in the manifest and append + # the relative path from the prefix to the looked up path. + prefix_end = len(path) + while True: + prefix_end = path.rfind("/", 0, prefix_end - 1) + if prefix_end == -1: + return None + prefix_match = self._runfiles.get(path[0:prefix_end]) + if prefix_match: + return prefix_match + "/" + path[prefix_end + 1 :] @staticmethod def _LoadRunfiles(path): diff --git a/tests/runfiles/BUILD.bazel b/tests/runfiles/BUILD.bazel new file mode 100644 index 0000000000..d62e179211 --- /dev/null +++ b/tests/runfiles/BUILD.bazel @@ -0,0 +1,7 @@ +load("@rules_python//python:defs.bzl", "py_test") + +py_test( + name = "runfiles_test", + srcs = ["runfiles_test.py"], + deps = ["//python/runfiles"], +) diff --git a/tests/runfiles/runfiles_test.py b/tests/runfiles/runfiles_test.py new file mode 100644 index 0000000000..958ca01637 --- /dev/null +++ b/tests/runfiles/runfiles_test.py @@ -0,0 +1,375 @@ +# pylint: disable=g-bad-file-header +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import tempfile +import unittest + +from python.runfiles import runfiles + + +class RunfilesTest(unittest.TestCase): + # """Unit tests for `runfiles.Runfiles`.""" + + def testRlocationArgumentValidation(self): + r = runfiles.Create({"RUNFILES_DIR": "whatever"}) + self.assertRaises(ValueError, lambda: r.Rlocation(None)) + self.assertRaises(ValueError, lambda: r.Rlocation("")) + self.assertRaises(TypeError, lambda: r.Rlocation(1)) + self.assertRaisesRegex( + ValueError, "is not normalized", lambda: r.Rlocation("../foo") + ) + self.assertRaisesRegex( + ValueError, "is not normalized", lambda: r.Rlocation("foo/..") + ) + self.assertRaisesRegex( + ValueError, "is not normalized", lambda: r.Rlocation("foo/../bar") + ) + self.assertRaisesRegex( + ValueError, "is not normalized", lambda: r.Rlocation("./foo") + ) + self.assertRaisesRegex( + ValueError, "is not normalized", lambda: r.Rlocation("foo/.") + ) + self.assertRaisesRegex( + ValueError, "is not normalized", lambda: r.Rlocation("foo/./bar") + ) + self.assertRaisesRegex( + ValueError, "is not normalized", lambda: r.Rlocation("//foobar") + ) + self.assertRaisesRegex( + ValueError, "is not normalized", lambda: r.Rlocation("foo//") + ) + self.assertRaisesRegex( + ValueError, "is not normalized", lambda: r.Rlocation("foo//bar") + ) + self.assertRaisesRegex( + ValueError, + "is absolute without a drive letter", + lambda: r.Rlocation("\\foo"), + ) + + def testCreatesManifestBasedRunfiles(self): + with _MockFile(contents=["a/b c/d"]) as mf: + r = runfiles.Create( + { + "RUNFILES_MANIFEST_FILE": mf.Path(), + "RUNFILES_DIR": "ignored when RUNFILES_MANIFEST_FILE has a value", + "TEST_SRCDIR": "always ignored", + } + ) + self.assertEqual(r.Rlocation("a/b"), "c/d") + self.assertIsNone(r.Rlocation("foo")) + + def testManifestBasedRunfilesEnvVars(self): + with _MockFile(name="MANIFEST") as mf: + r = runfiles.Create( + { + "RUNFILES_MANIFEST_FILE": mf.Path(), + "TEST_SRCDIR": "always ignored", + } + ) + self.assertDictEqual( + r.EnvVars(), + { + "RUNFILES_MANIFEST_FILE": mf.Path(), + "RUNFILES_DIR": mf.Path()[: -len("/MANIFEST")], + "JAVA_RUNFILES": mf.Path()[: -len("/MANIFEST")], + }, + ) + + with _MockFile(name="foo.runfiles_manifest") as mf: + r = runfiles.Create( + { + "RUNFILES_MANIFEST_FILE": mf.Path(), + "TEST_SRCDIR": "always ignored", + } + ) + self.assertDictEqual( + r.EnvVars(), + { + "RUNFILES_MANIFEST_FILE": mf.Path(), + "RUNFILES_DIR": ( + mf.Path()[: -len("foo.runfiles_manifest")] + "foo.runfiles" + ), + "JAVA_RUNFILES": ( + mf.Path()[: -len("foo.runfiles_manifest")] + "foo.runfiles" + ), + }, + ) + + with _MockFile(name="x_manifest") as mf: + r = runfiles.Create( + { + "RUNFILES_MANIFEST_FILE": mf.Path(), + "TEST_SRCDIR": "always ignored", + } + ) + self.assertDictEqual( + r.EnvVars(), + { + "RUNFILES_MANIFEST_FILE": mf.Path(), + "RUNFILES_DIR": "", + "JAVA_RUNFILES": "", + }, + ) + + def testCreatesDirectoryBasedRunfiles(self): + r = runfiles.Create( + { + "RUNFILES_DIR": "runfiles/dir", + "TEST_SRCDIR": "always ignored", + } + ) + self.assertEqual(r.Rlocation("a/b"), "runfiles/dir/a/b") + self.assertEqual(r.Rlocation("foo"), "runfiles/dir/foo") + + def testDirectoryBasedRunfilesEnvVars(self): + r = runfiles.Create( + { + "RUNFILES_DIR": "runfiles/dir", + "TEST_SRCDIR": "always ignored", + } + ) + self.assertDictEqual( + r.EnvVars(), + { + "RUNFILES_DIR": "runfiles/dir", + "JAVA_RUNFILES": "runfiles/dir", + }, + ) + + def testFailsToCreateManifestBasedBecauseManifestDoesNotExist(self): + def _Run(): + runfiles.Create({"RUNFILES_MANIFEST_FILE": "non-existing path"}) + + self.assertRaisesRegex(IOError, "non-existing path", _Run) + + def testFailsToCreateAnyRunfilesBecauseEnvvarsAreNotDefined(self): + with _MockFile(contents=["a b"]) as mf: + runfiles.Create( + { + "RUNFILES_MANIFEST_FILE": mf.Path(), + "RUNFILES_DIR": "whatever", + "TEST_SRCDIR": "always ignored", + } + ) + runfiles.Create( + { + "RUNFILES_DIR": "whatever", + "TEST_SRCDIR": "always ignored", + } + ) + self.assertIsNone(runfiles.Create({"TEST_SRCDIR": "always ignored"})) + self.assertIsNone(runfiles.Create({"FOO": "bar"})) + + def testManifestBasedRlocation(self): + with _MockFile( + contents=[ + "Foo/runfile1", + "Foo/runfile2 C:/Actual Path\\runfile2", + "Foo/Bar/runfile3 D:\\the path\\run file 3.txt", + "Foo/Bar/Dir E:\\Actual Path\\Directory", + ] + ) as mf: + r = runfiles.CreateManifestBased(mf.Path()) + self.assertEqual(r.Rlocation("Foo/runfile1"), "Foo/runfile1") + self.assertEqual(r.Rlocation("Foo/runfile2"), "C:/Actual Path\\runfile2") + self.assertEqual( + r.Rlocation("Foo/Bar/runfile3"), "D:\\the path\\run file 3.txt" + ) + self.assertEqual( + r.Rlocation("Foo/Bar/Dir/runfile4"), + "E:\\Actual Path\\Directory/runfile4", + ) + self.assertEqual( + r.Rlocation("Foo/Bar/Dir/Deeply/Nested/runfile4"), + "E:\\Actual Path\\Directory/Deeply/Nested/runfile4", + ) + self.assertIsNone(r.Rlocation("unknown")) + if RunfilesTest.IsWindows(): + self.assertEqual(r.Rlocation("c:/foo"), "c:/foo") + self.assertEqual(r.Rlocation("c:\\foo"), "c:\\foo") + else: + self.assertEqual(r.Rlocation("/foo"), "/foo") + + def testDirectoryBasedRlocation(self): + # The _DirectoryBased strategy simply joins the runfiles directory and the + # runfile's path on a "/". This strategy does not perform any normalization, + # nor does it check that the path exists. + r = runfiles.CreateDirectoryBased("foo/bar baz//qux/") + self.assertEqual(r.Rlocation("arg"), "foo/bar baz//qux/arg") + if RunfilesTest.IsWindows(): + self.assertEqual(r.Rlocation("c:/foo"), "c:/foo") + self.assertEqual(r.Rlocation("c:\\foo"), "c:\\foo") + else: + self.assertEqual(r.Rlocation("/foo"), "/foo") + + def testPathsFromEnvvars(self): + # Both envvars have a valid value. + mf, dr = runfiles._PathsFrom( + "argv0", + "mock1/MANIFEST", + "mock2", + lambda path: path == "mock1/MANIFEST", + lambda path: path == "mock2", + ) + self.assertEqual(mf, "mock1/MANIFEST") + self.assertEqual(dr, "mock2") + + # RUNFILES_MANIFEST_FILE is invalid but RUNFILES_DIR is good and there's a + # runfiles manifest in the runfiles directory. + mf, dr = runfiles._PathsFrom( + "argv0", + "mock1/MANIFEST", + "mock2", + lambda path: path == "mock2/MANIFEST", + lambda path: path == "mock2", + ) + self.assertEqual(mf, "mock2/MANIFEST") + self.assertEqual(dr, "mock2") + + # RUNFILES_MANIFEST_FILE is invalid but RUNFILES_DIR is good, but there's no + # runfiles manifest in the runfiles directory. + mf, dr = runfiles._PathsFrom( + "argv0", + "mock1/MANIFEST", + "mock2", + lambda path: False, + lambda path: path == "mock2", + ) + self.assertEqual(mf, "") + self.assertEqual(dr, "mock2") + + # RUNFILES_DIR is invalid but RUNFILES_MANIFEST_FILE is good, and it is in + # a valid-looking runfiles directory. + mf, dr = runfiles._PathsFrom( + "argv0", + "mock1/MANIFEST", + "mock2", + lambda path: path == "mock1/MANIFEST", + lambda path: path == "mock1", + ) + self.assertEqual(mf, "mock1/MANIFEST") + self.assertEqual(dr, "mock1") + + # RUNFILES_DIR is invalid but RUNFILES_MANIFEST_FILE is good, but it is not + # in any valid-looking runfiles directory. + mf, dr = runfiles._PathsFrom( + "argv0", + "mock1/MANIFEST", + "mock2", + lambda path: path == "mock1/MANIFEST", + lambda path: False, + ) + self.assertEqual(mf, "mock1/MANIFEST") + self.assertEqual(dr, "") + + # Both envvars are invalid, but there's a manifest in a runfiles directory + # next to argv0, however there's no other content in the runfiles directory. + mf, dr = runfiles._PathsFrom( + "argv0", + "mock1/MANIFEST", + "mock2", + lambda path: path == "argv0.runfiles/MANIFEST", + lambda path: False, + ) + self.assertEqual(mf, "argv0.runfiles/MANIFEST") + self.assertEqual(dr, "") + + # Both envvars are invalid, but there's a manifest next to argv0. There's + # no runfiles tree anywhere. + mf, dr = runfiles._PathsFrom( + "argv0", + "mock1/MANIFEST", + "mock2", + lambda path: path == "argv0.runfiles_manifest", + lambda path: False, + ) + self.assertEqual(mf, "argv0.runfiles_manifest") + self.assertEqual(dr, "") + + # Both envvars are invalid, but there's a valid manifest next to argv0, and + # a valid runfiles directory (without a manifest in it). + mf, dr = runfiles._PathsFrom( + "argv0", + "mock1/MANIFEST", + "mock2", + lambda path: path == "argv0.runfiles_manifest", + lambda path: path == "argv0.runfiles", + ) + self.assertEqual(mf, "argv0.runfiles_manifest") + self.assertEqual(dr, "argv0.runfiles") + + # Both envvars are invalid, but there's a valid runfiles directory next to + # argv0, though no manifest in it. + mf, dr = runfiles._PathsFrom( + "argv0", + "mock1/MANIFEST", + "mock2", + lambda path: False, + lambda path: path == "argv0.runfiles", + ) + self.assertEqual(mf, "") + self.assertEqual(dr, "argv0.runfiles") + + # Both envvars are invalid, but there's a valid runfiles directory next to + # argv0 with a valid manifest in it. + mf, dr = runfiles._PathsFrom( + "argv0", + "mock1/MANIFEST", + "mock2", + lambda path: path == "argv0.runfiles/MANIFEST", + lambda path: path == "argv0.runfiles", + ) + self.assertEqual(mf, "argv0.runfiles/MANIFEST") + self.assertEqual(dr, "argv0.runfiles") + + # Both envvars are invalid and there's no runfiles directory or manifest + # next to the argv0. + mf, dr = runfiles._PathsFrom( + "argv0", "mock1/MANIFEST", "mock2", lambda path: False, lambda path: False + ) + self.assertEqual(mf, "") + self.assertEqual(dr, "") + + @staticmethod + def IsWindows(): + return os.name == "nt" + + +class _MockFile(object): + def __init__(self, name=None, contents=None): + self._contents = contents or [] + self._name = name or "x" + self._path = None + + def __enter__(self): + tmpdir = os.environ.get("TEST_TMPDIR") + self._path = os.path.join(tempfile.mkdtemp(dir=tmpdir), self._name) + with open(self._path, "wt") as f: + f.writelines(l + "\n" for l in self._contents) + return self + + def __exit__(self, exc_type, exc_value, traceback): + os.remove(self._path) + os.rmdir(os.path.dirname(self._path)) + + def Path(self): + return self._path + + +if __name__ == "__main__": + unittest.main() From 07c1741b98ef07c8f7b566c838aaac1519a322ad Mon Sep 17 00:00:00 2001 From: Greg Roodt Date: Sun, 15 Jan 2023 05:34:45 +1100 Subject: [PATCH 107/234] Refactor poor naming and unused code in wheel_installer (#990) The incremental_dir parameter is a confusing name. There are 2 unused private functions. incremental_dir renamed to installation_dir to be a more descriptive name. The 2 unused functions are removed. --- .../tools/wheel_installer/wheel_installer.py | 25 +++++-------------- .../wheel_installer/wheel_installer_test.py | 2 +- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/python/pip_install/tools/wheel_installer/wheel_installer.py b/python/pip_install/tools/wheel_installer/wheel_installer.py index d525da8077..a324fbb3e3 100644 --- a/python/pip_install/tools/wheel_installer/wheel_installer.py +++ b/python/pip_install/tools/wheel_installer/wheel_installer.py @@ -275,43 +275,31 @@ def _generate_build_file_contents( ) -def _sanitised_library_label(whl_name: str, prefix: str) -> str: - return '"//%s"' % bazel.sanitise_name(whl_name, prefix) - - -def _sanitised_file_label(whl_name: str, prefix: str) -> str: - return '"//%s:%s"' % (bazel.sanitise_name(whl_name, prefix), bazel.WHEEL_FILE_LABEL) - - def _extract_wheel( wheel_file: str, extras: Dict[str, Set[str]], pip_data_exclude: List[str], enable_implicit_namespace_pkgs: bool, repo_prefix: str, - incremental_dir: Path = Path("."), + installation_dir: Path = Path("."), annotation: Optional[annotation.Annotation] = None, ) -> None: """Extracts wheel into given directory and creates py_library and filegroup targets. Args: wheel_file: the filepath of the .whl + installation_dir: the destination directory for installation of the wheel. extras: a list of extras to add as dependencies for the installed wheel pip_data_exclude: list of file patterns to exclude from the generated data section of the py_library enable_implicit_namespace_pkgs: if true, disables conversion of implicit namespace packages and will unzip as-is - incremental_dir: An optional override for the working directory of incremental builds. annotation: An optional set of annotations to apply to the BUILD contents of the wheel. - - Returns: - The Bazel label for the extracted wheel, in the form '//path/to/wheel'. """ whl = wheel.Wheel(wheel_file) - directory = incremental_dir - whl.unzip(directory) + whl.unzip(installation_dir) if not enable_implicit_namespace_pkgs: - _setup_namespace_pkg_compatibility(directory) + _setup_namespace_pkg_compatibility(installation_dir) extras_requested = extras[whl.name] if whl.name in extras else set() # Packages may create dependency cycles when specifying optional-dependencies / 'extras'. @@ -326,7 +314,6 @@ def _extract_wheel( bazel.sanitised_repo_file_label(d, repo_prefix=repo_prefix) for d in whl_deps ] - directory_path = Path(directory) entry_points = [] for name, (module, attribute) in sorted(whl.entry_points().items()): # There is an extreme edge-case with entry_points that end with `.py` @@ -336,7 +323,7 @@ def _extract_wheel( f"{bazel.WHEEL_ENTRY_POINT_PREFIX}_{entry_point_without_py}" ) entry_point_script_name = f"{entry_point_target_name}.py" - (directory_path / entry_point_script_name).write_text( + (installation_dir / entry_point_script_name).write_text( _generate_entry_point_contents(module, attribute) ) entry_points.append( @@ -347,7 +334,7 @@ def _extract_wheel( ) ) - with open(os.path.join(directory, "BUILD.bazel"), "w") as build_file: + with open(os.path.join(installation_dir, "BUILD.bazel"), "w") as build_file: additional_content = entry_points data = [] data_exclude = pip_data_exclude diff --git a/python/pip_install/tools/wheel_installer/wheel_installer_test.py b/python/pip_install/tools/wheel_installer/wheel_installer_test.py index 878867f51e..2a6c29314a 100644 --- a/python/pip_install/tools/wheel_installer/wheel_installer_test.py +++ b/python/pip_install/tools/wheel_installer/wheel_installer_test.py @@ -77,11 +77,11 @@ def tearDown(self): def test_wheel_exists(self) -> None: wheel_installer._extract_wheel( self.wheel_path, + installation_dir=Path(self.wheel_dir), extras={}, pip_data_exclude=[], enable_implicit_namespace_pkgs=False, repo_prefix="prefix_", - incremental_dir=Path(self.wheel_dir), ) self.assertIn(self.wheel_name, os.listdir(self.wheel_dir)) From 1487a0c416be8bb5d1033b3815fb662527c99197 Mon Sep 17 00:00:00 2001 From: Jeremy Volkman Date: Tue, 17 Jan 2023 22:04:56 -0800 Subject: [PATCH 108/234] Add new Python versions including 3.11 (#992) Also bumps some minor versions: * 3.9 from 3.9.15 to 3.9.16 * 3.10 from 3.10.8 to 3.10.9 --- python/versions.bzl | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/python/versions.bzl b/python/versions.bzl index dfe4320025..56d7ae1f1c 100644 --- a/python/versions.bzl +++ b/python/versions.bzl @@ -113,6 +113,17 @@ TOOL_VERSIONS = { }, "strip_prefix": "python", }, + "3.9.16": { + "url": "20230116/cpython-{python_version}+20230116-{platform}-{build}.tar.gz", + "sha256": { + "aarch64-apple-darwin": "d732d212d42315ac27c6da3e0b69636737a8d72086c980daf844344c010cab80", + "aarch64-unknown-linux-gnu": "1ba520c0db431c84305677f56eb9a4254f5097430ed443e92fc8617f8fba973d", + "x86_64-apple-darwin": "3948384af5e8d4ee7e5ccc648322b99c1c5cf4979954ed5e6b3382c69d6db71e", + "x86_64-pc-windows-msvc": "5274afd6b7ff2bddbd8306385ffb2336764b0e58535db968daeac656246f59a8", + "x86_64-unknown-linux-gnu": "7ba397787932393e65fc2fb9fcfabf54f2bb6751d5da2b45913cb25b2d493758", + }, + "strip_prefix": "python", + }, "3.10.2": { "url": "20220227/cpython-{python_version}+20220227-{platform}-{build}.tar.gz", "sha256": { @@ -157,13 +168,36 @@ TOOL_VERSIONS = { }, "strip_prefix": "python", }, + "3.10.9": { + "url": "20230116/cpython-{python_version}+20230116-{platform}-{build}.tar.gz", + "sha256": { + "aarch64-apple-darwin": "018d05a779b2de7a476f3b3ff2d10f503d69d14efcedd0774e6dab8c22ef84ff", + "aarch64-unknown-linux-gnu": "2003750f40cd09d4bf7a850342613992f8d9454f03b3c067989911fb37e7a4d1", + "x86_64-apple-darwin": "0e685f98dce0e5bc8da93c7081f4e6c10219792e223e4b5886730fd73a7ba4c6", + "x86_64-pc-windows-msvc": "59c6970cecb357dc1d8554bd0540eb81ee7f6d16a07acf3d14ed294ece02c035", + "x86_64-unknown-linux-gnu": "d196347aeb701a53fe2bb2b095abec38d27d0fa0443f8a1c2023a1bed6e18cdf", + }, + "strip_prefix": "python", + }, + "3.11.1": { + "url": "20230116/cpython-{python_version}+20230116-{platform}-{build}.tar.gz", + "sha256": { + "aarch64-apple-darwin": "4918cdf1cab742a90f85318f88b8122aeaa2d04705803c7b6e78e81a3dd40f80", + "aarch64-unknown-linux-gnu": "debf15783bdcb5530504f533d33fda75a7b905cec5361ae8f33da5ba6599f8b4", + "x86_64-apple-darwin": "20a4203d069dc9b710f70b09e7da2ce6f473d6b1110f9535fb6f4c469ed54733", + "x86_64-pc-windows-msvc": "edc08979cb0666a597466176511529c049a6f0bba8adf70df441708f766de5bf", + "x86_64-unknown-linux-gnu": "02a551fefab3750effd0e156c25446547c238688a32fabde2995c941c03a6423", + }, + "strip_prefix": "python", + }, } # buildifier: disable=unsorted-dict-items MINOR_MAPPING = { "3.8": "3.8.15", - "3.9": "3.9.15", - "3.10": "3.10.8", + "3.9": "3.9.16", + "3.10": "3.10.9", + "3.11": "3.11.1", } PLATFORMS = { From 3ebd927df0f407c488b9c981fcea4dc06d572b1a Mon Sep 17 00:00:00 2001 From: Fabian Meumertzheim Date: Wed, 18 Jan 2023 23:09:20 +0100 Subject: [PATCH 109/234] runfiles: Drop outdated comments about vendoring (#986) The runfiles library now canonically lives in rules_python and has been updated multiple times since its original import from bazel_tools. --- python/runfiles/BUILD.bazel | 17 ----------------- python/runfiles/runfiles.py | 6 ------ 2 files changed, 23 deletions(-) diff --git a/python/runfiles/BUILD.bazel b/python/runfiles/BUILD.bazel index fa824ada0e..2089c418d8 100644 --- a/python/runfiles/BUILD.bazel +++ b/python/runfiles/BUILD.bazel @@ -12,23 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# We'd like to alias the runfiles target @bazel_tools//tools/python/runfiles. -# However, we need its source file to exist in the runfiles tree under this -# repo's name, so that it can be imported as -# -# from rules_python.python.runfiles import runfiles -# -# in user code. This requires either adding a symlink to runfiles or copying -# the file with an action. -# -# Both solutions are made more difficult by the fact that runfiles.py is not -# directly exported by its package. We could try to get a handle on its File -# object by unpacking the runfiles target's providers, but this seems hacky -# and is probably more effort than it's worth. Also, it's not trivial to copy -# files in a cross-platform (i.e. Windows-friendly) way. -# -# So instead, we just vendor in runfiles.py here. - load("//python:defs.bzl", "py_library") filegroup( diff --git a/python/runfiles/runfiles.py b/python/runfiles/runfiles.py index 293af3a49b..01d4986d97 100644 --- a/python/runfiles/runfiles.py +++ b/python/runfiles/runfiles.py @@ -12,12 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -############################################################################### -# Vendored in from bazelbuild/bazel (tools/python/runfiles/runfiles.py) at # -# commit 6c60a8ec049b6b8540c473969dd7bd1dad46acb9 (2019-07-19). See # -# //python/runfiles:BUILD for details. # -############################################################################### - """Runfiles lookup library for Bazel-built Python binaries and tests. USAGE: From 0d3c4f76af0128d42b87f710ba4c4a8ad5a3cbc4 Mon Sep 17 00:00:00 2001 From: Ivo List Date: Wed, 18 Jan 2023 23:15:52 +0000 Subject: [PATCH 110/234] Implement py_proto_library (#832) * Add py_proto_library * Bump versions of rules_proto and protobuf * Update documentation * Bump rules_pkg version --- MODULE.bazel | 4 + README.md | 2 +- internal_deps.bzl | 27 ++- internal_setup.bzl | 7 + python/private/BUILD.bazel | 2 +- python/private/proto/BUILD | 32 ++++ python/private/proto/py_proto_library.bzl | 191 ++++++++++++++++++++++ python/proto.bzl | 21 +++ 8 files changed, 281 insertions(+), 5 deletions(-) create mode 100644 python/private/proto/BUILD create mode 100644 python/private/proto/py_proto_library.bzl create mode 100644 python/proto.bzl diff --git a/MODULE.bazel b/MODULE.bazel index 6afe365f69..f337db3cf0 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -6,6 +6,10 @@ module( bazel_dep(name = "platforms", version = "0.0.4") +# Those are loaded only when using py_proto_library +bazel_dep(name = "rules_proto", version = "5.3.0-21.7") +bazel_dep(name = "protobuf", repo_name = "com_google_protobuf", version = "21.7") + internal_deps = use_extension("@rules_python//python:extensions.bzl", "internal_deps") internal_deps.install() use_repo( diff --git a/README.md b/README.md index 53f195672e..a509e28d7e 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ ## Overview This repository is the home of the core Python rules -- `py_library`, -`py_binary`, `py_test`, and related symbols that provide the basis for Python +`py_binary`, `py_test`, `py_proto_library`, and related symbols that provide the basis for Python support in Bazel. It also contains package installation rules for integrating with PyPI and other package indices. Documentation lives in the [`docs/`](https://github.com/bazelbuild/rules_python/tree/main/docs) directory and in the diff --git a/internal_deps.bzl b/internal_deps.bzl index a41d5fb34b..942a8720e2 100644 --- a/internal_deps.bzl +++ b/internal_deps.bzl @@ -20,10 +20,10 @@ def rules_python_internal_deps(): http_archive, name = "rules_pkg", urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/rules_pkg/releases/download/0.2.4/rules_pkg-0.2.4.tar.gz", - "https://github.com/bazelbuild/rules_pkg/releases/download/0.2.4/rules_pkg-0.2.4.tar.gz", + "https://mirror.bazel.build/github.com/bazelbuild/rules_pkg/releases/download/0.7.0/rules_pkg-0.7.0.tar.gz", + "https://github.com/bazelbuild/rules_pkg/releases/download/0.7.0/rules_pkg-0.7.0.tar.gz", ], - sha256 = "4ba8f4ab0ff85f2484287ab06c0d871dcb31cc54d439457d28fd4ae14b18450a", + sha256 = "8a298e832762eda1830597d64fe7db58178aa84cd5926d76d5b744d6558941c2", ) maybe( @@ -124,3 +124,24 @@ def rules_python_internal_deps(): strip_prefix = "bazel-integration-testing-165440b2dbda885f8d1ccb8d0f417e6cf8c54f17", sha256 = "2401b1369ef44cc42f91dc94443ef491208dbd06da1e1e10b702d8c189f098e3", ) + + maybe( + http_archive, + name = "rules_proto", + sha256 = "dc3fb206a2cb3441b485eb1e423165b231235a1ea9b031b4433cf7bc1fa460dd", + strip_prefix = "rules_proto-5.3.0-21.7", + urls = [ + "https://github.com/bazelbuild/rules_proto/archive/refs/tags/5.3.0-21.7.tar.gz", + ], + ) + + maybe( + http_archive, + name = "com_google_protobuf", + sha256 = "75be42bd736f4df6d702a0e4e4d30de9ee40eac024c4b845d17ae4cc831fe4ae", + strip_prefix = "protobuf-21.7", + urls = [ + "https://mirror.bazel.build/github.com/protocolbuffers/protobuf/archive/v21.7.tar.gz", + "https://github.com/protocolbuffers/protobuf/archive/v21.7.tar.gz", + ], + ) diff --git a/internal_setup.bzl b/internal_setup.bzl index f4d3a1a8db..57eecc2116 100644 --- a/internal_setup.bzl +++ b/internal_setup.bzl @@ -17,7 +17,9 @@ load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies") load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") load("@build_bazel_integration_testing//tools:repositories.bzl", "bazel_binaries") +load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") +load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains") load("//:version.bzl", "SUPPORTED_BAZEL_VERSIONS") load("//gazelle:deps.bzl", _go_repositories = "gazelle_deps") load("//python/pip_install:repositories.bzl", "pip_install_dependencies") @@ -41,3 +43,8 @@ def rules_python_internal_setup(): go_register_toolchains(version = "1.19.2") gazelle_dependencies() + + rules_proto_dependencies() + rules_proto_toolchains() + + protobuf_deps() diff --git a/python/private/BUILD.bazel b/python/private/BUILD.bazel index c99b040103..75e48bc70a 100644 --- a/python/private/BUILD.bazel +++ b/python/private/BUILD.bazel @@ -19,7 +19,7 @@ licenses(["notice"]) # Apache 2.0 filegroup( name = "distribution", - srcs = glob(["**"]), + srcs = glob(["**"]) + ["//python/private/proto:distribution"], visibility = ["//python:__pkg__"], ) diff --git a/python/private/proto/BUILD b/python/private/proto/BUILD new file mode 100644 index 0000000000..8483d19c2f --- /dev/null +++ b/python/private/proto/BUILD @@ -0,0 +1,32 @@ +# Copyright 2022 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("@rules_proto//proto:defs.bzl", "proto_lang_toolchain") + +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) # Apache 2.0 + +filegroup( + name = "distribution", + srcs = glob(["**"]), + visibility = ["//python/private:__pkg__"], +) + +proto_lang_toolchain( + name = "python_toolchain", + command_line = "--python_out=%s", + progress_message = "Generating Python proto_library %{label}", + runtime = "@com_google_protobuf//:protobuf_python", +) diff --git a/python/private/proto/py_proto_library.bzl b/python/private/proto/py_proto_library.bzl new file mode 100644 index 0000000000..ef5f2cae70 --- /dev/null +++ b/python/private/proto/py_proto_library.bzl @@ -0,0 +1,191 @@ +# Copyright 2022 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""The implementation of the `py_proto_library` rule and its aspect.""" + +load("@rules_proto//proto:defs.bzl", "ProtoInfo", "proto_common") +load("//python:defs.bzl", "PyInfo") + +ProtoLangToolchainInfo = proto_common.ProtoLangToolchainInfo + +_PyProtoInfo = provider( + doc = "Encapsulates information needed by the Python proto rules.", + fields = { + "runfiles_from_proto_deps": """ + (depset[File]) Files from the transitive closure implicit proto + dependencies""", + "transitive_sources": """(depset[File]) The Python sources.""", + }, +) + +def _filter_provider(provider, *attrs): + return [dep[provider] for attr in attrs for dep in attr if provider in dep] + +def _py_proto_aspect_impl(target, ctx): + """Generates and compiles Python code for a proto_library. + + The function runs protobuf compiler on the `proto_library` target generating + a .py file for each .proto file. + + Args: + target: (Target) A target providing `ProtoInfo`. Usually this means a + `proto_library` target, but not always; you must expect to visit + non-`proto_library` targets, too. + ctx: (RuleContext) The rule context. + + Returns: + ([_PyProtoInfo]) Providers collecting transitive information about + generated files. + """ + + _proto_library = ctx.rule.attr + + # Check Proto file names + for proto in target[ProtoInfo].direct_sources: + if proto.is_source and "-" in proto.dirname: + fail("Cannot generate Python code for a .proto whose path contains '-' ({}).".format( + proto.path, + )) + + proto_lang_toolchain_info = ctx.attr._aspect_proto_toolchain[ProtoLangToolchainInfo] + api_deps = [proto_lang_toolchain_info.runtime] + + generated_sources = [] + proto_info = target[ProtoInfo] + if proto_info.direct_sources: + # Generate py files + generated_sources = proto_common.declare_generated_files( + actions = ctx.actions, + proto_info = proto_info, + extension = "_pb2.py", + name_mapper = lambda name: name.replace("-", "_").replace(".", "/"), + ) + + proto_common.compile( + actions = ctx.actions, + proto_info = proto_info, + proto_lang_toolchain_info = proto_lang_toolchain_info, + generated_files = generated_sources, + plugin_output = ctx.bin_dir.path, + ) + + # Generated sources == Python sources + python_sources = generated_sources + + deps = _filter_provider(_PyProtoInfo, getattr(_proto_library, "deps", [])) + runfiles_from_proto_deps = depset( + transitive = [dep[DefaultInfo].default_runfiles.files for dep in api_deps] + + [dep.runfiles_from_proto_deps for dep in deps], + ) + transitive_sources = depset( + direct = python_sources, + transitive = [dep.transitive_sources for dep in deps], + ) + + return [ + _PyProtoInfo( + runfiles_from_proto_deps = runfiles_from_proto_deps, + transitive_sources = transitive_sources, + ), + ] + +_py_proto_aspect = aspect( + implementation = _py_proto_aspect_impl, + attrs = { + "_aspect_proto_toolchain": attr.label( + default = ":python_toolchain", + ), + }, + attr_aspects = ["deps"], + required_providers = [ProtoInfo], + provides = [_PyProtoInfo], +) + +def _py_proto_library_rule(ctx): + """Merges results of `py_proto_aspect` in `deps`. + + Args: + ctx: (RuleContext) The rule context. + Returns: + ([PyInfo, DefaultInfo, OutputGroupInfo]) + """ + if not ctx.attr.deps: + fail("'deps' attribute mustn't be empty.") + + pyproto_infos = _filter_provider(_PyProtoInfo, ctx.attr.deps) + default_outputs = depset( + transitive = [info.transitive_sources for info in pyproto_infos], + ) + + return [ + DefaultInfo( + files = default_outputs, + default_runfiles = ctx.runfiles(transitive_files = depset( + transitive = + [default_outputs] + + [info.runfiles_from_proto_deps for info in pyproto_infos], + )), + ), + OutputGroupInfo( + default = depset(), + ), + PyInfo( + transitive_sources = default_outputs, + # Proto always produces 2- and 3- compatible source files + has_py2_only_sources = False, + has_py3_only_sources = False, + ), + ] + +py_proto_library = rule( + implementation = _py_proto_library_rule, + doc = """ + Use `py_proto_library` to generate Python libraries from `.proto` files. + + The convention is to name the `py_proto_library` rule `foo_py_pb2`, + when it is wrapping `proto_library` rule `foo_proto`. + + `deps` must point to a `proto_library` rule. + + Example: + +```starlark +py_library( + name = "lib", + deps = [":foo_py_pb2"], +) + +py_proto_library( + name = "foo_py_pb2", + deps = [":foo_proto"], +) + +proto_library( + name = "foo_proto", + srcs = ["foo.proto"], +) +```""", + attrs = { + "deps": attr.label_list( + doc = """ + The list of `proto_library` rules to generate Python libraries for. + + Usually this is just the one target: the proto library of interest. + It can be any target providing `ProtoInfo`.""", + providers = [ProtoInfo], + aspects = [_py_proto_aspect], + ), + }, + provides = [PyInfo], +) diff --git a/python/proto.bzl b/python/proto.bzl new file mode 100644 index 0000000000..3f455aee58 --- /dev/null +++ b/python/proto.bzl @@ -0,0 +1,21 @@ +# Copyright 2022 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Python proto library. +""" + +load("//python/private/proto:py_proto_library.bzl", _py_proto_library = "py_proto_library") + +py_proto_library = _py_proto_library From c988c0a16ea23697378863fdacd228e8944f28d1 Mon Sep 17 00:00:00 2001 From: Fabian Meumertzheim Date: Thu, 19 Jan 2023 00:38:16 +0100 Subject: [PATCH 111/234] runfiles: Fix usage instructions (#985) The canonical location for the runfiles library going forward will be the rules_python repo, so users should load from it. Since repository names are essentially dynamic with Bzlmod, they should not be used in import statements. --- python/runfiles/runfiles.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/runfiles/runfiles.py b/python/runfiles/runfiles.py index 01d4986d97..49a1e7b910 100644 --- a/python/runfiles/runfiles.py +++ b/python/runfiles/runfiles.py @@ -21,12 +21,12 @@ py_binary( name = "my_binary", ... - deps = ["@bazel_tools//tools/python/runfiles"], + deps = ["@rules_python//python/runfiles"], ) 2. Import the runfiles library. - from bazel_tools.tools.python.runfiles import runfiles + from python.runfiles import runfiles 3. Create a Runfiles object and use rlocation to look up runfile paths: From aab11ab0736c22585d4c2185c50916b1af48b975 Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Wed, 18 Jan 2023 19:06:00 -0800 Subject: [PATCH 112/234] chore: fix red CI - buildifier was broken by #832 (#996) --- MODULE.bazel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MODULE.bazel b/MODULE.bazel index f337db3cf0..389ced6972 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -8,7 +8,7 @@ bazel_dep(name = "platforms", version = "0.0.4") # Those are loaded only when using py_proto_library bazel_dep(name = "rules_proto", version = "5.3.0-21.7") -bazel_dep(name = "protobuf", repo_name = "com_google_protobuf", version = "21.7") +bazel_dep(name = "protobuf", version = "21.7", repo_name = "com_google_protobuf") internal_deps = use_extension("@rules_python//python:extensions.bzl", "internal_deps") internal_deps.install() From a475144054d328b540be46812604fb3806f36ee5 Mon Sep 17 00:00:00 2001 From: Fabian Meumertzheim Date: Thu, 19 Jan 2023 21:02:43 +0100 Subject: [PATCH 113/234] runfiles: Import `CurrentRepository` from Bazel (#988) Also adds an integration test to the BCR test module that replaces the tests maintained in Bazel itself. --- .bazelrc | 4 +- examples/bzlmod/.bazelignore | 1 + examples/bzlmod/MODULE.bazel | 6 ++ examples/bzlmod/other_module/MODULE.bazel | 5 ++ examples/bzlmod/other_module/WORKSPACE | 0 .../other_module/other_module/pkg/BUILD.bazel | 11 +++ .../other_module/pkg/data/data.txt | 1 + .../other_module/other_module/pkg/lib.py | 9 +++ examples/bzlmod/runfiles/BUILD.bazel | 18 +++++ examples/bzlmod/runfiles/data/data.txt | 1 + examples/bzlmod/runfiles/runfiles_test.py | 33 ++++++++ python/runfiles/runfiles.py | 76 ++++++++++++++++++- tests/runfiles/runfiles_test.py | 15 ++++ 13 files changed, 177 insertions(+), 3 deletions(-) create mode 100644 examples/bzlmod/.bazelignore create mode 100644 examples/bzlmod/other_module/MODULE.bazel create mode 100644 examples/bzlmod/other_module/WORKSPACE create mode 100644 examples/bzlmod/other_module/other_module/pkg/BUILD.bazel create mode 100644 examples/bzlmod/other_module/other_module/pkg/data/data.txt create mode 100644 examples/bzlmod/other_module/other_module/pkg/lib.py create mode 100644 examples/bzlmod/runfiles/BUILD.bazel create mode 100644 examples/bzlmod/runfiles/data/data.txt create mode 100644 examples/bzlmod/runfiles/runfiles_test.py diff --git a/.bazelrc b/.bazelrc index 2ad0284c3b..2dc32594d4 100644 --- a/.bazelrc +++ b/.bazelrc @@ -3,8 +3,8 @@ # This lets us glob() up all the files inside the examples to make them inputs to tests # (Note, we cannot use `common --deleted_packages` because the bazel version command doesn't support it) # To update these lines, run tools/bazel_integration_test/update_deleted_packages.sh -build --deleted_packages=examples/build_file_generation,examples/build_file_generation/get_url,examples/bzlmod,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps -query --deleted_packages=examples/build_file_generation,examples/build_file_generation/get_url,examples/bzlmod,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps +build --deleted_packages=examples/build_file_generation,examples/build_file_generation/get_url,examples/bzlmod,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/runfiles,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps +query --deleted_packages=examples/build_file_generation,examples/build_file_generation/get_url,examples/bzlmod,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/runfiles,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps test --test_output=errors diff --git a/examples/bzlmod/.bazelignore b/examples/bzlmod/.bazelignore new file mode 100644 index 0000000000..ab3eb1635c --- /dev/null +++ b/examples/bzlmod/.bazelignore @@ -0,0 +1 @@ +other_module diff --git a/examples/bzlmod/MODULE.bazel b/examples/bzlmod/MODULE.bazel index bbace8674f..89e5356c16 100644 --- a/examples/bzlmod/MODULE.bazel +++ b/examples/bzlmod/MODULE.bazel @@ -28,3 +28,9 @@ pip.parse( requirements_windows = "//:requirements_windows.txt", ) use_repo(pip, "pip") + +bazel_dep(name = "other_module", version = "") +local_path_override( + module_name = "other_module", + path = "other_module", +) diff --git a/examples/bzlmod/other_module/MODULE.bazel b/examples/bzlmod/other_module/MODULE.bazel new file mode 100644 index 0000000000..992e120760 --- /dev/null +++ b/examples/bzlmod/other_module/MODULE.bazel @@ -0,0 +1,5 @@ +module( + name = "other_module", +) + +bazel_dep(name = "rules_python", version = "") diff --git a/examples/bzlmod/other_module/WORKSPACE b/examples/bzlmod/other_module/WORKSPACE new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/bzlmod/other_module/other_module/pkg/BUILD.bazel b/examples/bzlmod/other_module/other_module/pkg/BUILD.bazel new file mode 100644 index 0000000000..9a130e3554 --- /dev/null +++ b/examples/bzlmod/other_module/other_module/pkg/BUILD.bazel @@ -0,0 +1,11 @@ +load("@rules_python//python:defs.bzl", "py_library") + +py_library( + name = "lib", + srcs = ["lib.py"], + data = ["data/data.txt"], + visibility = ["//visibility:public"], + deps = ["@rules_python//python/runfiles"], +) + +exports_files(["data/data.txt"]) diff --git a/examples/bzlmod/other_module/other_module/pkg/data/data.txt b/examples/bzlmod/other_module/other_module/pkg/data/data.txt new file mode 100644 index 0000000000..e975eaf640 --- /dev/null +++ b/examples/bzlmod/other_module/other_module/pkg/data/data.txt @@ -0,0 +1 @@ +Hello, other_module! diff --git a/examples/bzlmod/other_module/other_module/pkg/lib.py b/examples/bzlmod/other_module/other_module/pkg/lib.py new file mode 100644 index 0000000000..7ae76d7f85 --- /dev/null +++ b/examples/bzlmod/other_module/other_module/pkg/lib.py @@ -0,0 +1,9 @@ +from python.runfiles import runfiles + + +def GetRunfilePathWithCurrentRepository(): + r = runfiles.Create() + own_repo = r.CurrentRepository() + # For a non-main repository, the name of the runfiles directory is equal to + # the canonical repository name. + return r.Rlocation(own_repo + "/other_module/pkg/data/data.txt") diff --git a/examples/bzlmod/runfiles/BUILD.bazel b/examples/bzlmod/runfiles/BUILD.bazel new file mode 100644 index 0000000000..ad5fc1f0a6 --- /dev/null +++ b/examples/bzlmod/runfiles/BUILD.bazel @@ -0,0 +1,18 @@ +load("@rules_python//python:defs.bzl", "py_test") + +py_test( + name = "runfiles_test", + srcs = ["runfiles_test.py"], + data = [ + "data/data.txt", + "@other_module//other_module/pkg:data/data.txt", + ], + env = { + "DATA_RLOCATIONPATH": "$(rlocationpath data/data.txt)", + "OTHER_MODULE_DATA_RLOCATIONPATH": "$(rlocationpath @other_module//other_module/pkg:data/data.txt)", + }, + deps = [ + "@other_module//other_module/pkg:lib", + "@rules_python//python/runfiles", + ], +) diff --git a/examples/bzlmod/runfiles/data/data.txt b/examples/bzlmod/runfiles/data/data.txt new file mode 100644 index 0000000000..fb17e0df66 --- /dev/null +++ b/examples/bzlmod/runfiles/data/data.txt @@ -0,0 +1 @@ +Hello, example_bzlmod! diff --git a/examples/bzlmod/runfiles/runfiles_test.py b/examples/bzlmod/runfiles/runfiles_test.py new file mode 100644 index 0000000000..4f17c2a44c --- /dev/null +++ b/examples/bzlmod/runfiles/runfiles_test.py @@ -0,0 +1,33 @@ +import os +import unittest + +from other_module.pkg import lib + +from python.runfiles import runfiles + + +class RunfilesTest(unittest.TestCase): + # """Unit tests for `runfiles.Runfiles`.""" + def testCurrentRepository(self): + self.assertEqual(runfiles.Create().CurrentRepository(), "") + + def testRunfileWithRlocationpath(self): + data_rlocationpath = os.getenv("DATA_RLOCATIONPATH") + data_path = runfiles.Create().Rlocation(data_rlocationpath) + with open(data_path) as f: + self.assertEqual(f.read().strip(), "Hello, example_bzlmod!") + + def testRunfileInOtherModuleWithCurrentRepository(self): + data_path = lib.GetRunfilePathWithCurrentRepository() + with open(data_path) as f: + self.assertEqual(f.read().strip(), "Hello, other_module!") + + def testRunfileInOtherModuleWithRlocationpath(self): + data_rlocationpath = os.getenv("OTHER_MODULE_DATA_RLOCATIONPATH") + data_path = runfiles.Create().Rlocation(data_rlocationpath) + with open(data_path) as f: + self.assertEqual(f.read().strip(), "Hello, other_module!") + + +if __name__ == "__main__": + unittest.main() diff --git a/python/runfiles/runfiles.py b/python/runfiles/runfiles.py index 49a1e7b910..c55b33c227 100644 --- a/python/runfiles/runfiles.py +++ b/python/runfiles/runfiles.py @@ -58,9 +58,10 @@ env.update(r.EnvVars()) p = subprocess.Popen([r.Rlocation("path/to/binary")], env, ...) """ - +import inspect import os import posixpath +import sys if False: # Mypy needs these symbols imported, but since they only exist in python 3.5+, @@ -124,6 +125,7 @@ class _Runfiles(object): def __init__(self, strategy): # type: (Union[_ManifestBased, _DirectoryBased]) -> None self._strategy = strategy + self._python_runfiles_root = _FindPythonRunfilesRoot() def Rlocation(self, path): # type: (str) -> Optional[str] @@ -179,6 +181,78 @@ def EnvVars(self): """ return self._strategy.EnvVars() + def CurrentRepository(self, frame=1): + # type: (int) -> str + """Returns the canonical name of the caller's Bazel repository. + + For example, this function returns '' (the empty string) when called + from the main repository and a string of the form + 'rules_python~0.13.0` when called from code in the repository + corresponding to the rules_python Bazel module. + + More information about the difference between canonical repository + names and the `@repo` part of labels is available at: + https://bazel.build/build/bzlmod#repository-names + + NOTE: This function inspects the callstack to determine where in the + runfiles the caller is located to determine which repository it came + from. This may fail or produce incorrect results depending on who the + caller is, for example if it is not represented by a Python source + file. Use the `frame` argument to control the stack lookup. + + Args: + frame: int; the stack frame to return the repository name for. + Defaults to 1, the caller of the CurrentRepository function. + + Returns: + The canonical name of the Bazel repository containing the file + containing the frame-th caller of this function + + Raises: + ValueError: if the caller cannot be determined or the caller's file + path is not contained in the Python runfiles tree + """ + # pylint:disable=protected-access # for sys._getframe + # pylint:disable=raise-missing-from # we're still supporting Python 2 + try: + caller_path = inspect.getfile(sys._getframe(frame)) + except (TypeError, ValueError): + raise ValueError("failed to determine caller's file path") + caller_runfiles_path = os.path.relpath(caller_path, self._python_runfiles_root) + if caller_runfiles_path.startswith(".." + os.path.sep): + raise ValueError( + "{} does not lie under the runfiles root {}".format( + caller_path, self._python_runfiles_root + ) + ) + + caller_runfiles_directory = caller_runfiles_path[ + : caller_runfiles_path.find(os.path.sep) + ] + # With Bzlmod, the runfiles directory of the main repository is always + # named "_main". Without Bzlmod, the value returned by this function is + # never used, so we just assume Bzlmod is enabled. + if caller_runfiles_directory == "_main": + # The canonical name of the main repository (also known as the + # workspace) is the empty string. + return "" + # For all other repositories, the name of the runfiles directory is the + # canonical name. + return caller_runfiles_directory + + +def _FindPythonRunfilesRoot(): + # type: () -> str + """Finds the root of the Python runfiles tree.""" + root = __file__ + # Walk up our own runfiles path to the root of the runfiles tree from which + # the current file is being run. This path coincides with what the Bazel + # Python stub sets up as sys.path[0]. Since that entry can be changed at + # runtime, we rederive it here. + for _ in range("rules_python/python/runfiles/runfiles.py".count("/") + 1): + root = os.path.dirname(root) + return root + class _ManifestBased(object): """`Runfiles` strategy that parses a runfiles-manifest to look up runfiles.""" diff --git a/tests/runfiles/runfiles_test.py b/tests/runfiles/runfiles_test.py index 958ca01637..c234a7b547 100644 --- a/tests/runfiles/runfiles_test.py +++ b/tests/runfiles/runfiles_test.py @@ -345,6 +345,21 @@ def testPathsFromEnvvars(self): self.assertEqual(mf, "") self.assertEqual(dr, "") + def testCurrentRepository(self): + # This test assumes that it is running without --enable_bzlmod as the + # correct result with Bzlmod would be the empty string - the canonical + # name # of the main repository. Without Bzlmod, the main repository is + # treated just like any other repository and has the name of its + # runfiles directory returned, which coincides with the name specified + # in the WORKSPACE file. + # + # Specify a fake runfiles directory to verify that its value isn't used + # by the function. + self.assertEqual( + runfiles.Create({"RUNFILES_DIR": "whatever"}).CurrentRepository(), + "rules_python", + ) + @staticmethod def IsWindows(): return os.name == "nt" From 63379a4dfe93290f8c04b108220f400ebcf0f707 Mon Sep 17 00:00:00 2001 From: satoru Date: Fri, 20 Jan 2023 09:43:59 +0800 Subject: [PATCH 114/234] Fix misleading error message (#927) When `rctx.which` can not find a program for the specified name, it returns `None`. We should not override the original `python_interpreter` in this case, otherwise we'll see a misleading error message like `Error in fail: python interpreter `None` not found in PATH` --- python/pip_install/pip_repository.bzl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl index f5a2da2b0a..782a947fc4 100644 --- a/python/pip_install/pip_repository.bzl +++ b/python/pip_install/pip_repository.bzl @@ -60,11 +60,11 @@ def _resolve_python_interpreter(rctx): if rctx.attr.python_interpreter_target != None: target = rctx.attr.python_interpreter_target python_interpreter = rctx.path(target) - else: - if "/" not in python_interpreter: - python_interpreter = rctx.which(python_interpreter) - if not python_interpreter: + elif "/" not in python_interpreter: + found_python_interpreter = rctx.which(python_interpreter) + if not found_python_interpreter: fail("python interpreter `{}` not found in PATH".format(python_interpreter)) + python_interpreter = found_python_interpreter return python_interpreter def _get_xcode_location_cflags(rctx): From 96621391e7e8861eb448fb94b49aa1fcb9f45ba7 Mon Sep 17 00:00:00 2001 From: Fabian Meumertzheim Date: Fri, 20 Jan 2023 15:24:04 +0100 Subject: [PATCH 115/234] runfiles: Apply repo mapping to Rlocation path (#998) --- examples/bzlmod/MODULE.bazel | 2 +- .../other_module/other_module/pkg/lib.py | 4 + examples/bzlmod/runfiles/BUILD.bazel | 6 +- examples/bzlmod/runfiles/runfiles_test.py | 17 ++ python/runfiles/runfiles.py | 65 +++- tests/runfiles/runfiles_test.py | 288 ++++++++++++++++++ 6 files changed, 375 insertions(+), 7 deletions(-) diff --git a/examples/bzlmod/MODULE.bazel b/examples/bzlmod/MODULE.bazel index 89e5356c16..48fb4cb3fc 100644 --- a/examples/bzlmod/MODULE.bazel +++ b/examples/bzlmod/MODULE.bazel @@ -29,7 +29,7 @@ pip.parse( ) use_repo(pip, "pip") -bazel_dep(name = "other_module", version = "") +bazel_dep(name = "other_module", version = "", repo_name = "our_other_module") local_path_override( module_name = "other_module", path = "other_module", diff --git a/examples/bzlmod/other_module/other_module/pkg/lib.py b/examples/bzlmod/other_module/other_module/pkg/lib.py index 7ae76d7f85..48f6b58b36 100644 --- a/examples/bzlmod/other_module/other_module/pkg/lib.py +++ b/examples/bzlmod/other_module/other_module/pkg/lib.py @@ -7,3 +7,7 @@ def GetRunfilePathWithCurrentRepository(): # For a non-main repository, the name of the runfiles directory is equal to # the canonical repository name. return r.Rlocation(own_repo + "/other_module/pkg/data/data.txt") + + +def GetRunfilePathWithRepoMapping(): + return runfiles.Create().Rlocation("other_module/other_module/pkg/data/data.txt") diff --git a/examples/bzlmod/runfiles/BUILD.bazel b/examples/bzlmod/runfiles/BUILD.bazel index ad5fc1f0a6..add56b3bd0 100644 --- a/examples/bzlmod/runfiles/BUILD.bazel +++ b/examples/bzlmod/runfiles/BUILD.bazel @@ -5,14 +5,14 @@ py_test( srcs = ["runfiles_test.py"], data = [ "data/data.txt", - "@other_module//other_module/pkg:data/data.txt", + "@our_other_module//other_module/pkg:data/data.txt", ], env = { "DATA_RLOCATIONPATH": "$(rlocationpath data/data.txt)", - "OTHER_MODULE_DATA_RLOCATIONPATH": "$(rlocationpath @other_module//other_module/pkg:data/data.txt)", + "OTHER_MODULE_DATA_RLOCATIONPATH": "$(rlocationpath @our_other_module//other_module/pkg:data/data.txt)", }, deps = [ - "@other_module//other_module/pkg:lib", + "@our_other_module//other_module/pkg:lib", "@rules_python//python/runfiles", ], ) diff --git a/examples/bzlmod/runfiles/runfiles_test.py b/examples/bzlmod/runfiles/runfiles_test.py index 4f17c2a44c..3c3ae75a2c 100644 --- a/examples/bzlmod/runfiles/runfiles_test.py +++ b/examples/bzlmod/runfiles/runfiles_test.py @@ -11,12 +11,29 @@ class RunfilesTest(unittest.TestCase): def testCurrentRepository(self): self.assertEqual(runfiles.Create().CurrentRepository(), "") + def testRunfilesWithRepoMapping(self): + data_path = runfiles.Create().Rlocation("example_bzlmod/runfiles/data/data.txt") + with open(data_path) as f: + self.assertEqual(f.read().strip(), "Hello, example_bzlmod!") + def testRunfileWithRlocationpath(self): data_rlocationpath = os.getenv("DATA_RLOCATIONPATH") data_path = runfiles.Create().Rlocation(data_rlocationpath) with open(data_path) as f: self.assertEqual(f.read().strip(), "Hello, example_bzlmod!") + def testRunfileInOtherModuleWithOurRepoMapping(self): + data_path = runfiles.Create().Rlocation( + "our_other_module/other_module/pkg/data/data.txt" + ) + with open(data_path) as f: + self.assertEqual(f.read().strip(), "Hello, other_module!") + + def testRunfileInOtherModuleWithItsRepoMapping(self): + data_path = lib.GetRunfilePathWithRepoMapping() + with open(data_path) as f: + self.assertEqual(f.read().strip(), "Hello, other_module!") + def testRunfileInOtherModuleWithCurrentRepository(self): data_path = lib.GetRunfilePathWithCurrentRepository() with open(data_path) as f: diff --git a/python/runfiles/runfiles.py b/python/runfiles/runfiles.py index c55b33c227..c310f06b96 100644 --- a/python/runfiles/runfiles.py +++ b/python/runfiles/runfiles.py @@ -126,9 +126,12 @@ def __init__(self, strategy): # type: (Union[_ManifestBased, _DirectoryBased]) -> None self._strategy = strategy self._python_runfiles_root = _FindPythonRunfilesRoot() + self._repo_mapping = _ParseRepoMapping( + strategy.RlocationChecked("_repo_mapping") + ) - def Rlocation(self, path): - # type: (str) -> Optional[str] + def Rlocation(self, path, source_repo=None): + # type: (str, Optional[str]) -> Optional[str] """Returns the runtime path of a runfile. Runfiles are data-dependencies of Bazel-built binaries and tests. @@ -141,6 +144,13 @@ def Rlocation(self, path): Args: path: string; runfiles-root-relative path of the runfile + source_repo: string; optional; the canonical name of the repository + whose repository mapping should be used to resolve apparent to + canonical repository names in `path`. If `None` (default), the + repository mapping of the repository containing the caller of this + method is used. Explicitly setting this parameter should only be + necessary for libraries that want to wrap the runfiles library. Use + `CurrentRepository` to obtain canonical repository names. Returns: the path to the runfile, which the caller should check for existence, or None if the method doesn't know about this runfile @@ -165,7 +175,31 @@ def Rlocation(self, path): raise ValueError('path is absolute without a drive letter: "%s"' % path) if os.path.isabs(path): return path - return self._strategy.RlocationChecked(path) + + if source_repo is None and self._repo_mapping: + # Look up runfiles using the repository mapping of the caller of the + # current method. If the repo mapping is empty, determining this + # name is not necessary. + source_repo = self.CurrentRepository(frame=2) + + # Split off the first path component, which contains the repository + # name (apparent or canonical). + target_repo, _, remainder = path.partition("/") + if not remainder or (source_repo, target_repo) not in self._repo_mapping: + # One of the following is the case: + # - not using Bzlmod, so the repository mapping is empty and + # apparent and canonical repository names are the same + # - target_repo is already a canonical repository name and does not + # have to be mapped. + # - path did not contain a slash and referred to a root symlink, + # which also should not be mapped. + return self._strategy.RlocationChecked(path) + + # target_repo is an apparent repository name. Look up the corresponding + # canonical repository name with respect to the current repository, + # identified by its canonical name. + target_canonical = self._repo_mapping[(source_repo, target_repo)] + return self._strategy.RlocationChecked(target_canonical + "/" + remainder) def EnvVars(self): # type: () -> Dict[str, str] @@ -254,6 +288,31 @@ def _FindPythonRunfilesRoot(): return root +def _ParseRepoMapping(repo_mapping_path): + # type: (Optional[str]) -> Dict[Tuple[str, str], str] + """Parses the repository mapping manifest.""" + # If the repository mapping file can't be found, that is not an error: We + # might be running without Bzlmod enabled or there may not be any runfiles. + # In this case, just apply an empty repo mapping. + if not repo_mapping_path: + return {} + try: + with open(repo_mapping_path, "r") as f: + content = f.read() + except FileNotFoundError: + return {} + + repo_mapping = {} + for line in content.split("\n"): + if not line: + # Empty line following the last line break + break + current_canonical, target_local, target_canonical = line.split(",") + repo_mapping[(current_canonical, target_local)] = target_canonical + + return repo_mapping + + class _ManifestBased(object): """`Runfiles` strategy that parses a runfiles-manifest to look up runfiles.""" diff --git a/tests/runfiles/runfiles_test.py b/tests/runfiles/runfiles_test.py index c234a7b547..966d012c77 100644 --- a/tests/runfiles/runfiles_test.py +++ b/tests/runfiles/runfiles_test.py @@ -205,6 +205,159 @@ def testManifestBasedRlocation(self): else: self.assertEqual(r.Rlocation("/foo"), "/foo") + def testManifestBasedRlocationWithRepoMappingFromMain(self): + with _MockFile( + contents=[ + ",my_module,_main", + ",my_protobuf,protobuf~3.19.2", + ",my_workspace,_main", + "protobuf~3.19.2,protobuf,protobuf~3.19.2", + ] + ) as rm, _MockFile( + contents=[ + "_repo_mapping " + rm.Path(), + "config.json /etc/config.json", + "protobuf~3.19.2/foo/runfile C:/Actual Path\\protobuf\\runfile", + "_main/bar/runfile /the/path/./to/other//other runfile.txt", + "protobuf~3.19.2/bar/dir E:\\Actual Path\\Directory", + ], + ) as mf: + r = runfiles.CreateManifestBased(mf.Path()) + + self.assertEqual( + r.Rlocation("my_module/bar/runfile", ""), + "/the/path/./to/other//other runfile.txt", + ) + self.assertEqual( + r.Rlocation("my_workspace/bar/runfile", ""), + "/the/path/./to/other//other runfile.txt", + ) + self.assertEqual( + r.Rlocation("my_protobuf/foo/runfile", ""), + "C:/Actual Path\\protobuf\\runfile", + ) + self.assertEqual( + r.Rlocation("my_protobuf/bar/dir", ""), "E:\\Actual Path\\Directory" + ) + self.assertEqual( + r.Rlocation("my_protobuf/bar/dir/file", ""), + "E:\\Actual Path\\Directory/file", + ) + self.assertEqual( + r.Rlocation("my_protobuf/bar/dir/de eply/nes ted/fi~le", ""), + "E:\\Actual Path\\Directory/de eply/nes ted/fi~le", + ) + + self.assertIsNone(r.Rlocation("protobuf/foo/runfile")) + self.assertIsNone(r.Rlocation("protobuf/bar/dir")) + self.assertIsNone(r.Rlocation("protobuf/bar/dir/file")) + self.assertIsNone(r.Rlocation("protobuf/bar/dir/dir/de eply/nes ted/fi~le")) + + self.assertEqual( + r.Rlocation("_main/bar/runfile", ""), + "/the/path/./to/other//other runfile.txt", + ) + self.assertEqual( + r.Rlocation("protobuf~3.19.2/foo/runfile", ""), + "C:/Actual Path\\protobuf\\runfile", + ) + self.assertEqual( + r.Rlocation("protobuf~3.19.2/bar/dir", ""), "E:\\Actual Path\\Directory" + ) + self.assertEqual( + r.Rlocation("protobuf~3.19.2/bar/dir/file", ""), + "E:\\Actual Path\\Directory/file", + ) + self.assertEqual( + r.Rlocation("protobuf~3.19.2/bar/dir/de eply/nes ted/fi~le", ""), + "E:\\Actual Path\\Directory/de eply/nes ted/fi~le", + ) + + self.assertEqual(r.Rlocation("config.json", ""), "/etc/config.json") + self.assertIsNone(r.Rlocation("_main", "")) + self.assertIsNone(r.Rlocation("my_module", "")) + self.assertIsNone(r.Rlocation("protobuf", "")) + + def testManifestBasedRlocationWithRepoMappingFromOtherRepo(self): + with _MockFile( + contents=[ + ",my_module,_main", + ",my_protobuf,protobuf~3.19.2", + ",my_workspace,_main", + "protobuf~3.19.2,protobuf,protobuf~3.19.2", + ] + ) as rm, _MockFile( + contents=[ + "_repo_mapping " + rm.Path(), + "config.json /etc/config.json", + "protobuf~3.19.2/foo/runfile C:/Actual Path\\protobuf\\runfile", + "_main/bar/runfile /the/path/./to/other//other runfile.txt", + "protobuf~3.19.2/bar/dir E:\\Actual Path\\Directory", + ], + ) as mf: + r = runfiles.CreateManifestBased(mf.Path()) + + self.assertEqual( + r.Rlocation("protobuf/foo/runfile", "protobuf~3.19.2"), + "C:/Actual Path\\protobuf\\runfile", + ) + self.assertEqual( + r.Rlocation("protobuf/bar/dir", "protobuf~3.19.2"), + "E:\\Actual Path\\Directory", + ) + self.assertEqual( + r.Rlocation("protobuf/bar/dir/file", "protobuf~3.19.2"), + "E:\\Actual Path\\Directory/file", + ) + self.assertEqual( + r.Rlocation( + "protobuf/bar/dir/de eply/nes ted/fi~le", "protobuf~3.19.2" + ), + "E:\\Actual Path\\Directory/de eply/nes ted/fi~le", + ) + + self.assertIsNone(r.Rlocation("my_module/bar/runfile", "protobuf~3.19.2")) + self.assertIsNone(r.Rlocation("my_protobuf/foo/runfile", "protobuf~3.19.2")) + self.assertIsNone(r.Rlocation("my_protobuf/bar/dir", "protobuf~3.19.2")) + self.assertIsNone( + r.Rlocation("my_protobuf/bar/dir/file", "protobuf~3.19.2") + ) + self.assertIsNone( + r.Rlocation( + "my_protobuf/bar/dir/de eply/nes ted/fi~le", "protobuf~3.19.2" + ) + ) + + self.assertEqual( + r.Rlocation("_main/bar/runfile", "protobuf~3.19.2"), + "/the/path/./to/other//other runfile.txt", + ) + self.assertEqual( + r.Rlocation("protobuf~3.19.2/foo/runfile", "protobuf~3.19.2"), + "C:/Actual Path\\protobuf\\runfile", + ) + self.assertEqual( + r.Rlocation("protobuf~3.19.2/bar/dir", "protobuf~3.19.2"), + "E:\\Actual Path\\Directory", + ) + self.assertEqual( + r.Rlocation("protobuf~3.19.2/bar/dir/file", "protobuf~3.19.2"), + "E:\\Actual Path\\Directory/file", + ) + self.assertEqual( + r.Rlocation( + "protobuf~3.19.2/bar/dir/de eply/nes ted/fi~le", "protobuf~3.19.2" + ), + "E:\\Actual Path\\Directory/de eply/nes ted/fi~le", + ) + + self.assertEqual( + r.Rlocation("config.json", "protobuf~3.19.2"), "/etc/config.json" + ) + self.assertIsNone(r.Rlocation("_main", "protobuf~3.19.2")) + self.assertIsNone(r.Rlocation("my_module", "protobuf~3.19.2")) + self.assertIsNone(r.Rlocation("protobuf", "protobuf~3.19.2")) + def testDirectoryBasedRlocation(self): # The _DirectoryBased strategy simply joins the runfiles directory and the # runfile's path on a "/". This strategy does not perform any normalization, @@ -217,6 +370,141 @@ def testDirectoryBasedRlocation(self): else: self.assertEqual(r.Rlocation("/foo"), "/foo") + def testDirectoryBasedRlocationWithRepoMappingFromMain(self): + with _MockFile( + name="_repo_mapping", + contents=[ + ",my_module,_main", + ",my_protobuf,protobuf~3.19.2", + ",my_workspace,_main", + "protobuf~3.19.2,protobuf,protobuf~3.19.2", + ], + ) as rm: + dir = os.path.dirname(rm.Path()) + r = runfiles.CreateDirectoryBased(dir) + + self.assertEqual( + r.Rlocation("my_module/bar/runfile", ""), dir + "/_main/bar/runfile" + ) + self.assertEqual( + r.Rlocation("my_workspace/bar/runfile", ""), dir + "/_main/bar/runfile" + ) + self.assertEqual( + r.Rlocation("my_protobuf/foo/runfile", ""), + dir + "/protobuf~3.19.2/foo/runfile", + ) + self.assertEqual( + r.Rlocation("my_protobuf/bar/dir", ""), dir + "/protobuf~3.19.2/bar/dir" + ) + self.assertEqual( + r.Rlocation("my_protobuf/bar/dir/file", ""), + dir + "/protobuf~3.19.2/bar/dir/file", + ) + self.assertEqual( + r.Rlocation("my_protobuf/bar/dir/de eply/nes ted/fi~le", ""), + dir + "/protobuf~3.19.2/bar/dir/de eply/nes ted/fi~le", + ) + + self.assertEqual( + r.Rlocation("protobuf/foo/runfile", ""), dir + "/protobuf/foo/runfile" + ) + self.assertEqual( + r.Rlocation("protobuf/bar/dir/dir/de eply/nes ted/fi~le", ""), + dir + "/protobuf/bar/dir/dir/de eply/nes ted/fi~le", + ) + + self.assertEqual( + r.Rlocation("_main/bar/runfile", ""), dir + "/_main/bar/runfile" + ) + self.assertEqual( + r.Rlocation("protobuf~3.19.2/foo/runfile", ""), + dir + "/protobuf~3.19.2/foo/runfile", + ) + self.assertEqual( + r.Rlocation("protobuf~3.19.2/bar/dir", ""), + dir + "/protobuf~3.19.2/bar/dir", + ) + self.assertEqual( + r.Rlocation("protobuf~3.19.2/bar/dir/file", ""), + dir + "/protobuf~3.19.2/bar/dir/file", + ) + self.assertEqual( + r.Rlocation("protobuf~3.19.2/bar/dir/de eply/nes ted/fi~le", ""), + dir + "/protobuf~3.19.2/bar/dir/de eply/nes ted/fi~le", + ) + + self.assertEqual(r.Rlocation("config.json", ""), dir + "/config.json") + + def testDirectoryBasedRlocationWithRepoMappingFromOtherRepo(self): + with _MockFile( + name="_repo_mapping", + contents=[ + ",my_module,_main", + ",my_protobuf,protobuf~3.19.2", + ",my_workspace,_main", + "protobuf~3.19.2,protobuf,protobuf~3.19.2", + ], + ) as rm: + dir = os.path.dirname(rm.Path()) + r = runfiles.CreateDirectoryBased(dir) + + self.assertEqual( + r.Rlocation("protobuf/foo/runfile", "protobuf~3.19.2"), + dir + "/protobuf~3.19.2/foo/runfile", + ) + self.assertEqual( + r.Rlocation("protobuf/bar/dir", "protobuf~3.19.2"), + dir + "/protobuf~3.19.2/bar/dir", + ) + self.assertEqual( + r.Rlocation("protobuf/bar/dir/file", "protobuf~3.19.2"), + dir + "/protobuf~3.19.2/bar/dir/file", + ) + self.assertEqual( + r.Rlocation( + "protobuf/bar/dir/de eply/nes ted/fi~le", "protobuf~3.19.2" + ), + dir + "/protobuf~3.19.2/bar/dir/de eply/nes ted/fi~le", + ) + + self.assertEqual( + r.Rlocation("my_module/bar/runfile", "protobuf~3.19.2"), + dir + "/my_module/bar/runfile", + ) + self.assertEqual( + r.Rlocation( + "my_protobuf/bar/dir/de eply/nes ted/fi~le", "protobuf~3.19.2" + ), + dir + "/my_protobuf/bar/dir/de eply/nes ted/fi~le", + ) + + self.assertEqual( + r.Rlocation("_main/bar/runfile", "protobuf~3.19.2"), + dir + "/_main/bar/runfile", + ) + self.assertEqual( + r.Rlocation("protobuf~3.19.2/foo/runfile", "protobuf~3.19.2"), + dir + "/protobuf~3.19.2/foo/runfile", + ) + self.assertEqual( + r.Rlocation("protobuf~3.19.2/bar/dir", "protobuf~3.19.2"), + dir + "/protobuf~3.19.2/bar/dir", + ) + self.assertEqual( + r.Rlocation("protobuf~3.19.2/bar/dir/file", "protobuf~3.19.2"), + dir + "/protobuf~3.19.2/bar/dir/file", + ) + self.assertEqual( + r.Rlocation( + "protobuf~3.19.2/bar/dir/de eply/nes ted/fi~le", "protobuf~3.19.2" + ), + dir + "/protobuf~3.19.2/bar/dir/de eply/nes ted/fi~le", + ) + + self.assertEqual( + r.Rlocation("config.json", "protobuf~3.19.2"), dir + "/config.json" + ) + def testPathsFromEnvvars(self): # Both envvars have a valid value. mf, dr = runfiles._PathsFrom( From bd3a7197a295ddcb37414e5723da6c2f41b806ee Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Fri, 20 Jan 2023 17:48:49 -0800 Subject: [PATCH 116/234] fix(deps): declare our dependency on bazel_skylib (#1001) --- .github/workflows/workspace_snippet.sh | 5 +++++ MODULE.bazel | 1 + examples/multi_python_versions/WORKSPACE | 15 +++----------- examples/pip_install/WORKSPACE | 15 +++----------- examples/pip_parse/WORKSPACE | 15 +++----------- examples/pip_parse_vendored/WORKSPACE | 13 ++---------- examples/pip_repository_annotations/WORKSPACE | 13 ++---------- python/repositories.bzl | 20 +++++++++++++++++-- tests/pip_repository_entry_points/WORKSPACE | 15 +++----------- 9 files changed, 40 insertions(+), 72 deletions(-) diff --git a/.github/workflows/workspace_snippet.sh b/.github/workflows/workspace_snippet.sh index 9a51d06e3d..4837f731e7 100755 --- a/.github/workflows/workspace_snippet.sh +++ b/.github/workflows/workspace_snippet.sh @@ -46,11 +46,16 @@ Paste this snippet into your \`WORKSPACE\` file: \`\`\`starlark load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + http_archive( name = "rules_python", sha256 = "${SHA}", strip_prefix = "${PREFIX}", url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/${TAG}.tar.gz", ) + +load("@rules_python//python:repositories.bzl", "py_repositories") + +py_repositories() \`\`\` EOF diff --git a/MODULE.bazel b/MODULE.bazel index 389ced6972..af5d2e079f 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -5,6 +5,7 @@ module( ) bazel_dep(name = "platforms", version = "0.0.4") +bazel_dep(name = "bazel_skylib", version = "1.3.0") # Those are loaded only when using py_proto_library bazel_dep(name = "rules_proto", version = "5.3.0-21.7") diff --git a/examples/multi_python_versions/WORKSPACE b/examples/multi_python_versions/WORKSPACE index 9a6676ea25..698bce87ed 100644 --- a/examples/multi_python_versions/WORKSPACE +++ b/examples/multi_python_versions/WORKSPACE @@ -1,16 +1,5 @@ workspace(name = "rules_python_multi_python_versions") -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -http_archive( - name = "bazel_skylib", - sha256 = "c6966ec828da198c5d9adbaa94c05e3a1c7f21bd012a0b29ba8ddbccb2c93b0d", - urls = [ - "https://github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", - "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", - ], -) - local_repository( name = "rules_python", path = "../..", @@ -20,7 +9,9 @@ load("@rules_python//python/pip_install:repositories.bzl", "pip_install_dependen pip_install_dependencies() -load("@rules_python//python:repositories.bzl", "python_register_multi_toolchains") +load("@rules_python//python:repositories.bzl", "py_repositories", "python_register_multi_toolchains") + +py_repositories() default_python_version = "3.9" diff --git a/examples/pip_install/WORKSPACE b/examples/pip_install/WORKSPACE index f63d928013..b1744bfa7d 100644 --- a/examples/pip_install/WORKSPACE +++ b/examples/pip_install/WORKSPACE @@ -1,22 +1,13 @@ workspace(name = "rules_python_pip_install_example") -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -http_archive( - name = "bazel_skylib", - sha256 = "c6966ec828da198c5d9adbaa94c05e3a1c7f21bd012a0b29ba8ddbccb2c93b0d", - urls = [ - "https://github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", - "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", - ], -) - local_repository( name = "rules_python", path = "../..", ) -load("@rules_python//python:repositories.bzl", "python_register_toolchains") +load("@rules_python//python:repositories.bzl", "py_repositories", "python_register_toolchains") + +py_repositories() python_register_toolchains( name = "python39", diff --git a/examples/pip_parse/WORKSPACE b/examples/pip_parse/WORKSPACE index cd557a35db..79aca14b8c 100644 --- a/examples/pip_parse/WORKSPACE +++ b/examples/pip_parse/WORKSPACE @@ -1,22 +1,13 @@ workspace(name = "rules_python_pip_parse_example") -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -http_archive( - name = "bazel_skylib", - sha256 = "c6966ec828da198c5d9adbaa94c05e3a1c7f21bd012a0b29ba8ddbccb2c93b0d", - urls = [ - "https://github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", - "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", - ], -) - local_repository( name = "rules_python", path = "../..", ) -load("@rules_python//python:repositories.bzl", "python_register_toolchains") +load("@rules_python//python:repositories.bzl", "py_repositories", "python_register_toolchains") + +py_repositories() python_register_toolchains( name = "python39", diff --git a/examples/pip_parse_vendored/WORKSPACE b/examples/pip_parse_vendored/WORKSPACE index 2f0bfb183a..157f70aeb6 100644 --- a/examples/pip_parse_vendored/WORKSPACE +++ b/examples/pip_parse_vendored/WORKSPACE @@ -1,22 +1,13 @@ workspace(name = "pip_repository_annotations_example") -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - local_repository( name = "rules_python", path = "../..", ) -http_archive( - name = "bazel_skylib", - sha256 = "c6966ec828da198c5d9adbaa94c05e3a1c7f21bd012a0b29ba8ddbccb2c93b0d", - urls = [ - "https://github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", - "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", - ], -) +load("@rules_python//python:repositories.bzl", "py_repositories", "python_register_toolchains") -load("@rules_python//python:repositories.bzl", "python_register_toolchains") +py_repositories() python_register_toolchains( name = "python39", diff --git a/examples/pip_repository_annotations/WORKSPACE b/examples/pip_repository_annotations/WORKSPACE index 8fd998b7ae..3deea0329c 100644 --- a/examples/pip_repository_annotations/WORKSPACE +++ b/examples/pip_repository_annotations/WORKSPACE @@ -1,22 +1,13 @@ workspace(name = "pip_repository_annotations_example") -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - local_repository( name = "rules_python", path = "../..", ) -http_archive( - name = "bazel_skylib", - sha256 = "c6966ec828da198c5d9adbaa94c05e3a1c7f21bd012a0b29ba8ddbccb2c93b0d", - urls = [ - "https://github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", - "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", - ], -) +load("@rules_python//python:repositories.bzl", "py_repositories", "python_register_toolchains") -load("@rules_python//python:repositories.bzl", "python_register_toolchains") +py_repositories() python_register_toolchains( name = "python39", diff --git a/python/repositories.bzl b/python/repositories.bzl index e0c9b0626d..ba8e433995 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -17,6 +17,8 @@ For historic reasons, pip_repositories() is defined in //python:pip.bzl. """ +load("@bazel_tools//tools/build_defs/repo:http.bzl", _http_archive = "http_archive") +load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") load( "//python/private:toolchains_repo.bzl", "multi_toolchain_aliases", @@ -32,9 +34,23 @@ load( "get_release_url", ) +def http_archive(**kwargs): + maybe(_http_archive, **kwargs) + def py_repositories(): - # buildifier: disable=print - print("py_repositories is a no-op and is deprecated. You can remove this from your WORKSPACE file") + """Runtime dependencies that users must install. + + This function should be loaded and called in the user's WORKSPACE. + With bzlmod enabled, this function is not needed since MODULE.bazel handles transitive deps. + """ + http_archive( + name = "bazel_skylib", + sha256 = "74d544d96f4a5bb630d465ca8bbcfe231e3594e5aae57e1edbf17a6eb3ca2506", + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz", + "https://github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz", + ], + ) ######## # Remaining content of the file is only used to support toolchains. diff --git a/tests/pip_repository_entry_points/WORKSPACE b/tests/pip_repository_entry_points/WORKSPACE index e2915b9d93..1afd68c215 100644 --- a/tests/pip_repository_entry_points/WORKSPACE +++ b/tests/pip_repository_entry_points/WORKSPACE @@ -1,22 +1,13 @@ workspace(name = "pip_repository_annotations_example") -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -http_archive( - name = "bazel_skylib", - sha256 = "c6966ec828da198c5d9adbaa94c05e3a1c7f21bd012a0b29ba8ddbccb2c93b0d", - urls = [ - "https://github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", - "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", - ], -) - local_repository( name = "rules_python", path = "../..", ) -load("@rules_python//python:repositories.bzl", "python_register_toolchains") +load("@rules_python//python:repositories.bzl", "py_repositories", "python_register_toolchains") + +py_repositories() # This toolchain is explicitly 3.10 while `rules_python` is 3.9 to act as # a regression test, ensuring 3.10 is functional From 1722988cc407b08a4e7770295452076706823f9d Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Sat, 21 Jan 2023 11:16:41 -0800 Subject: [PATCH 117/234] chore: publish a runfiles library as a wheel (#995) * chore: publish a runfiles library as a wheel Wire it up to GH actions so it is published for each release. Tested locally with: bazel build python/runfiles:wheel --embed_label=1.0.2 --stamp PYTHONPATH=bazel-bin/python/runfiles/bazel_runfiles-_BUILD_EMBED_LABEL_-py3-none-any.whl python >>> import runfiles >>> runfiles.Create() Note, I would have liked to call the package bazel-runfiles, but this isn't possible without either refactoring the paths in this repo, or doing some fancy starlark to copy files around to create a folder that we turn into the wheel. There is no project https://pypi.org/project/runfiles though there is a https://pypi.org/project/runfile We could try harder to get the name we prefer. * Apply suggestions from code review Co-authored-by: Richard Levasseur * more code review cleanup Co-authored-by: Richard Levasseur --- .github/workflows/release.yml | 12 ++++- python/runfiles/BUILD.bazel | 25 ++++++++- python/runfiles/README.md | 52 +++++++++++++++++++ python/runfiles/__init__.py | 1 + python/runfiles/runfiles.py | 44 +--------------- .../runfiles_wheel_integration_test.sh | 10 ++++ 6 files changed, 99 insertions(+), 45 deletions(-) create mode 100644 python/runfiles/README.md create mode 100644 python/runfiles/__init__.py create mode 100755 tests/runfiles/runfiles_wheel_integration_test.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a675fe1562..5906289e66 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,7 +13,17 @@ jobs: - name: Checkout uses: actions/checkout@v2 - name: Prepare workspace snippet - run: .github/workflows/workspace_snippet.sh ${{ env.GITHUB_REF_NAME }} > release_notes.txt + run: .github/workflows/workspace_snippet.sh > release_notes.txt + - name: Build wheel dist + run: bazel build --stamp --embed_label=${{ env.GITHUB_REF_NAME }} //python/runfiles:wheel + - name: Publish runfiles package to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + # Note, the PYPI_API_TOKEN was added on + # https://github.com/bazelbuild/rules_python/settings/secrets/actions + # and currently uses a token which authenticates as https://pypi.org/user/alexeagle/ + password: ${{ secrets.PYPI_API_TOKEN }} + packages_dir: bazel-bin/python/runfiles - name: Release uses: softprops/action-gh-release@v1 with: diff --git a/python/runfiles/BUILD.bazel b/python/runfiles/BUILD.bazel index 2089c418d8..ea171ccd8e 100644 --- a/python/runfiles/BUILD.bazel +++ b/python/runfiles/BUILD.bazel @@ -13,6 +13,7 @@ # limitations under the License. load("//python:defs.bzl", "py_library") +load("//python:packaging.bzl", "py_wheel") filegroup( name = "distribution", @@ -22,6 +23,28 @@ filegroup( py_library( name = "runfiles", - srcs = ["runfiles.py"], + srcs = [ + "__init__.py", + "runfiles.py", + ], visibility = ["//visibility:public"], ) + +# This can be manually tested by running tests/runfiles/runfiles_wheel_integration_test.sh +# We ought to have an automated integration test for it, too. +# see https://github.com/bazelbuild/rules_python/issues/1002 +py_wheel( + name = "wheel", + # From https://pypi.org/classifiers/ + classifiers = [ + "Development Status :: 5 - Production/Stable", + "License :: OSI Approved :: Apache Software License", + ], + description_file = "README.md", + distribution = "bazel_runfiles", + homepage = "https://github.com/bazelbuild/rules_python", + strip_path_prefixes = ["python"], + version = "{BUILD_EMBED_LABEL}", + visibility = ["//visibility:public"], + deps = [":runfiles"], +) diff --git a/python/runfiles/README.md b/python/runfiles/README.md new file mode 100644 index 0000000000..79ba82c1de --- /dev/null +++ b/python/runfiles/README.md @@ -0,0 +1,52 @@ +# bazel-runfiles library + +This is a Bazel Runfiles lookup library for Bazel-built Python binaries and tests. + +Typical Usage +------------- + +1. Add the 'runfiles' dependency along with other third-party dependencies, for example in your + `requirements.txt` file. + +2. Depend on this runfiles library from your build rule, like you would other third-party libraries. + + py_binary( + name = "my_binary", + ... + deps = [requirement("runfiles")], + ) + +3. Import the runfiles library. + + import runfiles # not "from runfiles import runfiles" + +4. Create a Runfiles object and use rlocation to look up runfile paths: + + r = runfiles.Create() + ... + with open(r.Rlocation("my_workspace/path/to/my/data.txt"), "r") as f: + contents = f.readlines() + ... + + The code above creates a manifest- or directory-based implementations based + on the environment variables in os.environ. See `Create()` for more info. + + If you want to explicitly create a manifest- or directory-based + implementations, you can do so as follows: + + r1 = runfiles.CreateManifestBased("path/to/foo.runfiles_manifest") + + r2 = runfiles.CreateDirectoryBased("path/to/foo.runfiles/") + + If you wnat to start subprocesses, and the subprocess can't automatically + find the correct runfiles directory, you can explicitly set the right + environment variables for them: + + import subprocess + import runfiles + + r = runfiles.Create() + env = {} + ... + env.update(r.EnvVars()) + p = subprocess.Popen([r.Rlocation("path/to/binary")], env, ...) \ No newline at end of file diff --git a/python/runfiles/__init__.py b/python/runfiles/__init__.py new file mode 100644 index 0000000000..eb42f79c8d --- /dev/null +++ b/python/runfiles/__init__.py @@ -0,0 +1 @@ +from .runfiles import * diff --git a/python/runfiles/runfiles.py b/python/runfiles/runfiles.py index c310f06b96..01413fc529 100644 --- a/python/runfiles/runfiles.py +++ b/python/runfiles/runfiles.py @@ -14,49 +14,7 @@ """Runfiles lookup library for Bazel-built Python binaries and tests. -USAGE: - -1. Depend on this runfiles library from your build rule: - - py_binary( - name = "my_binary", - ... - deps = ["@rules_python//python/runfiles"], - ) - -2. Import the runfiles library. - - from python.runfiles import runfiles - -3. Create a Runfiles object and use rlocation to look up runfile paths: - - r = runfiles.Create() - ... - with open(r.Rlocation("my_workspace/path/to/my/data.txt"), "r") as f: - contents = f.readlines() - ... - - The code above creates a manifest- or directory-based implementations based - on the environment variables in os.environ. See `Create()` for more info. - - If you want to explicitly create a manifest- or directory-based - implementations, you can do so as follows: - - r1 = runfiles.CreateManifestBased("path/to/foo.runfiles_manifest") - - r2 = runfiles.CreateDirectoryBased("path/to/foo.runfiles/") - - If you want to start subprocesses that also need runfiles, you need to set - the right environment variables for them: - - import subprocess - from bazel_tools.tools.python.runfiles import runfiles - - r = runfiles.Create() - env = {} - ... - env.update(r.EnvVars()) - p = subprocess.Popen([r.Rlocation("path/to/binary")], env, ...) +See README.md for usage instructions. """ import inspect import os diff --git a/tests/runfiles/runfiles_wheel_integration_test.sh b/tests/runfiles/runfiles_wheel_integration_test.sh new file mode 100755 index 0000000000..7faa027909 --- /dev/null +++ b/tests/runfiles/runfiles_wheel_integration_test.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +# Manual test, run outside of Bazel, to check that our runfiles wheel should be functional +# for users who install it from pypi. +set -o errexit + +SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" + +bazel 2>/dev/null build --stamp --embed_label=1.2.3 //python/runfiles:wheel +wheelpath=$SCRIPTPATH/../../$(bazel 2>/dev/null cquery --output=files //python/runfiles:wheel) +PYTHONPATH=$wheelpath python3 -c 'import importlib;print(importlib.import_module("runfiles"))' From b4a47a46016b9bc1fb9fe82c262f151da0c4d0cf Mon Sep 17 00:00:00 2001 From: Matt Mackay Date: Mon, 23 Jan 2023 14:53:00 -0500 Subject: [PATCH 118/234] feat: allow patching the interpreter fetched via toolchains (#1004) --- python/repositories.bzl | 15 +++++++++++++-- python/versions.bzl | 16 ++++++++++++---- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/python/repositories.bzl b/python/repositories.bzl index ba8e433995..de8d90ae36 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -31,7 +31,7 @@ load( "MINOR_MAPPING", "PLATFORMS", "TOOL_VERSIONS", - "get_release_url", + "get_release_info", ) def http_archive(**kwargs): @@ -142,6 +142,12 @@ def _python_repository_impl(rctx): stripPrefix = rctx.attr.strip_prefix, ) + patches = rctx.attr.patches + if patches: + for patch in patches: + # Should take the strip as an attr, but this is fine for the moment + rctx.patch(patch, strip = 1) + # Write distutils.cfg to the Python installation. if "windows" in rctx.os.name: distutils_path = "Lib/distutils/distutils.cfg" @@ -310,6 +316,10 @@ python_repository = repository_rule( doc = "Whether the check for root should be ignored or not. This causes cache misses with .pyc files.", mandatory = False, ), + "patches": attr.label_list( + doc = "A list of patch files to apply to the unpacked interpreter", + mandatory = False, + ), "platform": attr.string( doc = "The platform name for the Python interpreter tarball.", mandatory = True, @@ -389,7 +399,7 @@ def python_register_toolchains( if not sha256: continue - (release_filename, url, strip_prefix) = get_release_url(platform, python_version, base_url, tool_versions) + (release_filename, url, strip_prefix, patches) = get_release_info(platform, python_version, base_url, tool_versions) python_repository( name = "{name}_{platform}".format( @@ -397,6 +407,7 @@ def python_register_toolchains( platform = platform, ), sha256 = sha256, + patches = patches, platform = platform, python_version = python_version, release_filename = release_filename, diff --git a/python/versions.bzl b/python/versions.bzl index 56d7ae1f1c..3c19c1890b 100644 --- a/python/versions.bzl +++ b/python/versions.bzl @@ -248,7 +248,7 @@ PLATFORMS = { ), } -def get_release_url(platform, python_version, base_url = DEFAULT_RELEASE_BASE_URL, tool_versions = TOOL_VERSIONS): +def get_release_info(platform, python_version, base_url = DEFAULT_RELEASE_BASE_URL, tool_versions = TOOL_VERSIONS): """Resolve the release URL for the requested interpreter version Args: @@ -276,7 +276,15 @@ def get_release_url(platform, python_version, base_url = DEFAULT_RELEASE_BASE_UR build = "shared-install_only" if (WINDOWS_NAME in platform) else "install_only", ) url = "/".join([base_url, release_filename]) - return (release_filename, url, strip_prefix) + + patches = tool_versions[python_version].get("patches", []) + if type(patches) == type({}): + if platform in patches.keys(): + patches = patches[platform] + else: + patches = [] + + return (release_filename, url, strip_prefix, patches) def print_toolchains_checksums(name): native.genrule( @@ -307,8 +315,8 @@ def _commands_for_version(python_version): "echo \"{python_version}: {platform}: $$(curl --location --fail {release_url_sha256} 2>/dev/null || curl --location --fail {release_url} 2>/dev/null | shasum -a 256 | awk '{{ print $$1 }}')\"".format( python_version = python_version, platform = platform, - release_url = get_release_url(platform, python_version)[1], - release_url_sha256 = get_release_url(platform, python_version)[1] + ".sha256", + release_url = get_release_info(platform, python_version)[1], + release_url_sha256 = get_release_info(platform, python_version)[1] + ".sha256", ) for platform in TOOL_VERSIONS[python_version]["sha256"].keys() ]) From 767e3ced63df806242c3f5103b1290bc3ce4b914 Mon Sep 17 00:00:00 2001 From: aptenodytes-forsteri <92043606+aptenodytes-forsteri@users.noreply.github.com> Date: Mon, 23 Jan 2023 16:58:33 -0500 Subject: [PATCH 119/234] Redirect stdout when checking imports. (#1007) Fixes https://github.com/bazelbuild/rules_python/issues/1006 Also, set PYTHONNOUSERSITE so that the script doesn't even look in site packages when checking modules. Fix typo with capitilize. --- gazelle/std_modules.go | 4 ++-- gazelle/std_modules.py | 28 +++++++++++++--------------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/gazelle/std_modules.go b/gazelle/std_modules.go index f7d0c243d5..e784a2d301 100644 --- a/gazelle/std_modules.go +++ b/gazelle/std_modules.go @@ -37,8 +37,8 @@ func init() { cmd := exec.CommandContext(ctx, stdModulesScriptRunfile) cmd.Stderr = os.Stderr - cmd.Env = []string{} - + // All userland site-packages should be ignored. + cmd.Env = []string{"PYTHONNOUSERSITE=1"} stdin, err := cmd.StdinPipe() if err != nil { log.Printf("failed to initialize std_modules: %v\n", err) diff --git a/gazelle/std_modules.py b/gazelle/std_modules.py index ccd1dcd3aa..86a20774f0 100644 --- a/gazelle/std_modules.py +++ b/gazelle/std_modules.py @@ -3,30 +3,28 @@ # it evaluates, it outputs true/false for whether the module is part of the # standard library or not. -import site +import os import sys - - -# Don't return any paths, all userland site-packages should be ignored. -def __override_getusersitepackages__(): - return "" - - -site.getusersitepackages = __override_getusersitepackages__ +from contextlib import redirect_stdout def is_std_modules(module): - try: - __import__(module, globals(), locals(), [], 0) - return True - except Exception: - return False + # If for some reason a module (such as pygame, see https://github.com/pygame/pygame/issues/542) + # prints to stdout upon import, + # the output of this script should still be parseable by golang. + # Therefore, redirect stdout while running the import. + with redirect_stdout(os.devnull): + try: + __import__(module, globals(), locals(), [], 0) + return True + except Exception: + return False def main(stdin, stdout): for module in stdin: module = module.strip() - # Don't print the boolean directly as it is captilized in Python. + # Don't print the boolean directly as it is capitalized in Python. print( "true" if is_std_modules(module) else "false", end="\n", From 5f166c1753bc6ac10acc1f38af266df4b398e35a Mon Sep 17 00:00:00 2001 From: Michael Krasnyk Date: Mon, 23 Jan 2023 23:30:50 +0100 Subject: [PATCH 120/234] Fix Python interpreter target labels with @@ prefixes. (#940) ERROR: An error occurred during the fetch of repository 'rules_python~0.16.1~pip~pip': Traceback (most recent call last): File "/home/miha/.cache/bazel/_bazel_miha/bd93af10788cff1331d75ed739998a3c/external/rules_python~0.16.1/python/pip_install/pip_repository.bzl", line 335, column 63, in _pip_repository_impl environment = _create_repository_execution_environment(rctx), File "/home/miha/.cache/bazel/_bazel_miha/bd93af10788cff1331d75ed739998a3c/external/rules_python~0.16.1/python/pip_install/pip_repository.bzl", line 210, column 47, in _create_repository_execution_environment cppflags.extend(_get_toolchain_unix_cflags(rctx)) File "/home/miha/.cache/bazel/_bazel_miha/bd93af10788cff1331d75ed739998a3c/external/rules_python~0.16.1/python/pip_install/pip_repository.bzl", line 115, column 37, in _get_toolchain_unix_cflags if not is_standalone_interpreter(rctx, rctx.attr.python_interpreter_target): File "/home/miha/.cache/bazel/_bazel_miha/bd93af10788cff1331d75ed739998a3c/external/rules_python~0.16.1/python/repositories.bzl", line 64, column 22, in is_standalone_interpreter rctx.path(Label("@{}//:WORKSPACE".format(rctx.attr.python_interpreter_target.workspace_name))).dirname, Error in path: Unable to load package for @[unknown repo 'rules_python~0.16.1~python~python3_10_x86_64-unknown-linux-gnu' requested from @rules_python~0.16.1]//:WORKSPACE: The repository '@[unknown repo 'rules_python~0.16.1~python~python3_10_x86_64-unknown-linux-gnu' requested from @rules_python~0.16.1]' could not be resolved: No repository visible as '@rules_python~0.16.1~python~python3_10_x86_64-unknown-linux-gnu' from repository '@rules_python~0.16.1' --- python/pip_install/pip_repository.bzl | 4 ++-- python/repositories.bzl | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl index 782a947fc4..0685a88366 100644 --- a/python/pip_install/pip_repository.bzl +++ b/python/pip_install/pip_repository.bzl @@ -1,6 +1,6 @@ "" -load("//python:repositories.bzl", "is_standalone_interpreter") +load("//python:repositories.bzl", "get_interpreter_dirname", "is_standalone_interpreter") load("//python/pip_install:repositories.bzl", "all_requirements") load("//python/pip_install:requirements_parser.bzl", parse_requirements = "parse") load("//python/pip_install/private:srcs.bzl", "PIP_INSTALL_PY_SRCS") @@ -124,7 +124,7 @@ def _get_toolchain_unix_cflags(rctx): fail("could not get python version from interpreter (status {}): {}".format(er.return_code, er.stderr)) _python_version = er.stdout include_path = "{}/include/python{}".format( - rctx.path(Label("@{}//:WORKSPACE".format(rctx.attr.python_interpreter_target.workspace_name))).dirname.realpath, + get_interpreter_dirname(rctx, rctx.attr.python_interpreter_target), _python_version, ) diff --git a/python/repositories.bzl b/python/repositories.bzl index de8d90ae36..e151d88c16 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -58,6 +58,19 @@ def py_repositories(): STANDALONE_INTERPRETER_FILENAME = "STANDALONE_INTERPRETER" +def get_interpreter_dirname(rctx, python_interpreter_target): + """Get a python interpreter target dirname. + + Args: + rctx (repository_ctx): The repository rule's context object. + python_interpreter_target (Target): A target representing a python interpreter. + + Returns: + str: The Python interpreter directory. + """ + + return rctx.path(Label("{}//:WORKSPACE".format(str(python_interpreter_target).split("//")[0]))).dirname + def is_standalone_interpreter(rctx, python_interpreter_target): """Query a python interpreter target for whether or not it's a rules_rust provided toolchain @@ -77,7 +90,7 @@ def is_standalone_interpreter(rctx, python_interpreter_target): return rctx.execute([ "ls", "{}/{}".format( - rctx.path(Label("@{}//:WORKSPACE".format(rctx.attr.python_interpreter_target.workspace_name))).dirname, + get_interpreter_dirname(rctx, python_interpreter_target), STANDALONE_INTERPRETER_FILENAME, ), ]).return_code == 0 From 1d283fc16984da5a8c1b306328bde4264c8c4bfb Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Mon, 23 Jan 2023 14:40:18 -0800 Subject: [PATCH 121/234] cleanup: remove vendored copy of skylib (#1003) Following #1001 we require that users install bazel-skylib, so we are now free to load from it. --- BUILD.bazel | 3 - docs/BUILD.bazel | 4 +- examples/multi_python_versions/WORKSPACE | 8 +- python/pip_install/repositories.bzl | 4 +- .../tools/wheel_installer/wheel_installer.py | 2 +- tests/compile_pip_requirements/WORKSPACE | 6 +- .../bazelbuild/bazel-skylib/README.md | 4 - .../bazelbuild/bazel-skylib/lib/BUILD | 22 --- .../bazelbuild/bazel-skylib/lib/versions.bzl | 128 ---------------- .../bazelbuild/bazel-skylib/rules/BUILD | 36 ----- .../bazel-skylib/rules/copy_file.bzl | 29 ---- .../bazel-skylib/rules/private/BUILD | 18 --- .../rules/private/copy_file_private.bzl | 141 ------------------ 13 files changed, 12 insertions(+), 393 deletions(-) delete mode 100644 third_party/github.com/bazelbuild/bazel-skylib/README.md delete mode 100644 third_party/github.com/bazelbuild/bazel-skylib/lib/BUILD delete mode 100644 third_party/github.com/bazelbuild/bazel-skylib/lib/versions.bzl delete mode 100644 third_party/github.com/bazelbuild/bazel-skylib/rules/BUILD delete mode 100644 third_party/github.com/bazelbuild/bazel-skylib/rules/copy_file.bzl delete mode 100644 third_party/github.com/bazelbuild/bazel-skylib/rules/private/BUILD delete mode 100644 third_party/github.com/bazelbuild/bazel-skylib/rules/private/copy_file_private.bzl diff --git a/BUILD.bazel b/BUILD.bazel index 654e0149b4..5e9b5920a7 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -35,9 +35,6 @@ filegroup( "//gazelle:distribution", "//python:distribution", "//python/pip_install:distribution", - "//third_party/github.com/bazelbuild/bazel-skylib/lib:distribution", - "//third_party/github.com/bazelbuild/bazel-skylib/rules:distribution", - "//third_party/github.com/bazelbuild/bazel-skylib/rules/private:distribution", "//tools:distribution", ], visibility = [ diff --git a/docs/BUILD.bazel b/docs/BUILD.bazel index f2f13be05b..105a68e3be 100644 --- a/docs/BUILD.bazel +++ b/docs/BUILD.bazel @@ -109,7 +109,7 @@ stardoc( deps = [ ":bazel_repo_tools", ":pip_install_bzl", - "//third_party/github.com/bazelbuild/bazel-skylib/lib:versions", + "@bazel_skylib//lib:versions", ], ) @@ -122,7 +122,7 @@ stardoc( ":bazel_repo_tools", ":pip_install_bzl", ":requirements_parser_bzl", - "//third_party/github.com/bazelbuild/bazel-skylib/lib:versions", + "@bazel_skylib//lib:versions", ], ) diff --git a/examples/multi_python_versions/WORKSPACE b/examples/multi_python_versions/WORKSPACE index 698bce87ed..41c8880221 100644 --- a/examples/multi_python_versions/WORKSPACE +++ b/examples/multi_python_versions/WORKSPACE @@ -5,14 +5,14 @@ local_repository( path = "../..", ) -load("@rules_python//python/pip_install:repositories.bzl", "pip_install_dependencies") - -pip_install_dependencies() - load("@rules_python//python:repositories.bzl", "py_repositories", "python_register_multi_toolchains") py_repositories() +load("@rules_python//python/pip_install:repositories.bzl", "pip_install_dependencies") + +pip_install_dependencies() + default_python_version = "3.9" python_register_multi_toolchains( diff --git a/python/pip_install/repositories.bzl b/python/pip_install/repositories.bzl index 5ce427dc8e..12fe9403a6 100644 --- a/python/pip_install/repositories.bzl +++ b/python/pip_install/repositories.bzl @@ -1,11 +1,9 @@ "" +load("@bazel_skylib//lib:versions.bzl", "versions") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") -# Avoid a load from @bazel_skylib repository as users don't necessarily have it installed -load("//third_party/github.com/bazelbuild/bazel-skylib/lib:versions.bzl", "versions") - _RULE_DEPS = [ ( "pypi__build", diff --git a/python/pip_install/tools/wheel_installer/wheel_installer.py b/python/pip_install/tools/wheel_installer/wheel_installer.py index a324fbb3e3..1f6eaf2450 100644 --- a/python/pip_install/tools/wheel_installer/wheel_installer.py +++ b/python/pip_install/tools/wheel_installer/wheel_installer.py @@ -226,7 +226,7 @@ def _generate_build_file_contents( textwrap.dedent( """\ load("@rules_python//python:defs.bzl", "py_library", "py_binary") - load("@rules_python//third_party/github.com/bazelbuild/bazel-skylib/rules:copy_file.bzl", "copy_file") + load("@bazel_skylib//rules:copy_file.bzl", "copy_file") package(default_visibility = ["//visibility:public"]) diff --git a/tests/compile_pip_requirements/WORKSPACE b/tests/compile_pip_requirements/WORKSPACE index d3fd700911..d3a419cfc5 100644 --- a/tests/compile_pip_requirements/WORKSPACE +++ b/tests/compile_pip_requirements/WORKSPACE @@ -3,12 +3,14 @@ local_repository( path = "../..", ) +load("@rules_python//python:repositories.bzl", "py_repositories", "python_register_toolchains") + +py_repositories() + load("@rules_python//python/pip_install:repositories.bzl", "pip_install_dependencies") pip_install_dependencies() -load("@rules_python//python:repositories.bzl", "python_register_toolchains") - python_register_toolchains( name = "python39", python_version = "3.9", diff --git a/third_party/github.com/bazelbuild/bazel-skylib/README.md b/third_party/github.com/bazelbuild/bazel-skylib/README.md deleted file mode 100644 index 5ed93ff6d1..0000000000 --- a/third_party/github.com/bazelbuild/bazel-skylib/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# vendored copy of skylib - -This exists so that users of rules_python don't have to install bazel-skylib -copied from https://github.com/bazelbuild/bazel-skylib/blob/1.0.3 \ No newline at end of file diff --git a/third_party/github.com/bazelbuild/bazel-skylib/lib/BUILD b/third_party/github.com/bazelbuild/bazel-skylib/lib/BUILD deleted file mode 100644 index 9560aed406..0000000000 --- a/third_party/github.com/bazelbuild/bazel-skylib/lib/BUILD +++ /dev/null @@ -1,22 +0,0 @@ -load("@bazel_skylib//:bzl_library.bzl", "bzl_library") - -licenses(["notice"]) - -package(default_visibility = ["//visibility:public"]) - -# export bzl files for the documentation -exports_files( - glob(["*.bzl"]), - visibility = ["//:__subpackages__"], -) - -filegroup( - name = "distribution", - srcs = glob(["**"]), - visibility = ["//:__pkg__"], -) - -bzl_library( - name = "versions", - srcs = ["versions.bzl"], -) diff --git a/third_party/github.com/bazelbuild/bazel-skylib/lib/versions.bzl b/third_party/github.com/bazelbuild/bazel-skylib/lib/versions.bzl deleted file mode 100644 index 3cd60197aa..0000000000 --- a/third_party/github.com/bazelbuild/bazel-skylib/lib/versions.bzl +++ /dev/null @@ -1,128 +0,0 @@ -# Copyright 2018 The Bazel Authors. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Skylib module containing functions for checking Bazel versions.""" - -def _get_bazel_version(): - """Returns the current Bazel version""" - - return native.bazel_version - -def _extract_version_number(bazel_version): - """Extracts the semantic version number from a version string - - Args: - bazel_version: the version string that begins with the semantic version - e.g. "1.2.3rc1 abc1234" where "abc1234" is a commit hash. - - Returns: - The semantic version string, like "1.2.3". - """ - for i in range(len(bazel_version)): - c = bazel_version[i] - if not (c.isdigit() or c == "."): - return bazel_version[:i] - return bazel_version - -# Parse the bazel version string from `native.bazel_version`. -# e.g. -# "0.10.0rc1 abc123d" => (0, 10, 0) -# "0.3.0" => (0, 3, 0) -def _parse_bazel_version(bazel_version): - """Parses a version string into a 3-tuple of ints - - int tuples can be compared directly using binary operators (<, >). - - Args: - bazel_version: the Bazel version string - - Returns: - An int 3-tuple of a (major, minor, patch) version. - """ - - version = _extract_version_number(bazel_version) - return tuple([int(n) for n in version.split(".")]) - -def _is_at_most(threshold, version): - """Check that a version is lower or equals to a threshold. - - Args: - threshold: the maximum version string - version: the version string to be compared to the threshold - - Returns: - True if version <= threshold. - """ - return _parse_bazel_version(version) <= _parse_bazel_version(threshold) - -def _is_at_least(threshold, version): - """Check that a version is higher or equals to a threshold. - - Args: - threshold: the minimum version string - version: the version string to be compared to the threshold - - Returns: - True if version >= threshold. - """ - - return _parse_bazel_version(version) >= _parse_bazel_version(threshold) - -def _check_bazel_version(minimum_bazel_version, maximum_bazel_version = None, bazel_version = None): - """Check that the version of Bazel is valid within the specified range. - - Args: - minimum_bazel_version: minimum version of Bazel expected - maximum_bazel_version: maximum version of Bazel expected - bazel_version: the version of Bazel to check. Used for testing, defaults to native.bazel_version - """ - if not bazel_version: - if "bazel_version" not in dir(native): - fail("Bazel version cannot be determined; expected at least {}".format( - minimum_bazel_version, - )) - elif not native.bazel_version: - # Using a non-release version, assume it is good. - return - else: - bazel_version = native.bazel_version - - if not _is_at_least( - threshold = minimum_bazel_version, - version = bazel_version, - ): - fail("Current Bazel version is {}; expected at least {}".format( - bazel_version, - minimum_bazel_version, - )) - - if maximum_bazel_version: - if not _is_at_most( - threshold = maximum_bazel_version, - version = bazel_version, - ): - fail("Current Bazel version is {}; expected at most {}".format( - bazel_version, - maximum_bazel_version, - )) - - pass - -versions = struct( - get = _get_bazel_version, - parse = _parse_bazel_version, - check = _check_bazel_version, - is_at_most = _is_at_most, - is_at_least = _is_at_least, -) diff --git a/third_party/github.com/bazelbuild/bazel-skylib/rules/BUILD b/third_party/github.com/bazelbuild/bazel-skylib/rules/BUILD deleted file mode 100644 index 6857449878..0000000000 --- a/third_party/github.com/bazelbuild/bazel-skylib/rules/BUILD +++ /dev/null @@ -1,36 +0,0 @@ -load("@bazel_skylib//:bzl_library.bzl", "bzl_library") - -licenses(["notice"]) - -package(default_visibility = ["//visibility:public"]) - -bzl_library( - name = "copy_file", - srcs = ["copy_file.bzl"], - deps = ["//third_party/github.com/bazelbuild/bazel-skylib/rules/private:copy_file_private"], -) - -filegroup( - name = "test_deps", - testonly = True, - srcs = [ - "BUILD", - ] + glob(["*.bzl"]), -) - -# The files needed for distribution -filegroup( - name = "distribution", - srcs = [ - "BUILD", - ] + glob(["*.bzl"]), - visibility = [ - "//:__pkg__", - ], -) - -# export bzl files for the documentation -exports_files( - glob(["*.bzl"]), - visibility = ["//:__subpackages__"], -) diff --git a/third_party/github.com/bazelbuild/bazel-skylib/rules/copy_file.bzl b/third_party/github.com/bazelbuild/bazel-skylib/rules/copy_file.bzl deleted file mode 100644 index 2908fa6e85..0000000000 --- a/third_party/github.com/bazelbuild/bazel-skylib/rules/copy_file.bzl +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright 2019 The Bazel Authors. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""A rule that copies a file to another place. - -native.genrule() is sometimes used to copy files (often wishing to rename them). -The 'copy_file' rule does this with a simpler interface than genrule. - -The rule uses a Bash command on Linux/macOS/non-Windows, and a cmd.exe command -on Windows (no Bash is required). -""" - -load( - "@rules_python//third_party/github.com/bazelbuild/bazel-skylib/rules/private:copy_file_private.bzl", - _copy_file = "copy_file", -) - -copy_file = _copy_file diff --git a/third_party/github.com/bazelbuild/bazel-skylib/rules/private/BUILD b/third_party/github.com/bazelbuild/bazel-skylib/rules/private/BUILD deleted file mode 100644 index a1aeb39914..0000000000 --- a/third_party/github.com/bazelbuild/bazel-skylib/rules/private/BUILD +++ /dev/null @@ -1,18 +0,0 @@ -load("@bazel_skylib//:bzl_library.bzl", "bzl_library") - -licenses(["notice"]) - -bzl_library( - name = "copy_file_private", - srcs = ["copy_file_private.bzl"], - visibility = ["//third_party/github.com/bazelbuild/bazel-skylib/rules:__pkg__"], -) - -# The files needed for distribution -filegroup( - name = "distribution", - srcs = glob(["*"]), - visibility = [ - "//:__subpackages__", - ], -) diff --git a/third_party/github.com/bazelbuild/bazel-skylib/rules/private/copy_file_private.bzl b/third_party/github.com/bazelbuild/bazel-skylib/rules/private/copy_file_private.bzl deleted file mode 100644 index d044c9767e..0000000000 --- a/third_party/github.com/bazelbuild/bazel-skylib/rules/private/copy_file_private.bzl +++ /dev/null @@ -1,141 +0,0 @@ -# Copyright 2019 The Bazel Authors. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Implementation of copy_file macro and underlying rules. - -These rules copy a file to another location using Bash (on Linux/macOS) or -cmd.exe (on Windows). '_copy_xfile' marks the resulting file executable, -'_copy_file' does not. -""" - -def copy_cmd(ctx, src, dst): - # Most Windows binaries built with MSVC use a certain argument quoting - # scheme. Bazel uses that scheme too to quote arguments. However, - # cmd.exe uses different semantics, so Bazel's quoting is wrong here. - # To fix that we write the command to a .bat file so no command line - # quoting or escaping is required. - bat = ctx.actions.declare_file(ctx.label.name + "-cmd.bat") - ctx.actions.write( - output = bat, - # Do not use lib/shell.bzl's shell.quote() method, because that uses - # Bash quoting syntax, which is different from cmd.exe's syntax. - content = "@copy /Y \"%s\" \"%s\" >NUL" % ( - src.path.replace("/", "\\"), - dst.path.replace("/", "\\"), - ), - is_executable = True, - ) - ctx.actions.run( - inputs = [src], - tools = [bat], - outputs = [dst], - executable = "cmd.exe", - arguments = ["/C", bat.path.replace("/", "\\")], - mnemonic = "CopyFile", - progress_message = "Copying files", - use_default_shell_env = True, - ) - -def copy_bash(ctx, src, dst): - ctx.actions.run_shell( - tools = [src], - outputs = [dst], - command = "cp -f \"$1\" \"$2\"", - arguments = [src.path, dst.path], - mnemonic = "CopyFile", - progress_message = "Copying files", - use_default_shell_env = True, - ) - -def _copy_file_impl(ctx): - if ctx.attr.allow_symlink: - ctx.actions.symlink( - output = ctx.outputs.out, - target_file = ctx.file.src, - is_executable = ctx.attr.is_executable, - ) - elif ctx.attr.is_windows: - copy_cmd(ctx, ctx.file.src, ctx.outputs.out) - else: - copy_bash(ctx, ctx.file.src, ctx.outputs.out) - - files = depset(direct = [ctx.outputs.out]) - runfiles = ctx.runfiles(files = [ctx.outputs.out]) - if ctx.attr.is_executable: - return [DefaultInfo(files = files, runfiles = runfiles, executable = ctx.outputs.out)] - else: - return [DefaultInfo(files = files, runfiles = runfiles)] - -_ATTRS = { - "allow_symlink": attr.bool(mandatory = True), - "is_executable": attr.bool(mandatory = True), - "is_windows": attr.bool(mandatory = True), - "out": attr.output(mandatory = True), - "src": attr.label(mandatory = True, allow_single_file = True), -} - -_copy_file = rule( - implementation = _copy_file_impl, - provides = [DefaultInfo], - attrs = _ATTRS, -) - -_copy_xfile = rule( - implementation = _copy_file_impl, - executable = True, - provides = [DefaultInfo], - attrs = _ATTRS, -) - -def copy_file(name, src, out, is_executable = False, allow_symlink = False, **kwargs): - """Copies a file to another location. - - `native.genrule()` is sometimes used to copy files (often wishing to rename them). The 'copy_file' rule does this with a simpler interface than genrule. - - This rule uses a Bash command on Linux/macOS/non-Windows, and a cmd.exe command on Windows (no Bash is required). - - Args: - name: Name of the rule. - src: A Label. The file to make a copy of. (Can also be the label of a rule - that generates a file.) - out: Path of the output file, relative to this package. - is_executable: A boolean. Whether to make the output file executable. When - True, the rule's output can be executed using `bazel run` and can be - in the srcs of binary and test rules that require executable sources. - WARNING: If `allow_symlink` is True, `src` must also be executable. - allow_symlink: A boolean. Whether to allow symlinking instead of copying. - When False, the output is always a hard copy. When True, the output - *can* be a symlink, but there is no guarantee that a symlink is - created (i.e., at the time of writing, we don't create symlinks on - Windows). Set this to True if you need fast copying and your tools can - handle symlinks (which most UNIX tools can). - **kwargs: further keyword arguments, e.g. `visibility` - """ - - copy_file_impl = _copy_file - if is_executable: - copy_file_impl = _copy_xfile - - copy_file_impl( - name = name, - src = src, - out = out, - is_windows = select({ - "@bazel_tools//src/conditions:host_windows": True, - "//conditions:default": False, - }), - is_executable = is_executable, - allow_symlink = allow_symlink, - **kwargs - ) From 0943375cbbef6b1f73c439b5e350ac93b1b22bfa Mon Sep 17 00:00:00 2001 From: Zhongpeng Lin Date: Mon, 23 Jan 2023 14:40:50 -0800 Subject: [PATCH 122/234] generate py_test without __test__ (#999) --- gazelle/generate.go | 56 ++++++++++--------- .../python_target_with_test_in_name/BUILD.out | 24 +++++--- .../{not_a_real_test.py => real_test.py} | 0 .../{test_not_a_real.py => test_reality.py} | 0 4 files changed, 47 insertions(+), 33 deletions(-) rename gazelle/testdata/python_target_with_test_in_name/{not_a_real_test.py => real_test.py} (100%) rename gazelle/testdata/python_target_with_test_in_name/{test_not_a_real.py => test_reality.py} (100%) diff --git a/gazelle/generate.go b/gazelle/generate.go index c7b0709687..ac0ba6b8cf 100644 --- a/gazelle/generate.go +++ b/gazelle/generate.go @@ -69,10 +69,10 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes // this package or not. hasPyBinary := false - // hasPyTestFile and hasPyTestTarget control whether a py_test target should + // hasPyTestEntryPointFile and hasPyTestEntryPointTarget control whether a py_test target should // be generated for this package or not. - hasPyTestFile := false - hasPyTestTarget := false + hasPyTestEntryPointFile := false + hasPyTestEntryPointTarget := false hasConftestFile := false for _, f := range args.RegularFiles { @@ -82,8 +82,8 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes ext := filepath.Ext(f) if !hasPyBinary && f == pyBinaryEntrypointFilename { hasPyBinary = true - } else if !hasPyTestFile && f == pyTestEntrypointFilename { - hasPyTestFile = true + } else if !hasPyTestEntryPointFile && f == pyTestEntrypointFilename { + hasPyTestEntryPointFile = true } else if f == conftestFilename { hasConftestFile = true } else if strings.HasSuffix(f, "_test.py") || (strings.HasPrefix(f, "test_") && ext == ".py") { @@ -95,10 +95,10 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes // If a __test__.py file was not found on disk, search for targets that are // named __test__. - if !hasPyTestFile && args.File != nil { + if !hasPyTestEntryPointFile && args.File != nil { for _, rule := range args.File.Rules { if rule.Name() == pyTestEntrypointTargetname { - hasPyTestTarget = true + hasPyTestEntryPointTarget = true break } } @@ -185,13 +185,6 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes collisionErrors := singlylinkedlist.New() - if !hasPyTestFile && !hasPyTestTarget { - it := pyTestFilenames.Iterator() - for it.Next() { - pyLibraryFilenames.Add(it.Value()) - } - } - var pyLibrary *rule.Rule if !pyLibraryFilenames.Empty() { deps, err := parser.parse(pyLibraryFilenames) @@ -309,19 +302,12 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes result.Imports = append(result.Imports, conftest.PrivateAttr(config.GazelleImportsKey)) } - if hasPyTestFile || hasPyTestTarget { - if hasPyTestFile { - // Only add the pyTestEntrypointFilename to the pyTestFilenames if - // the file exists on disk. - pyTestFilenames.Add(pyTestEntrypointFilename) - } + var pyTestTargets []*targetBuilder + newPyTestTargetBuilder := func(pyTestFilenames *treeset.Set, pyTestTargetName string) *targetBuilder { deps, err := parser.parse(pyTestFilenames) if err != nil { log.Fatalf("ERROR: %v\n", err) } - - pyTestTargetName := cfg.RenderTestName(packageName) - // Check if a target with the same name we are generating already // exists, and if it is of a different kind from the one we are // generating. If so, we have to throw an error since Gazelle won't @@ -338,13 +324,21 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } } } - - pyTestTarget := newTargetBuilder(pyTestKind, pyTestTargetName, pythonProjectRoot, args.Rel). + return newTargetBuilder(pyTestKind, pyTestTargetName, pythonProjectRoot, args.Rel). addSrcs(pyTestFilenames). addModuleDependencies(deps). generateImportsAttribute() + } + if hasPyTestEntryPointFile || hasPyTestEntryPointTarget { + if hasPyTestEntryPointFile { + // Only add the pyTestEntrypointFilename to the pyTestFilenames if + // the file exists on disk. + pyTestFilenames.Add(pyTestEntrypointFilename) + } + pyTestTargetName := cfg.RenderTestName(packageName) + pyTestTarget := newPyTestTargetBuilder(pyTestFilenames, pyTestTargetName) - if hasPyTestTarget { + if hasPyTestEntryPointTarget { entrypointTarget := fmt.Sprintf(":%s", pyTestEntrypointTargetname) main := fmt.Sprintf(":%s", pyTestEntrypointFilename) pyTestTarget. @@ -354,7 +348,17 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } else { pyTestTarget.setMain(pyTestEntrypointFilename) } + pyTestTargets = append(pyTestTargets, pyTestTarget) + } else { + // Create one py_test target per file + pyTestFilenames.Each(func(index int, testFile interface{}) { + srcs := treeset.NewWith(godsutils.StringComparator, testFile) + pyTestTargetName := strings.TrimSuffix(filepath.Base(testFile.(string)), ".py") + pyTestTargets = append(pyTestTargets, newPyTestTargetBuilder(srcs, pyTestTargetName)) + }) + } + for _, pyTestTarget := range pyTestTargets { if pyLibrary != nil { pyTestTarget.addModuleDependency(module{Name: pyLibrary.PrivateAttr(uuidKey).(string)}) } diff --git a/gazelle/testdata/python_target_with_test_in_name/BUILD.out b/gazelle/testdata/python_target_with_test_in_name/BUILD.out index 72a648ffe5..a46f5c40b8 100644 --- a/gazelle/testdata/python_target_with_test_in_name/BUILD.out +++ b/gazelle/testdata/python_target_with_test_in_name/BUILD.out @@ -1,12 +1,22 @@ -load("@rules_python//python:defs.bzl", "py_library") +load("@rules_python//python:defs.bzl", "py_library", "py_test") py_library( name = "python_target_with_test_in_name", - srcs = [ - "__init__.py", - "not_a_real_test.py", - "test_not_a_real.py", - ], + srcs = ["__init__.py"], visibility = ["//:__subpackages__"], - deps = ["@gazelle_python_test_boto3//:pkg"], +) + +py_test( + name = "real_test", + srcs = ["real_test.py"], + deps = [ + ":python_target_with_test_in_name", + "@gazelle_python_test_boto3//:pkg", + ], +) + +py_test( + name = "test_reality", + srcs = ["test_reality.py"], + deps = [":python_target_with_test_in_name"], ) diff --git a/gazelle/testdata/python_target_with_test_in_name/not_a_real_test.py b/gazelle/testdata/python_target_with_test_in_name/real_test.py similarity index 100% rename from gazelle/testdata/python_target_with_test_in_name/not_a_real_test.py rename to gazelle/testdata/python_target_with_test_in_name/real_test.py diff --git a/gazelle/testdata/python_target_with_test_in_name/test_not_a_real.py b/gazelle/testdata/python_target_with_test_in_name/test_reality.py similarity index 100% rename from gazelle/testdata/python_target_with_test_in_name/test_not_a_real.py rename to gazelle/testdata/python_target_with_test_in_name/test_reality.py From 8081ca6b86861c348d9749294b89ef7452167fbe Mon Sep 17 00:00:00 2001 From: Zhongpeng Lin Date: Mon, 23 Jan 2023 14:42:37 -0800 Subject: [PATCH 123/234] Add runtime dependencies to gazelle extension (#993) --- gazelle/BUILD.bazel | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gazelle/BUILD.bazel b/gazelle/BUILD.bazel index 593831db46..303b496364 100644 --- a/gazelle/BUILD.bazel +++ b/gazelle/BUILD.bazel @@ -15,6 +15,10 @@ go_library( "std_modules.go", "target.go", ], + data = [ + ":parse", + ":std_modules", + ], importpath = "github.com/bazelbuild/rules_python/gazelle", visibility = ["//visibility:public"], deps = [ From 64d287bafed0ee18b2096d8d839c61a416037e7c Mon Sep 17 00:00:00 2001 From: Lukas Date: Mon, 23 Jan 2023 23:44:44 +0100 Subject: [PATCH 124/234] fix: allow omitting the `strip_prefix` in `tool_versions` (#975) --- python/repositories.bzl | 1 - 1 file changed, 1 deletion(-) diff --git a/python/repositories.bzl b/python/repositories.bzl index e151d88c16..011d4f9112 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -352,7 +352,6 @@ python_repository = repository_rule( ), "strip_prefix": attr.string( doc = "A directory prefix to strip from the extracted files.", - mandatory = True, ), "url": attr.string( doc = "The URL of the interpreter to download", From 0ee2a7e1fc948ead8d76f10f9d23a58866455dc8 Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius Date: Tue, 24 Jan 2023 15:49:15 +0900 Subject: [PATCH 125/234] refactor(gazelle): Move plugin to a separate directory. (#983) --- gazelle/BUILD.bazel | 73 ++--------------- gazelle/def.bzl | 4 +- gazelle/python/BUILD.bazel | 81 +++++++++++++++++++ gazelle/{ => python}/configure.go | 0 gazelle/{ => python}/fix.go | 0 gazelle/{ => python}/generate.go | 0 gazelle/{ => python}/kinds.go | 0 gazelle/{ => python}/language.go | 0 gazelle/{ => python}/parse.py | 0 gazelle/{ => python}/parser.go | 2 +- gazelle/{ => python}/python_test.go | 10 +-- gazelle/{ => python}/resolve.go | 0 gazelle/{ => python}/std_modules.go | 2 +- gazelle/{ => python}/std_modules.py | 0 gazelle/{ => python}/target.go | 0 gazelle/{ => python}/testdata/README.md | 0 .../dependency_resolution_order/BUILD.in | 0 .../dependency_resolution_order/BUILD.out | 0 .../dependency_resolution_order/README.md | 0 .../dependency_resolution_order/WORKSPACE | 0 .../dependency_resolution_order/__init__.py | 0 .../dependency_resolution_order/bar/BUILD.in | 0 .../dependency_resolution_order/bar/BUILD.out | 0 .../bar/__init__.py | 0 .../dependency_resolution_order/baz/BUILD.in | 0 .../dependency_resolution_order/baz/BUILD.out | 0 .../baz/__init__.py | 0 .../dependency_resolution_order/foo/BUILD.in | 0 .../dependency_resolution_order/foo/BUILD.out | 0 .../foo/__init__.py | 0 .../gazelle_python.yaml | 0 .../somewhere/bar/BUILD.in | 0 .../somewhere/bar/BUILD.out | 0 .../somewhere/bar/__init__.py | 0 .../dependency_resolution_order/test.yaml | 0 .../BUILD.in | 0 .../BUILD.out | 0 .../README.md | 0 .../WORKSPACE | 0 .../__init__.py | 0 .../test.yaml | 0 .../testdata/dont_rename_target/BUILD.in | 0 .../testdata/dont_rename_target/BUILD.out | 0 .../testdata/dont_rename_target/README.md | 0 .../testdata/dont_rename_target/WORKSPACE | 0 .../testdata/dont_rename_target/__init__.py | 0 .../testdata/dont_rename_target/test.yaml | 0 .../BUILD.in | 0 .../BUILD.out | 0 .../README.md | 0 .../WORKSPACE | 0 .../__init__.py | 0 .../gazelle_python.yaml | 0 .../rest_framework.py | 0 .../test.yaml | 0 .../first_party_dependencies/BUILD.in | 0 .../first_party_dependencies/BUILD.out | 0 .../first_party_dependencies/README.md | 0 .../first_party_dependencies/WORKSPACE | 0 .../first_party_dependencies/one/BUILD.in | 0 .../first_party_dependencies/one/BUILD.out | 0 .../first_party_dependencies/one/__main__.py | 0 .../first_party_dependencies/one/bar/BUILD.in | 0 .../one/bar/BUILD.out | 0 .../one/bar/__init__.py | 0 .../one/bar/baz/BUILD.in | 0 .../one/bar/baz/BUILD.out | 0 .../one/bar/baz/__init__.py | 0 .../first_party_dependencies/one/foo/BUILD.in | 0 .../one/foo/BUILD.out | 0 .../one/foo/__init__.py | 0 .../first_party_dependencies/test.yaml | 0 .../first_party_dependencies/three/BUILD.in | 0 .../first_party_dependencies/three/BUILD.out | 0 .../three/__init__.py | 0 .../first_party_dependencies/two/BUILD.in | 0 .../first_party_dependencies/two/BUILD.out | 0 .../first_party_dependencies/two/__init__.py | 0 .../BUILD.in | 0 .../BUILD.out | 0 .../README.md | 0 .../WORKSPACE | 0 .../__main__.py | 0 .../baz.py | 0 .../foo.py | 0 .../foo/BUILD.in | 0 .../foo/BUILD.out | 0 .../foo/__init__.py | 0 .../foo/bar.py | 0 .../one/BUILD.in | 0 .../one/BUILD.out | 0 .../one/__init__.py | 0 .../one/two.py | 0 .../test.yaml | 0 .../undiscoverable/BUILD.in | 0 .../undiscoverable/BUILD.out | 0 .../package1/subpackage1/BUILD.in | 0 .../package1/subpackage1/BUILD.out | 0 .../package1/subpackage1/__init__.py | 0 .../package1/subpackage1/module1.py | 0 .../testdata/from_imports/BUILD.in | 0 .../testdata/from_imports/BUILD.out | 0 .../testdata/from_imports/README.md | 0 .../testdata/from_imports/WORKSPACE | 0 .../testdata/from_imports/foo/BUILD.in | 0 .../testdata/from_imports/foo/BUILD.out | 0 .../testdata/from_imports/foo/__init__.py | 0 .../testdata/from_imports/foo/bar/BUILD.in | 0 .../testdata/from_imports/foo/bar/BUILD.out | 0 .../testdata/from_imports/foo/bar/__init__.py | 0 .../testdata/from_imports/foo/bar/baz.py | 0 .../testdata/from_imports/gazelle_python.yaml | 0 .../from_imports/import_from_init_py/BUILD.in | 0 .../import_from_init_py/BUILD.out | 0 .../import_from_init_py/__init__.py | 0 .../import_from_multiple/BUILD.in | 0 .../import_from_multiple/BUILD.out | 0 .../import_from_multiple/__init__.py | 0 .../from_imports/import_nested_file/BUILD.in | 0 .../from_imports/import_nested_file/BUILD.out | 0 .../import_nested_file/__init__.py | 0 .../import_nested_module/BUILD.in | 0 .../import_nested_module/BUILD.out | 0 .../import_nested_module/__init__.py | 0 .../from_imports/import_nested_var/BUILD.in | 0 .../from_imports/import_nested_var/BUILD.out | 0 .../import_nested_var/__init__.py | 0 .../import_top_level_var/BUILD.in | 0 .../import_top_level_var/BUILD.out | 0 .../import_top_level_var/__init__.py | 0 .../testdata/from_imports/std_module/BUILD.in | 0 .../from_imports/std_module/BUILD.out | 0 .../from_imports/std_module/__init__.py | 0 .../testdata/from_imports/test.yaml | 0 .../generated_test_entrypoint/BUILD.in | 0 .../generated_test_entrypoint/BUILD.out | 0 .../generated_test_entrypoint/README.md | 0 .../generated_test_entrypoint/WORKSPACE | 0 .../generated_test_entrypoint/__init__.py | 0 .../testdata/generated_test_entrypoint/foo.py | 0 .../generated_test_entrypoint/test.yaml | 0 .../ignored_invalid_imported_module/BUILD.in | 0 .../ignored_invalid_imported_module/BUILD.out | 0 .../ignored_invalid_imported_module/README.md | 0 .../ignored_invalid_imported_module/WORKSPACE | 0 .../__init__.py | 0 .../gazelle_python.yaml | 0 .../ignored_invalid_imported_module/test.yaml | 0 .../testdata/invalid_annotation/BUILD.in | 0 .../testdata/invalid_annotation/BUILD.out | 0 .../testdata/invalid_annotation/README.md | 0 .../testdata/invalid_annotation/WORKSPACE | 0 .../testdata/invalid_annotation/__init__.py | 0 .../testdata/invalid_annotation/test.yaml | 0 .../testdata/invalid_imported_module/BUILD.in | 0 .../invalid_imported_module/BUILD.out | 0 .../invalid_imported_module/README.md | 0 .../invalid_imported_module/WORKSPACE | 0 .../invalid_imported_module/__init__.py | 0 .../invalid_imported_module/test.yaml | 0 .../{ => python}/testdata/monorepo/BUILD.in | 0 .../{ => python}/testdata/monorepo/BUILD.out | 0 .../{ => python}/testdata/monorepo/README.md | 0 .../{ => python}/testdata/monorepo/WORKSPACE | 0 .../testdata/monorepo/coarse_grained/BUILD.in | 0 .../monorepo/coarse_grained/BUILD.out | 0 .../monorepo/coarse_grained/__init__.py | 0 .../coarse_grained/_boundary/BUILD.in | 0 .../coarse_grained/_boundary/BUILD.out | 0 .../coarse_grained/_boundary/README.md | 0 .../coarse_grained/_boundary/__init__.py | 0 .../monorepo/coarse_grained/bar/__init__.py | 0 .../coarse_grained/bar/baz/__init__.py | 0 .../coarse_grained/bar/baz/first_excluded.py | 0 .../monorepo/coarse_grained/bar/baz/hue.py | 0 .../coarse_grained/bar/baz/second_excluded.py | 0 .../monorepo/coarse_grained/foo/__init__.py | 0 .../testdata/monorepo/gazelle_python.yaml | 0 .../testdata/monorepo/one/BUILD.in | 0 .../testdata/monorepo/one/BUILD.out | 0 .../testdata/monorepo/one/__main__.py | 0 .../testdata/monorepo/one/bar/BUILD.in | 0 .../testdata/monorepo/one/bar/BUILD.out | 0 .../testdata/monorepo/one/bar/__init__.py | 0 .../testdata/monorepo/one/bar/baz/BUILD.in | 0 .../testdata/monorepo/one/bar/baz/BUILD.out | 0 .../testdata/monorepo/one/bar/baz/__init__.py | 0 .../testdata/monorepo/one/foo/BUILD.in | 0 .../testdata/monorepo/one/foo/BUILD.out | 0 .../testdata/monorepo/one/foo/__init__.py | 0 .../testdata/monorepo/one/gazelle_python.yaml | 0 .../{ => python}/testdata/monorepo/test.yaml | 0 .../testdata/monorepo/three/BUILD.in | 0 .../testdata/monorepo/three/BUILD.out | 0 .../testdata/monorepo/three/__init__.py | 0 .../monorepo/three/gazelle_python.yaml | 0 .../testdata/monorepo/two/BUILD.in | 0 .../testdata/monorepo/two/BUILD.out | 0 .../testdata/monorepo/two/__init__.py | 0 .../testdata/monorepo/two/gazelle_python.yaml | 0 .../testdata/monorepo/wont_generate/BUILD.in | 0 .../testdata/monorepo/wont_generate/BUILD.out | 0 .../monorepo/wont_generate/__main__.py | 0 .../monorepo/wont_generate/bar/BUILD.in | 0 .../monorepo/wont_generate/bar/BUILD.out | 0 .../monorepo/wont_generate/bar/__init__.py | 0 .../monorepo/wont_generate/bar/baz/BUILD.in | 0 .../monorepo/wont_generate/bar/baz/BUILD.out | 0 .../wont_generate/bar/baz/__init__.py | 0 .../monorepo/wont_generate/foo/BUILD.in | 0 .../monorepo/wont_generate/foo/BUILD.out | 0 .../monorepo/wont_generate/foo/__init__.py | 0 .../testdata/naming_convention/BUILD.in | 0 .../testdata/naming_convention/BUILD.out | 0 .../testdata/naming_convention/README.md | 0 .../testdata/naming_convention/WORKSPACE | 0 .../testdata/naming_convention/__init__.py | 0 .../testdata/naming_convention/__main__.py | 0 .../testdata/naming_convention/__test__.py | 0 .../naming_convention/dont_rename/BUILD.in | 0 .../naming_convention/dont_rename/BUILD.out | 0 .../naming_convention/dont_rename/__init__.py | 0 .../naming_convention/dont_rename/__main__.py | 0 .../naming_convention/dont_rename/__test__.py | 0 .../resolve_conflict/BUILD.in | 0 .../resolve_conflict/BUILD.out | 0 .../resolve_conflict/__init__.py | 0 .../resolve_conflict/__main__.py | 0 .../resolve_conflict/__test__.py | 0 .../testdata/naming_convention/test.yaml | 0 .../naming_convention_binary_fail/BUILD.in | 0 .../naming_convention_binary_fail/BUILD.out | 0 .../naming_convention_binary_fail/README.md | 0 .../naming_convention_binary_fail/WORKSPACE | 0 .../naming_convention_binary_fail/__main__.py | 0 .../naming_convention_binary_fail/test.yaml | 0 .../naming_convention_library_fail/BUILD.in | 0 .../naming_convention_library_fail/BUILD.out | 0 .../naming_convention_library_fail/README.md | 0 .../naming_convention_library_fail/WORKSPACE | 0 .../__init__.py | 0 .../naming_convention_library_fail/test.yaml | 0 .../naming_convention_test_fail/BUILD.in | 0 .../naming_convention_test_fail/BUILD.out | 0 .../naming_convention_test_fail/README.md | 0 .../naming_convention_test_fail/WORKSPACE | 0 .../naming_convention_test_fail/__test__.py | 0 .../naming_convention_test_fail/test.yaml | 0 .../BUILD.in | 0 .../BUILD.out | 0 .../README.md | 0 .../WORKSPACE | 0 .../__init__.py | 0 .../gazelle_python.yaml | 0 .../test.yaml | 0 .../python_ignore_files_directive/BUILD.in | 0 .../python_ignore_files_directive/BUILD.out | 0 .../python_ignore_files_directive/README.md | 0 .../python_ignore_files_directive/WORKSPACE | 0 .../python_ignore_files_directive/__init__.py | 0 .../bar/BUILD.in | 0 .../bar/BUILD.out | 0 .../python_ignore_files_directive/bar/baz.py | 0 .../bar/some_other.py | 0 .../foo/BUILD.in | 0 .../foo/BUILD.out | 0 .../python_ignore_files_directive/foo/baz.py | 0 .../python_ignore_files_directive/setup.py | 0 .../some_other.py | 0 .../python_ignore_files_directive/test.yaml | 0 .../python_target_with_test_in_name/BUILD.in | 0 .../python_target_with_test_in_name/BUILD.out | 0 .../python_target_with_test_in_name/README.md | 0 .../python_target_with_test_in_name/WORKSPACE | 0 .../__init__.py | 0 .../gazelle_python.yaml | 0 .../real_test.py | 0 .../python_target_with_test_in_name/test.yaml | 0 .../test_reality.py | 0 .../testdata/relative_imports/BUILD.in | 0 .../testdata/relative_imports/BUILD.out | 0 .../testdata/relative_imports/README.md | 0 .../testdata/relative_imports/WORKSPACE | 0 .../testdata/relative_imports/__main__.py | 0 .../relative_imports/package1/module1.py | 0 .../relative_imports/package1/module2.py | 0 .../relative_imports/package2/BUILD.in | 0 .../relative_imports/package2/BUILD.out | 0 .../relative_imports/package2/__init__.py | 0 .../relative_imports/package2/module3.py | 0 .../relative_imports/package2/module4.py | 0 .../package2/subpackage1/module5.py | 0 .../testdata/relative_imports/test.yaml | 0 .../testdata/simple_binary/BUILD.in | 0 .../testdata/simple_binary/BUILD.out | 0 .../testdata/simple_binary/README.md | 0 .../testdata/simple_binary/WORKSPACE | 0 .../testdata/simple_binary/__main__.py | 0 .../testdata/simple_binary/test.yaml | 0 .../simple_binary_with_library/BUILD.in | 0 .../simple_binary_with_library/BUILD.out | 0 .../simple_binary_with_library/README.md | 0 .../simple_binary_with_library/WORKSPACE | 0 .../simple_binary_with_library/__init__.py | 0 .../simple_binary_with_library/__main__.py | 0 .../simple_binary_with_library/bar.py | 0 .../simple_binary_with_library/foo.py | 0 .../simple_binary_with_library/test.yaml | 0 .../testdata/simple_library/BUILD.in | 0 .../testdata/simple_library/BUILD.out | 0 .../testdata/simple_library/README.md | 0 .../testdata/simple_library/WORKSPACE | 0 .../testdata/simple_library/__init__.py | 0 .../testdata/simple_library/test.yaml | 0 .../simple_library_without_init/BUILD.in | 0 .../simple_library_without_init/BUILD.out | 0 .../simple_library_without_init/README.md | 0 .../simple_library_without_init/WORKSPACE | 0 .../simple_library_without_init/foo/BUILD.in | 0 .../simple_library_without_init/foo/BUILD.out | 0 .../simple_library_without_init/foo/foo.py | 0 .../simple_library_without_init/test.yaml | 0 .../testdata/simple_test/BUILD.in | 0 .../testdata/simple_test/BUILD.out | 0 .../testdata/simple_test/README.md | 0 .../testdata/simple_test/WORKSPACE | 0 .../testdata/simple_test/__init__.py | 0 .../testdata/simple_test/__test__.py | 0 .../{ => python}/testdata/simple_test/foo.py | 0 .../testdata/simple_test/test.yaml | 0 .../simple_test_with_conftest/BUILD.in | 0 .../simple_test_with_conftest/BUILD.out | 0 .../simple_test_with_conftest/README.md | 0 .../simple_test_with_conftest/WORKSPACE | 0 .../simple_test_with_conftest/__init__.py | 0 .../simple_test_with_conftest/__test__.py | 0 .../simple_test_with_conftest/conftest.py | 0 .../testdata/simple_test_with_conftest/foo.py | 0 .../simple_test_with_conftest/test.yaml | 0 .../testdata/subdir_sources/BUILD.in | 0 .../testdata/subdir_sources/BUILD.out | 0 .../testdata/subdir_sources/README.md | 0 .../testdata/subdir_sources/WORKSPACE | 0 .../testdata/subdir_sources/__main__.py | 0 .../testdata/subdir_sources/foo/BUILD.in | 0 .../testdata/subdir_sources/foo/BUILD.out | 0 .../testdata/subdir_sources/foo/__init__.py | 0 .../testdata/subdir_sources/foo/bar/bar.py | 0 .../testdata/subdir_sources/foo/baz/baz.py | 0 .../testdata/subdir_sources/foo/foo.py | 0 .../subdir_sources/foo/has_build/BUILD.in | 0 .../subdir_sources/foo/has_build/BUILD.out | 0 .../foo/has_build/python/my_module.py | 0 .../foo/has_build_bazel/BUILD.bazel.in | 0 .../foo/has_build_bazel/python/my_module.py | 0 .../subdir_sources/foo/has_init/BUILD.in | 0 .../subdir_sources/foo/has_init/BUILD.out | 0 .../subdir_sources/foo/has_init/__init__.py | 0 .../foo/has_init/python/my_module.py | 0 .../subdir_sources/foo/has_main/BUILD.in | 0 .../subdir_sources/foo/has_main/BUILD.out | 0 .../subdir_sources/foo/has_main/__main__.py | 0 .../foo/has_main/python/my_module.py | 0 .../subdir_sources/foo/has_test/BUILD.in | 0 .../subdir_sources/foo/has_test/BUILD.out | 0 .../subdir_sources/foo/has_test/__test__.py | 0 .../foo/has_test/python/my_module.py | 0 .../testdata/subdir_sources/one/BUILD.in | 0 .../testdata/subdir_sources/one/BUILD.out | 0 .../testdata/subdir_sources/one/__init__.py | 0 .../testdata/subdir_sources/one/two/BUILD.in | 0 .../testdata/subdir_sources/one/two/BUILD.out | 0 .../subdir_sources/one/two/__init__.py | 0 .../testdata/subdir_sources/one/two/three.py | 0 .../testdata/subdir_sources/test.yaml | 0 .../with_nested_import_statements/BUILD.in | 0 .../with_nested_import_statements/BUILD.out | 0 .../with_nested_import_statements/README.md | 0 .../with_nested_import_statements/WORKSPACE | 0 .../with_nested_import_statements/__init__.py | 0 .../gazelle_python.yaml | 0 .../with_nested_import_statements/test.yaml | 0 .../testdata/with_std_requirements/BUILD.in | 0 .../testdata/with_std_requirements/BUILD.out | 0 .../testdata/with_std_requirements/README.md | 0 .../testdata/with_std_requirements/WORKSPACE | 0 .../with_std_requirements/__init__.py | 0 .../testdata/with_std_requirements/test.yaml | 0 .../with_third_party_requirements/BUILD.in | 0 .../with_third_party_requirements/BUILD.out | 0 .../with_third_party_requirements/README.md | 0 .../with_third_party_requirements/WORKSPACE | 0 .../with_third_party_requirements/__init__.py | 0 .../with_third_party_requirements/__main__.py | 0 .../with_third_party_requirements/bar.py | 0 .../with_third_party_requirements/foo.py | 0 .../gazelle_python.yaml | 0 .../with_third_party_requirements/test.yaml | 0 .../BUILD.in | 0 .../BUILD.out | 0 .../README.md | 0 .../WORKSPACE | 0 .../__init__.py | 0 .../__main__.py | 0 .../bar.py | 0 .../gazelle_python.yaml | 0 .../test.yaml | 0 .../foo/has_build_bazel/BUILD.bazel.out | 8 -- 408 files changed, 95 insertions(+), 85 deletions(-) create mode 100644 gazelle/python/BUILD.bazel rename gazelle/{ => python}/configure.go (100%) rename gazelle/{ => python}/fix.go (100%) rename gazelle/{ => python}/generate.go (100%) rename gazelle/{ => python}/kinds.go (100%) rename gazelle/{ => python}/language.go (100%) rename gazelle/{ => python}/parse.py (100%) rename gazelle/{ => python}/parser.go (99%) rename gazelle/{ => python}/python_test.go (93%) rename gazelle/{ => python}/resolve.go (100%) rename gazelle/{ => python}/std_modules.go (96%) rename gazelle/{ => python}/std_modules.py (100%) rename gazelle/{ => python}/target.go (100%) rename gazelle/{ => python}/testdata/README.md (100%) rename gazelle/{ => python}/testdata/dependency_resolution_order/BUILD.in (100%) rename gazelle/{ => python}/testdata/dependency_resolution_order/BUILD.out (100%) rename gazelle/{ => python}/testdata/dependency_resolution_order/README.md (100%) rename gazelle/{ => python}/testdata/dependency_resolution_order/WORKSPACE (100%) rename gazelle/{ => python}/testdata/dependency_resolution_order/__init__.py (100%) rename gazelle/{ => python}/testdata/dependency_resolution_order/bar/BUILD.in (100%) rename gazelle/{ => python}/testdata/dependency_resolution_order/bar/BUILD.out (100%) rename gazelle/{ => python}/testdata/dependency_resolution_order/bar/__init__.py (100%) rename gazelle/{ => python}/testdata/dependency_resolution_order/baz/BUILD.in (100%) rename gazelle/{ => python}/testdata/dependency_resolution_order/baz/BUILD.out (100%) rename gazelle/{ => python}/testdata/dependency_resolution_order/baz/__init__.py (100%) rename gazelle/{ => python}/testdata/dependency_resolution_order/foo/BUILD.in (100%) rename gazelle/{ => python}/testdata/dependency_resolution_order/foo/BUILD.out (100%) rename gazelle/{ => python}/testdata/dependency_resolution_order/foo/__init__.py (100%) rename gazelle/{ => python}/testdata/dependency_resolution_order/gazelle_python.yaml (100%) rename gazelle/{ => python}/testdata/dependency_resolution_order/somewhere/bar/BUILD.in (100%) rename gazelle/{ => python}/testdata/dependency_resolution_order/somewhere/bar/BUILD.out (100%) rename gazelle/{ => python}/testdata/dependency_resolution_order/somewhere/bar/__init__.py (100%) rename gazelle/{ => python}/testdata/dependency_resolution_order/test.yaml (100%) rename gazelle/{ => python}/testdata/disable_import_statements_validation/BUILD.in (100%) rename gazelle/{ => python}/testdata/disable_import_statements_validation/BUILD.out (100%) rename gazelle/{ => python}/testdata/disable_import_statements_validation/README.md (100%) rename gazelle/{ => python}/testdata/disable_import_statements_validation/WORKSPACE (100%) rename gazelle/{ => python}/testdata/disable_import_statements_validation/__init__.py (100%) rename gazelle/{ => python}/testdata/disable_import_statements_validation/test.yaml (100%) rename gazelle/{ => python}/testdata/dont_rename_target/BUILD.in (100%) rename gazelle/{ => python}/testdata/dont_rename_target/BUILD.out (100%) rename gazelle/{ => python}/testdata/dont_rename_target/README.md (100%) rename gazelle/{ => python}/testdata/dont_rename_target/WORKSPACE (100%) rename gazelle/{ => python}/testdata/dont_rename_target/__init__.py (100%) rename gazelle/{ => python}/testdata/dont_rename_target/test.yaml (100%) rename gazelle/{ => python}/testdata/file_name_matches_import_statement/BUILD.in (100%) rename gazelle/{ => python}/testdata/file_name_matches_import_statement/BUILD.out (100%) rename gazelle/{ => python}/testdata/file_name_matches_import_statement/README.md (100%) rename gazelle/{ => python}/testdata/file_name_matches_import_statement/WORKSPACE (100%) rename gazelle/{ => python}/testdata/file_name_matches_import_statement/__init__.py (100%) rename gazelle/{ => python}/testdata/file_name_matches_import_statement/gazelle_python.yaml (100%) rename gazelle/{ => python}/testdata/file_name_matches_import_statement/rest_framework.py (100%) rename gazelle/{ => python}/testdata/file_name_matches_import_statement/test.yaml (100%) rename gazelle/{ => python}/testdata/first_party_dependencies/BUILD.in (100%) rename gazelle/{ => python}/testdata/first_party_dependencies/BUILD.out (100%) rename gazelle/{ => python}/testdata/first_party_dependencies/README.md (100%) rename gazelle/{ => python}/testdata/first_party_dependencies/WORKSPACE (100%) rename gazelle/{ => python}/testdata/first_party_dependencies/one/BUILD.in (100%) rename gazelle/{ => python}/testdata/first_party_dependencies/one/BUILD.out (100%) rename gazelle/{ => python}/testdata/first_party_dependencies/one/__main__.py (100%) rename gazelle/{ => python}/testdata/first_party_dependencies/one/bar/BUILD.in (100%) rename gazelle/{ => python}/testdata/first_party_dependencies/one/bar/BUILD.out (100%) rename gazelle/{ => python}/testdata/first_party_dependencies/one/bar/__init__.py (100%) rename gazelle/{ => python}/testdata/first_party_dependencies/one/bar/baz/BUILD.in (100%) rename gazelle/{ => python}/testdata/first_party_dependencies/one/bar/baz/BUILD.out (100%) rename gazelle/{ => python}/testdata/first_party_dependencies/one/bar/baz/__init__.py (100%) rename gazelle/{ => python}/testdata/first_party_dependencies/one/foo/BUILD.in (100%) rename gazelle/{ => python}/testdata/first_party_dependencies/one/foo/BUILD.out (100%) rename gazelle/{ => python}/testdata/first_party_dependencies/one/foo/__init__.py (100%) rename gazelle/{ => python}/testdata/first_party_dependencies/test.yaml (100%) rename gazelle/{ => python}/testdata/first_party_dependencies/three/BUILD.in (100%) rename gazelle/{ => python}/testdata/first_party_dependencies/three/BUILD.out (100%) rename gazelle/{ => python}/testdata/first_party_dependencies/three/__init__.py (100%) rename gazelle/{ => python}/testdata/first_party_dependencies/two/BUILD.in (100%) rename gazelle/{ => python}/testdata/first_party_dependencies/two/BUILD.out (100%) rename gazelle/{ => python}/testdata/first_party_dependencies/two/__init__.py (100%) rename gazelle/{ => python}/testdata/first_party_file_and_directory_modules/BUILD.in (100%) rename gazelle/{ => python}/testdata/first_party_file_and_directory_modules/BUILD.out (100%) rename gazelle/{ => python}/testdata/first_party_file_and_directory_modules/README.md (100%) rename gazelle/{ => python}/testdata/first_party_file_and_directory_modules/WORKSPACE (100%) rename gazelle/{ => python}/testdata/first_party_file_and_directory_modules/__main__.py (100%) rename gazelle/{ => python}/testdata/first_party_file_and_directory_modules/baz.py (100%) rename gazelle/{ => python}/testdata/first_party_file_and_directory_modules/foo.py (100%) rename gazelle/{ => python}/testdata/first_party_file_and_directory_modules/foo/BUILD.in (100%) rename gazelle/{ => python}/testdata/first_party_file_and_directory_modules/foo/BUILD.out (100%) rename gazelle/{ => python}/testdata/first_party_file_and_directory_modules/foo/__init__.py (100%) rename gazelle/{ => python}/testdata/first_party_file_and_directory_modules/foo/bar.py (100%) rename gazelle/{ => python}/testdata/first_party_file_and_directory_modules/one/BUILD.in (100%) rename gazelle/{ => python}/testdata/first_party_file_and_directory_modules/one/BUILD.out (100%) rename gazelle/{ => python}/testdata/first_party_file_and_directory_modules/one/__init__.py (100%) rename gazelle/{ => python}/testdata/first_party_file_and_directory_modules/one/two.py (100%) rename gazelle/{ => python}/testdata/first_party_file_and_directory_modules/test.yaml (100%) rename gazelle/{ => python}/testdata/first_party_file_and_directory_modules/undiscoverable/BUILD.in (100%) rename gazelle/{ => python}/testdata/first_party_file_and_directory_modules/undiscoverable/BUILD.out (100%) rename gazelle/{ => python}/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/BUILD.in (100%) rename gazelle/{ => python}/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/BUILD.out (100%) rename gazelle/{ => python}/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/__init__.py (100%) rename gazelle/{ => python}/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/module1.py (100%) rename gazelle/{ => python}/testdata/from_imports/BUILD.in (100%) rename gazelle/{ => python}/testdata/from_imports/BUILD.out (100%) rename gazelle/{ => python}/testdata/from_imports/README.md (100%) rename gazelle/{ => python}/testdata/from_imports/WORKSPACE (100%) rename gazelle/{ => python}/testdata/from_imports/foo/BUILD.in (100%) rename gazelle/{ => python}/testdata/from_imports/foo/BUILD.out (100%) rename gazelle/{ => python}/testdata/from_imports/foo/__init__.py (100%) rename gazelle/{ => python}/testdata/from_imports/foo/bar/BUILD.in (100%) rename gazelle/{ => python}/testdata/from_imports/foo/bar/BUILD.out (100%) rename gazelle/{ => python}/testdata/from_imports/foo/bar/__init__.py (100%) rename gazelle/{ => python}/testdata/from_imports/foo/bar/baz.py (100%) rename gazelle/{ => python}/testdata/from_imports/gazelle_python.yaml (100%) rename gazelle/{ => python}/testdata/from_imports/import_from_init_py/BUILD.in (100%) rename gazelle/{ => python}/testdata/from_imports/import_from_init_py/BUILD.out (100%) rename gazelle/{ => python}/testdata/from_imports/import_from_init_py/__init__.py (100%) rename gazelle/{ => python}/testdata/from_imports/import_from_multiple/BUILD.in (100%) rename gazelle/{ => python}/testdata/from_imports/import_from_multiple/BUILD.out (100%) rename gazelle/{ => python}/testdata/from_imports/import_from_multiple/__init__.py (100%) rename gazelle/{ => python}/testdata/from_imports/import_nested_file/BUILD.in (100%) rename gazelle/{ => python}/testdata/from_imports/import_nested_file/BUILD.out (100%) rename gazelle/{ => python}/testdata/from_imports/import_nested_file/__init__.py (100%) rename gazelle/{ => python}/testdata/from_imports/import_nested_module/BUILD.in (100%) rename gazelle/{ => python}/testdata/from_imports/import_nested_module/BUILD.out (100%) rename gazelle/{ => python}/testdata/from_imports/import_nested_module/__init__.py (100%) rename gazelle/{ => python}/testdata/from_imports/import_nested_var/BUILD.in (100%) rename gazelle/{ => python}/testdata/from_imports/import_nested_var/BUILD.out (100%) rename gazelle/{ => python}/testdata/from_imports/import_nested_var/__init__.py (100%) rename gazelle/{ => python}/testdata/from_imports/import_top_level_var/BUILD.in (100%) rename gazelle/{ => python}/testdata/from_imports/import_top_level_var/BUILD.out (100%) rename gazelle/{ => python}/testdata/from_imports/import_top_level_var/__init__.py (100%) rename gazelle/{ => python}/testdata/from_imports/std_module/BUILD.in (100%) rename gazelle/{ => python}/testdata/from_imports/std_module/BUILD.out (100%) rename gazelle/{ => python}/testdata/from_imports/std_module/__init__.py (100%) rename gazelle/{ => python}/testdata/from_imports/test.yaml (100%) rename gazelle/{ => python}/testdata/generated_test_entrypoint/BUILD.in (100%) rename gazelle/{ => python}/testdata/generated_test_entrypoint/BUILD.out (100%) rename gazelle/{ => python}/testdata/generated_test_entrypoint/README.md (100%) rename gazelle/{ => python}/testdata/generated_test_entrypoint/WORKSPACE (100%) rename gazelle/{ => python}/testdata/generated_test_entrypoint/__init__.py (100%) rename gazelle/{ => python}/testdata/generated_test_entrypoint/foo.py (100%) rename gazelle/{ => python}/testdata/generated_test_entrypoint/test.yaml (100%) rename gazelle/{ => python}/testdata/ignored_invalid_imported_module/BUILD.in (100%) rename gazelle/{ => python}/testdata/ignored_invalid_imported_module/BUILD.out (100%) rename gazelle/{ => python}/testdata/ignored_invalid_imported_module/README.md (100%) rename gazelle/{ => python}/testdata/ignored_invalid_imported_module/WORKSPACE (100%) rename gazelle/{ => python}/testdata/ignored_invalid_imported_module/__init__.py (100%) rename gazelle/{ => python}/testdata/ignored_invalid_imported_module/gazelle_python.yaml (100%) rename gazelle/{ => python}/testdata/ignored_invalid_imported_module/test.yaml (100%) rename gazelle/{ => python}/testdata/invalid_annotation/BUILD.in (100%) rename gazelle/{ => python}/testdata/invalid_annotation/BUILD.out (100%) rename gazelle/{ => python}/testdata/invalid_annotation/README.md (100%) rename gazelle/{ => python}/testdata/invalid_annotation/WORKSPACE (100%) rename gazelle/{ => python}/testdata/invalid_annotation/__init__.py (100%) rename gazelle/{ => python}/testdata/invalid_annotation/test.yaml (100%) rename gazelle/{ => python}/testdata/invalid_imported_module/BUILD.in (100%) rename gazelle/{ => python}/testdata/invalid_imported_module/BUILD.out (100%) rename gazelle/{ => python}/testdata/invalid_imported_module/README.md (100%) rename gazelle/{ => python}/testdata/invalid_imported_module/WORKSPACE (100%) rename gazelle/{ => python}/testdata/invalid_imported_module/__init__.py (100%) rename gazelle/{ => python}/testdata/invalid_imported_module/test.yaml (100%) rename gazelle/{ => python}/testdata/monorepo/BUILD.in (100%) rename gazelle/{ => python}/testdata/monorepo/BUILD.out (100%) rename gazelle/{ => python}/testdata/monorepo/README.md (100%) rename gazelle/{ => python}/testdata/monorepo/WORKSPACE (100%) rename gazelle/{ => python}/testdata/monorepo/coarse_grained/BUILD.in (100%) rename gazelle/{ => python}/testdata/monorepo/coarse_grained/BUILD.out (100%) rename gazelle/{ => python}/testdata/monorepo/coarse_grained/__init__.py (100%) rename gazelle/{ => python}/testdata/monorepo/coarse_grained/_boundary/BUILD.in (100%) rename gazelle/{ => python}/testdata/monorepo/coarse_grained/_boundary/BUILD.out (100%) rename gazelle/{ => python}/testdata/monorepo/coarse_grained/_boundary/README.md (100%) rename gazelle/{ => python}/testdata/monorepo/coarse_grained/_boundary/__init__.py (100%) rename gazelle/{ => python}/testdata/monorepo/coarse_grained/bar/__init__.py (100%) rename gazelle/{ => python}/testdata/monorepo/coarse_grained/bar/baz/__init__.py (100%) rename gazelle/{ => python}/testdata/monorepo/coarse_grained/bar/baz/first_excluded.py (100%) rename gazelle/{ => python}/testdata/monorepo/coarse_grained/bar/baz/hue.py (100%) rename gazelle/{ => python}/testdata/monorepo/coarse_grained/bar/baz/second_excluded.py (100%) rename gazelle/{ => python}/testdata/monorepo/coarse_grained/foo/__init__.py (100%) rename gazelle/{ => python}/testdata/monorepo/gazelle_python.yaml (100%) rename gazelle/{ => python}/testdata/monorepo/one/BUILD.in (100%) rename gazelle/{ => python}/testdata/monorepo/one/BUILD.out (100%) rename gazelle/{ => python}/testdata/monorepo/one/__main__.py (100%) rename gazelle/{ => python}/testdata/monorepo/one/bar/BUILD.in (100%) rename gazelle/{ => python}/testdata/monorepo/one/bar/BUILD.out (100%) rename gazelle/{ => python}/testdata/monorepo/one/bar/__init__.py (100%) rename gazelle/{ => python}/testdata/monorepo/one/bar/baz/BUILD.in (100%) rename gazelle/{ => python}/testdata/monorepo/one/bar/baz/BUILD.out (100%) rename gazelle/{ => python}/testdata/monorepo/one/bar/baz/__init__.py (100%) rename gazelle/{ => python}/testdata/monorepo/one/foo/BUILD.in (100%) rename gazelle/{ => python}/testdata/monorepo/one/foo/BUILD.out (100%) rename gazelle/{ => python}/testdata/monorepo/one/foo/__init__.py (100%) rename gazelle/{ => python}/testdata/monorepo/one/gazelle_python.yaml (100%) rename gazelle/{ => python}/testdata/monorepo/test.yaml (100%) rename gazelle/{ => python}/testdata/monorepo/three/BUILD.in (100%) rename gazelle/{ => python}/testdata/monorepo/three/BUILD.out (100%) rename gazelle/{ => python}/testdata/monorepo/three/__init__.py (100%) rename gazelle/{ => python}/testdata/monorepo/three/gazelle_python.yaml (100%) rename gazelle/{ => python}/testdata/monorepo/two/BUILD.in (100%) rename gazelle/{ => python}/testdata/monorepo/two/BUILD.out (100%) rename gazelle/{ => python}/testdata/monorepo/two/__init__.py (100%) rename gazelle/{ => python}/testdata/monorepo/two/gazelle_python.yaml (100%) rename gazelle/{ => python}/testdata/monorepo/wont_generate/BUILD.in (100%) rename gazelle/{ => python}/testdata/monorepo/wont_generate/BUILD.out (100%) rename gazelle/{ => python}/testdata/monorepo/wont_generate/__main__.py (100%) rename gazelle/{ => python}/testdata/monorepo/wont_generate/bar/BUILD.in (100%) rename gazelle/{ => python}/testdata/monorepo/wont_generate/bar/BUILD.out (100%) rename gazelle/{ => python}/testdata/monorepo/wont_generate/bar/__init__.py (100%) rename gazelle/{ => python}/testdata/monorepo/wont_generate/bar/baz/BUILD.in (100%) rename gazelle/{ => python}/testdata/monorepo/wont_generate/bar/baz/BUILD.out (100%) rename gazelle/{ => python}/testdata/monorepo/wont_generate/bar/baz/__init__.py (100%) rename gazelle/{ => python}/testdata/monorepo/wont_generate/foo/BUILD.in (100%) rename gazelle/{ => python}/testdata/monorepo/wont_generate/foo/BUILD.out (100%) rename gazelle/{ => python}/testdata/monorepo/wont_generate/foo/__init__.py (100%) rename gazelle/{ => python}/testdata/naming_convention/BUILD.in (100%) rename gazelle/{ => python}/testdata/naming_convention/BUILD.out (100%) rename gazelle/{ => python}/testdata/naming_convention/README.md (100%) rename gazelle/{ => python}/testdata/naming_convention/WORKSPACE (100%) rename gazelle/{ => python}/testdata/naming_convention/__init__.py (100%) rename gazelle/{ => python}/testdata/naming_convention/__main__.py (100%) rename gazelle/{ => python}/testdata/naming_convention/__test__.py (100%) rename gazelle/{ => python}/testdata/naming_convention/dont_rename/BUILD.in (100%) rename gazelle/{ => python}/testdata/naming_convention/dont_rename/BUILD.out (100%) rename gazelle/{ => python}/testdata/naming_convention/dont_rename/__init__.py (100%) rename gazelle/{ => python}/testdata/naming_convention/dont_rename/__main__.py (100%) rename gazelle/{ => python}/testdata/naming_convention/dont_rename/__test__.py (100%) rename gazelle/{ => python}/testdata/naming_convention/resolve_conflict/BUILD.in (100%) rename gazelle/{ => python}/testdata/naming_convention/resolve_conflict/BUILD.out (100%) rename gazelle/{ => python}/testdata/naming_convention/resolve_conflict/__init__.py (100%) rename gazelle/{ => python}/testdata/naming_convention/resolve_conflict/__main__.py (100%) rename gazelle/{ => python}/testdata/naming_convention/resolve_conflict/__test__.py (100%) rename gazelle/{ => python}/testdata/naming_convention/test.yaml (100%) rename gazelle/{ => python}/testdata/naming_convention_binary_fail/BUILD.in (100%) rename gazelle/{ => python}/testdata/naming_convention_binary_fail/BUILD.out (100%) rename gazelle/{ => python}/testdata/naming_convention_binary_fail/README.md (100%) rename gazelle/{ => python}/testdata/naming_convention_binary_fail/WORKSPACE (100%) rename gazelle/{ => python}/testdata/naming_convention_binary_fail/__main__.py (100%) rename gazelle/{ => python}/testdata/naming_convention_binary_fail/test.yaml (100%) rename gazelle/{ => python}/testdata/naming_convention_library_fail/BUILD.in (100%) rename gazelle/{ => python}/testdata/naming_convention_library_fail/BUILD.out (100%) rename gazelle/{ => python}/testdata/naming_convention_library_fail/README.md (100%) rename gazelle/{ => python}/testdata/naming_convention_library_fail/WORKSPACE (100%) rename gazelle/{ => python}/testdata/naming_convention_library_fail/__init__.py (100%) rename gazelle/{ => python}/testdata/naming_convention_library_fail/test.yaml (100%) rename gazelle/{ => python}/testdata/naming_convention_test_fail/BUILD.in (100%) rename gazelle/{ => python}/testdata/naming_convention_test_fail/BUILD.out (100%) rename gazelle/{ => python}/testdata/naming_convention_test_fail/README.md (100%) rename gazelle/{ => python}/testdata/naming_convention_test_fail/WORKSPACE (100%) rename gazelle/{ => python}/testdata/naming_convention_test_fail/__test__.py (100%) rename gazelle/{ => python}/testdata/naming_convention_test_fail/test.yaml (100%) rename gazelle/{ => python}/testdata/python_ignore_dependencies_directive/BUILD.in (100%) rename gazelle/{ => python}/testdata/python_ignore_dependencies_directive/BUILD.out (100%) rename gazelle/{ => python}/testdata/python_ignore_dependencies_directive/README.md (100%) rename gazelle/{ => python}/testdata/python_ignore_dependencies_directive/WORKSPACE (100%) rename gazelle/{ => python}/testdata/python_ignore_dependencies_directive/__init__.py (100%) rename gazelle/{ => python}/testdata/python_ignore_dependencies_directive/gazelle_python.yaml (100%) rename gazelle/{ => python}/testdata/python_ignore_dependencies_directive/test.yaml (100%) rename gazelle/{ => python}/testdata/python_ignore_files_directive/BUILD.in (100%) rename gazelle/{ => python}/testdata/python_ignore_files_directive/BUILD.out (100%) rename gazelle/{ => python}/testdata/python_ignore_files_directive/README.md (100%) rename gazelle/{ => python}/testdata/python_ignore_files_directive/WORKSPACE (100%) rename gazelle/{ => python}/testdata/python_ignore_files_directive/__init__.py (100%) rename gazelle/{ => python}/testdata/python_ignore_files_directive/bar/BUILD.in (100%) rename gazelle/{ => python}/testdata/python_ignore_files_directive/bar/BUILD.out (100%) rename gazelle/{ => python}/testdata/python_ignore_files_directive/bar/baz.py (100%) rename gazelle/{ => python}/testdata/python_ignore_files_directive/bar/some_other.py (100%) rename gazelle/{ => python}/testdata/python_ignore_files_directive/foo/BUILD.in (100%) rename gazelle/{ => python}/testdata/python_ignore_files_directive/foo/BUILD.out (100%) rename gazelle/{ => python}/testdata/python_ignore_files_directive/foo/baz.py (100%) rename gazelle/{ => python}/testdata/python_ignore_files_directive/setup.py (100%) rename gazelle/{ => python}/testdata/python_ignore_files_directive/some_other.py (100%) rename gazelle/{ => python}/testdata/python_ignore_files_directive/test.yaml (100%) rename gazelle/{ => python}/testdata/python_target_with_test_in_name/BUILD.in (100%) rename gazelle/{ => python}/testdata/python_target_with_test_in_name/BUILD.out (100%) rename gazelle/{ => python}/testdata/python_target_with_test_in_name/README.md (100%) rename gazelle/{ => python}/testdata/python_target_with_test_in_name/WORKSPACE (100%) rename gazelle/{ => python}/testdata/python_target_with_test_in_name/__init__.py (100%) rename gazelle/{ => python}/testdata/python_target_with_test_in_name/gazelle_python.yaml (100%) rename gazelle/{ => python}/testdata/python_target_with_test_in_name/real_test.py (100%) rename gazelle/{ => python}/testdata/python_target_with_test_in_name/test.yaml (100%) rename gazelle/{ => python}/testdata/python_target_with_test_in_name/test_reality.py (100%) rename gazelle/{ => python}/testdata/relative_imports/BUILD.in (100%) rename gazelle/{ => python}/testdata/relative_imports/BUILD.out (100%) rename gazelle/{ => python}/testdata/relative_imports/README.md (100%) rename gazelle/{ => python}/testdata/relative_imports/WORKSPACE (100%) rename gazelle/{ => python}/testdata/relative_imports/__main__.py (100%) rename gazelle/{ => python}/testdata/relative_imports/package1/module1.py (100%) rename gazelle/{ => python}/testdata/relative_imports/package1/module2.py (100%) rename gazelle/{ => python}/testdata/relative_imports/package2/BUILD.in (100%) rename gazelle/{ => python}/testdata/relative_imports/package2/BUILD.out (100%) rename gazelle/{ => python}/testdata/relative_imports/package2/__init__.py (100%) rename gazelle/{ => python}/testdata/relative_imports/package2/module3.py (100%) rename gazelle/{ => python}/testdata/relative_imports/package2/module4.py (100%) rename gazelle/{ => python}/testdata/relative_imports/package2/subpackage1/module5.py (100%) rename gazelle/{ => python}/testdata/relative_imports/test.yaml (100%) rename gazelle/{ => python}/testdata/simple_binary/BUILD.in (100%) rename gazelle/{ => python}/testdata/simple_binary/BUILD.out (100%) rename gazelle/{ => python}/testdata/simple_binary/README.md (100%) rename gazelle/{ => python}/testdata/simple_binary/WORKSPACE (100%) rename gazelle/{ => python}/testdata/simple_binary/__main__.py (100%) rename gazelle/{ => python}/testdata/simple_binary/test.yaml (100%) rename gazelle/{ => python}/testdata/simple_binary_with_library/BUILD.in (100%) rename gazelle/{ => python}/testdata/simple_binary_with_library/BUILD.out (100%) rename gazelle/{ => python}/testdata/simple_binary_with_library/README.md (100%) rename gazelle/{ => python}/testdata/simple_binary_with_library/WORKSPACE (100%) rename gazelle/{ => python}/testdata/simple_binary_with_library/__init__.py (100%) rename gazelle/{ => python}/testdata/simple_binary_with_library/__main__.py (100%) rename gazelle/{ => python}/testdata/simple_binary_with_library/bar.py (100%) rename gazelle/{ => python}/testdata/simple_binary_with_library/foo.py (100%) rename gazelle/{ => python}/testdata/simple_binary_with_library/test.yaml (100%) rename gazelle/{ => python}/testdata/simple_library/BUILD.in (100%) rename gazelle/{ => python}/testdata/simple_library/BUILD.out (100%) rename gazelle/{ => python}/testdata/simple_library/README.md (100%) rename gazelle/{ => python}/testdata/simple_library/WORKSPACE (100%) rename gazelle/{ => python}/testdata/simple_library/__init__.py (100%) rename gazelle/{ => python}/testdata/simple_library/test.yaml (100%) rename gazelle/{ => python}/testdata/simple_library_without_init/BUILD.in (100%) rename gazelle/{ => python}/testdata/simple_library_without_init/BUILD.out (100%) rename gazelle/{ => python}/testdata/simple_library_without_init/README.md (100%) rename gazelle/{ => python}/testdata/simple_library_without_init/WORKSPACE (100%) rename gazelle/{ => python}/testdata/simple_library_without_init/foo/BUILD.in (100%) rename gazelle/{ => python}/testdata/simple_library_without_init/foo/BUILD.out (100%) rename gazelle/{ => python}/testdata/simple_library_without_init/foo/foo.py (100%) rename gazelle/{ => python}/testdata/simple_library_without_init/test.yaml (100%) rename gazelle/{ => python}/testdata/simple_test/BUILD.in (100%) rename gazelle/{ => python}/testdata/simple_test/BUILD.out (100%) rename gazelle/{ => python}/testdata/simple_test/README.md (100%) rename gazelle/{ => python}/testdata/simple_test/WORKSPACE (100%) rename gazelle/{ => python}/testdata/simple_test/__init__.py (100%) rename gazelle/{ => python}/testdata/simple_test/__test__.py (100%) rename gazelle/{ => python}/testdata/simple_test/foo.py (100%) rename gazelle/{ => python}/testdata/simple_test/test.yaml (100%) rename gazelle/{ => python}/testdata/simple_test_with_conftest/BUILD.in (100%) rename gazelle/{ => python}/testdata/simple_test_with_conftest/BUILD.out (100%) rename gazelle/{ => python}/testdata/simple_test_with_conftest/README.md (100%) rename gazelle/{ => python}/testdata/simple_test_with_conftest/WORKSPACE (100%) rename gazelle/{ => python}/testdata/simple_test_with_conftest/__init__.py (100%) rename gazelle/{ => python}/testdata/simple_test_with_conftest/__test__.py (100%) rename gazelle/{ => python}/testdata/simple_test_with_conftest/conftest.py (100%) rename gazelle/{ => python}/testdata/simple_test_with_conftest/foo.py (100%) rename gazelle/{ => python}/testdata/simple_test_with_conftest/test.yaml (100%) rename gazelle/{ => python}/testdata/subdir_sources/BUILD.in (100%) rename gazelle/{ => python}/testdata/subdir_sources/BUILD.out (100%) rename gazelle/{ => python}/testdata/subdir_sources/README.md (100%) rename gazelle/{ => python}/testdata/subdir_sources/WORKSPACE (100%) rename gazelle/{ => python}/testdata/subdir_sources/__main__.py (100%) rename gazelle/{ => python}/testdata/subdir_sources/foo/BUILD.in (100%) rename gazelle/{ => python}/testdata/subdir_sources/foo/BUILD.out (100%) rename gazelle/{ => python}/testdata/subdir_sources/foo/__init__.py (100%) rename gazelle/{ => python}/testdata/subdir_sources/foo/bar/bar.py (100%) rename gazelle/{ => python}/testdata/subdir_sources/foo/baz/baz.py (100%) rename gazelle/{ => python}/testdata/subdir_sources/foo/foo.py (100%) rename gazelle/{ => python}/testdata/subdir_sources/foo/has_build/BUILD.in (100%) rename gazelle/{ => python}/testdata/subdir_sources/foo/has_build/BUILD.out (100%) rename gazelle/{ => python}/testdata/subdir_sources/foo/has_build/python/my_module.py (100%) rename gazelle/{ => python}/testdata/subdir_sources/foo/has_build_bazel/BUILD.bazel.in (100%) rename gazelle/{ => python}/testdata/subdir_sources/foo/has_build_bazel/python/my_module.py (100%) rename gazelle/{ => python}/testdata/subdir_sources/foo/has_init/BUILD.in (100%) rename gazelle/{ => python}/testdata/subdir_sources/foo/has_init/BUILD.out (100%) rename gazelle/{ => python}/testdata/subdir_sources/foo/has_init/__init__.py (100%) rename gazelle/{ => python}/testdata/subdir_sources/foo/has_init/python/my_module.py (100%) rename gazelle/{ => python}/testdata/subdir_sources/foo/has_main/BUILD.in (100%) rename gazelle/{ => python}/testdata/subdir_sources/foo/has_main/BUILD.out (100%) rename gazelle/{ => python}/testdata/subdir_sources/foo/has_main/__main__.py (100%) rename gazelle/{ => python}/testdata/subdir_sources/foo/has_main/python/my_module.py (100%) rename gazelle/{ => python}/testdata/subdir_sources/foo/has_test/BUILD.in (100%) rename gazelle/{ => python}/testdata/subdir_sources/foo/has_test/BUILD.out (100%) rename gazelle/{ => python}/testdata/subdir_sources/foo/has_test/__test__.py (100%) rename gazelle/{ => python}/testdata/subdir_sources/foo/has_test/python/my_module.py (100%) rename gazelle/{ => python}/testdata/subdir_sources/one/BUILD.in (100%) rename gazelle/{ => python}/testdata/subdir_sources/one/BUILD.out (100%) rename gazelle/{ => python}/testdata/subdir_sources/one/__init__.py (100%) rename gazelle/{ => python}/testdata/subdir_sources/one/two/BUILD.in (100%) rename gazelle/{ => python}/testdata/subdir_sources/one/two/BUILD.out (100%) rename gazelle/{ => python}/testdata/subdir_sources/one/two/__init__.py (100%) rename gazelle/{ => python}/testdata/subdir_sources/one/two/three.py (100%) rename gazelle/{ => python}/testdata/subdir_sources/test.yaml (100%) rename gazelle/{ => python}/testdata/with_nested_import_statements/BUILD.in (100%) rename gazelle/{ => python}/testdata/with_nested_import_statements/BUILD.out (100%) rename gazelle/{ => python}/testdata/with_nested_import_statements/README.md (100%) rename gazelle/{ => python}/testdata/with_nested_import_statements/WORKSPACE (100%) rename gazelle/{ => python}/testdata/with_nested_import_statements/__init__.py (100%) rename gazelle/{ => python}/testdata/with_nested_import_statements/gazelle_python.yaml (100%) rename gazelle/{ => python}/testdata/with_nested_import_statements/test.yaml (100%) rename gazelle/{ => python}/testdata/with_std_requirements/BUILD.in (100%) rename gazelle/{ => python}/testdata/with_std_requirements/BUILD.out (100%) rename gazelle/{ => python}/testdata/with_std_requirements/README.md (100%) rename gazelle/{ => python}/testdata/with_std_requirements/WORKSPACE (100%) rename gazelle/{ => python}/testdata/with_std_requirements/__init__.py (100%) rename gazelle/{ => python}/testdata/with_std_requirements/test.yaml (100%) rename gazelle/{ => python}/testdata/with_third_party_requirements/BUILD.in (100%) rename gazelle/{ => python}/testdata/with_third_party_requirements/BUILD.out (100%) rename gazelle/{ => python}/testdata/with_third_party_requirements/README.md (100%) rename gazelle/{ => python}/testdata/with_third_party_requirements/WORKSPACE (100%) rename gazelle/{ => python}/testdata/with_third_party_requirements/__init__.py (100%) rename gazelle/{ => python}/testdata/with_third_party_requirements/__main__.py (100%) rename gazelle/{ => python}/testdata/with_third_party_requirements/bar.py (100%) rename gazelle/{ => python}/testdata/with_third_party_requirements/foo.py (100%) rename gazelle/{ => python}/testdata/with_third_party_requirements/gazelle_python.yaml (100%) rename gazelle/{ => python}/testdata/with_third_party_requirements/test.yaml (100%) rename gazelle/{ => python}/testdata/with_third_party_requirements_from_imports/BUILD.in (100%) rename gazelle/{ => python}/testdata/with_third_party_requirements_from_imports/BUILD.out (100%) rename gazelle/{ => python}/testdata/with_third_party_requirements_from_imports/README.md (100%) rename gazelle/{ => python}/testdata/with_third_party_requirements_from_imports/WORKSPACE (100%) rename gazelle/{ => python}/testdata/with_third_party_requirements_from_imports/__init__.py (100%) rename gazelle/{ => python}/testdata/with_third_party_requirements_from_imports/__main__.py (100%) rename gazelle/{ => python}/testdata/with_third_party_requirements_from_imports/bar.py (100%) rename gazelle/{ => python}/testdata/with_third_party_requirements_from_imports/gazelle_python.yaml (100%) rename gazelle/{ => python}/testdata/with_third_party_requirements_from_imports/test.yaml (100%) delete mode 100644 gazelle/testdata/subdir_sources/foo/has_build_bazel/BUILD.bazel.out diff --git a/gazelle/BUILD.bazel b/gazelle/BUILD.bazel index 303b496364..8a67e1a2f9 100644 --- a/gazelle/BUILD.bazel +++ b/gazelle/BUILD.bazel @@ -1,76 +1,12 @@ -load("@bazel_gazelle//:def.bzl", "gazelle_binary") -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") -load("@rules_python//python:defs.bzl", "py_binary") - -go_library( +alias( name = "gazelle", - srcs = [ - "configure.go", - "fix.go", - "generate.go", - "kinds.go", - "language.go", - "parser.go", - "resolve.go", - "std_modules.go", - "target.go", - ], - data = [ - ":parse", - ":std_modules", - ], - importpath = "github.com/bazelbuild/rules_python/gazelle", - visibility = ["//visibility:public"], - deps = [ - "//gazelle/manifest", - "//gazelle/pythonconfig", - "@bazel_gazelle//config:go_default_library", - "@bazel_gazelle//label:go_default_library", - "@bazel_gazelle//language:go_default_library", - "@bazel_gazelle//repo:go_default_library", - "@bazel_gazelle//resolve:go_default_library", - "@bazel_gazelle//rule:go_default_library", - "@com_github_bazelbuild_buildtools//build:go_default_library", - "@com_github_bmatcuk_doublestar//:doublestar", - "@com_github_emirpasic_gods//lists/singlylinkedlist", - "@com_github_emirpasic_gods//sets/treeset", - "@com_github_emirpasic_gods//utils", - "@com_github_google_uuid//:uuid", - "@io_bazel_rules_go//go/tools/bazel:go_default_library", - ], -) - -py_binary( - name = "parse", - srcs = ["parse.py"], + actual = "//gazelle/python", visibility = ["//visibility:public"], ) -py_binary( - name = "std_modules", - srcs = ["std_modules.py"], - visibility = ["//visibility:public"], -) - -go_test( - name = "gazelle_test", - srcs = ["python_test.go"], - data = [ - ":gazelle_python_binary", - ":parse", - ":std_modules", - ] + glob(["testdata/**"]), - deps = [ - "@bazel_gazelle//testtools:go_default_library", - "@com_github_emirpasic_gods//lists/singlylinkedlist", - "@com_github_ghodss_yaml//:yaml", - "@io_bazel_rules_go//go/tools/bazel:go_default_library", - ], -) - -gazelle_binary( +alias( name = "gazelle_python_binary", - languages = ["//gazelle"], + actual = "//gazelle/python:gazelle_binary", visibility = ["//visibility:public"], ) @@ -79,6 +15,7 @@ filegroup( srcs = glob(["**"]) + [ "//gazelle/manifest:distribution", "//gazelle/modules_mapping:distribution", + "//gazelle/python:distribution", "//gazelle/pythonconfig:distribution", ], visibility = ["//:__pkg__"], diff --git a/gazelle/def.bzl b/gazelle/def.bzl index a402fc74c4..aa6c23eb76 100644 --- a/gazelle/def.bzl +++ b/gazelle/def.bzl @@ -2,6 +2,6 @@ """ GAZELLE_PYTHON_RUNTIME_DEPS = [ - "@rules_python//gazelle:parse", - "@rules_python//gazelle:std_modules", + "@rules_python//gazelle/python:parse", + "@rules_python//gazelle/python:std_modules", ] diff --git a/gazelle/python/BUILD.bazel b/gazelle/python/BUILD.bazel new file mode 100644 index 0000000000..659f6eb72b --- /dev/null +++ b/gazelle/python/BUILD.bazel @@ -0,0 +1,81 @@ +load("@bazel_gazelle//:def.bzl", "gazelle_binary") +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") +load("@rules_python//python:defs.bzl", "py_binary") + +go_library( + name = "python", + srcs = [ + "configure.go", + "fix.go", + "generate.go", + "kinds.go", + "language.go", + "parser.go", + "resolve.go", + "std_modules.go", + "target.go", + ], + data = [ + ":parse", + ":std_modules", + ], + importpath = "github.com/bazelbuild/rules_python/gazelle/python", + visibility = ["//visibility:public"], + deps = [ + "//gazelle/manifest", + "//gazelle/pythonconfig", + "@bazel_gazelle//config:go_default_library", + "@bazel_gazelle//label:go_default_library", + "@bazel_gazelle//language:go_default_library", + "@bazel_gazelle//repo:go_default_library", + "@bazel_gazelle//resolve:go_default_library", + "@bazel_gazelle//rule:go_default_library", + "@com_github_bazelbuild_buildtools//build:go_default_library", + "@com_github_bmatcuk_doublestar//:doublestar", + "@com_github_emirpasic_gods//lists/singlylinkedlist", + "@com_github_emirpasic_gods//sets/treeset", + "@com_github_emirpasic_gods//utils", + "@com_github_google_uuid//:uuid", + "@io_bazel_rules_go//go/tools/bazel:go_default_library", + ], +) + +py_binary( + name = "parse", + srcs = ["parse.py"], + visibility = ["//visibility:public"], +) + +py_binary( + name = "std_modules", + srcs = ["std_modules.py"], + visibility = ["//visibility:public"], +) + +go_test( + name = "python_test", + srcs = ["python_test.go"], + data = [ + ":gazelle_binary", + ":parse", + ":std_modules", + ] + glob(["testdata/**"]), + deps = [ + "@bazel_gazelle//testtools:go_default_library", + "@com_github_emirpasic_gods//lists/singlylinkedlist", + "@com_github_ghodss_yaml//:yaml", + "@io_bazel_rules_go//go/tools/bazel:go_default_library", + ], +) + +gazelle_binary( + name = "gazelle_binary", + languages = [":python"], + visibility = ["//visibility:public"], +) + +filegroup( + name = "distribution", + srcs = glob(["**"]), + visibility = ["//gazelle:__pkg__"], +) diff --git a/gazelle/configure.go b/gazelle/python/configure.go similarity index 100% rename from gazelle/configure.go rename to gazelle/python/configure.go diff --git a/gazelle/fix.go b/gazelle/python/fix.go similarity index 100% rename from gazelle/fix.go rename to gazelle/python/fix.go diff --git a/gazelle/generate.go b/gazelle/python/generate.go similarity index 100% rename from gazelle/generate.go rename to gazelle/python/generate.go diff --git a/gazelle/kinds.go b/gazelle/python/kinds.go similarity index 100% rename from gazelle/kinds.go rename to gazelle/python/kinds.go diff --git a/gazelle/language.go b/gazelle/python/language.go similarity index 100% rename from gazelle/language.go rename to gazelle/python/language.go diff --git a/gazelle/parse.py b/gazelle/python/parse.py similarity index 100% rename from gazelle/parse.py rename to gazelle/python/parse.py diff --git a/gazelle/parser.go b/gazelle/python/parser.go similarity index 99% rename from gazelle/parser.go rename to gazelle/python/parser.go index 6158d38ecf..df4a0fcbbc 100644 --- a/gazelle/parser.go +++ b/gazelle/python/parser.go @@ -25,7 +25,7 @@ var ( ) func init() { - parseScriptRunfile, err := bazel.Runfile("gazelle/parse") + parseScriptRunfile, err := bazel.Runfile("gazelle/python/parse") if err != nil { log.Printf("failed to initialize parser: %v\n", err) os.Exit(1) diff --git a/gazelle/python_test.go b/gazelle/python/python_test.go similarity index 93% rename from gazelle/python_test.go rename to gazelle/python/python_test.go index 4fac7c003a..6622bcbf23 100644 --- a/gazelle/python_test.go +++ b/gazelle/python/python_test.go @@ -38,9 +38,9 @@ import ( ) const ( - extensionDir = "gazelle/" - testDataPath = extensionDir + "testdata/" - gazelleBinaryName = "gazelle_python_binary" + extensionDir = "gazelle" + string(os.PathSeparator) + "python" + string(os.PathSeparator) + testDataPath = extensionDir + "testdata" + string(os.PathSeparator) + gazelleBinaryName = "gazelle_binary" ) var gazellePath = mustFindGazelle() @@ -55,7 +55,7 @@ func TestGazelleBinary(t *testing.T) { for _, f := range runfiles { if strings.HasPrefix(f.ShortPath, testDataPath) { relativePath := strings.TrimPrefix(f.ShortPath, testDataPath) - parts := strings.SplitN(relativePath, "/", 2) + parts := strings.SplitN(relativePath, string(os.PathSeparator), 2) if len(parts) < 2 { // This file is not a part of a testcase since it must be in a dir that // is the test case and then have a path inside of that. @@ -82,7 +82,7 @@ func testPath(t *testing.T, name string, files []bazel.RunfileEntry) { var config *testYAML for _, f := range files { path := f.Path - trim := testDataPath + name + "/" + trim := filepath.Join(testDataPath, name) + string(os.PathSeparator) shortPath := strings.TrimPrefix(f.ShortPath, trim) info, err := os.Stat(path) if err != nil { diff --git a/gazelle/resolve.go b/gazelle/python/resolve.go similarity index 100% rename from gazelle/resolve.go rename to gazelle/python/resolve.go diff --git a/gazelle/std_modules.go b/gazelle/python/std_modules.go similarity index 96% rename from gazelle/std_modules.go rename to gazelle/python/std_modules.go index e784a2d301..9ef1ecbd94 100644 --- a/gazelle/std_modules.go +++ b/gazelle/python/std_modules.go @@ -26,7 +26,7 @@ var ( func init() { stdModulesSeen = make(map[string]struct{}) - stdModulesScriptRunfile, err := bazel.Runfile("gazelle/std_modules") + stdModulesScriptRunfile, err := bazel.Runfile("gazelle/python/std_modules") if err != nil { log.Printf("failed to initialize std_modules: %v\n", err) os.Exit(1) diff --git a/gazelle/std_modules.py b/gazelle/python/std_modules.py similarity index 100% rename from gazelle/std_modules.py rename to gazelle/python/std_modules.py diff --git a/gazelle/target.go b/gazelle/python/target.go similarity index 100% rename from gazelle/target.go rename to gazelle/python/target.go diff --git a/gazelle/testdata/README.md b/gazelle/python/testdata/README.md similarity index 100% rename from gazelle/testdata/README.md rename to gazelle/python/testdata/README.md diff --git a/gazelle/testdata/dependency_resolution_order/BUILD.in b/gazelle/python/testdata/dependency_resolution_order/BUILD.in similarity index 100% rename from gazelle/testdata/dependency_resolution_order/BUILD.in rename to gazelle/python/testdata/dependency_resolution_order/BUILD.in diff --git a/gazelle/testdata/dependency_resolution_order/BUILD.out b/gazelle/python/testdata/dependency_resolution_order/BUILD.out similarity index 100% rename from gazelle/testdata/dependency_resolution_order/BUILD.out rename to gazelle/python/testdata/dependency_resolution_order/BUILD.out diff --git a/gazelle/testdata/dependency_resolution_order/README.md b/gazelle/python/testdata/dependency_resolution_order/README.md similarity index 100% rename from gazelle/testdata/dependency_resolution_order/README.md rename to gazelle/python/testdata/dependency_resolution_order/README.md diff --git a/gazelle/testdata/dependency_resolution_order/WORKSPACE b/gazelle/python/testdata/dependency_resolution_order/WORKSPACE similarity index 100% rename from gazelle/testdata/dependency_resolution_order/WORKSPACE rename to gazelle/python/testdata/dependency_resolution_order/WORKSPACE diff --git a/gazelle/testdata/dependency_resolution_order/__init__.py b/gazelle/python/testdata/dependency_resolution_order/__init__.py similarity index 100% rename from gazelle/testdata/dependency_resolution_order/__init__.py rename to gazelle/python/testdata/dependency_resolution_order/__init__.py diff --git a/gazelle/testdata/dependency_resolution_order/bar/BUILD.in b/gazelle/python/testdata/dependency_resolution_order/bar/BUILD.in similarity index 100% rename from gazelle/testdata/dependency_resolution_order/bar/BUILD.in rename to gazelle/python/testdata/dependency_resolution_order/bar/BUILD.in diff --git a/gazelle/testdata/dependency_resolution_order/bar/BUILD.out b/gazelle/python/testdata/dependency_resolution_order/bar/BUILD.out similarity index 100% rename from gazelle/testdata/dependency_resolution_order/bar/BUILD.out rename to gazelle/python/testdata/dependency_resolution_order/bar/BUILD.out diff --git a/gazelle/testdata/dependency_resolution_order/bar/__init__.py b/gazelle/python/testdata/dependency_resolution_order/bar/__init__.py similarity index 100% rename from gazelle/testdata/dependency_resolution_order/bar/__init__.py rename to gazelle/python/testdata/dependency_resolution_order/bar/__init__.py diff --git a/gazelle/testdata/dependency_resolution_order/baz/BUILD.in b/gazelle/python/testdata/dependency_resolution_order/baz/BUILD.in similarity index 100% rename from gazelle/testdata/dependency_resolution_order/baz/BUILD.in rename to gazelle/python/testdata/dependency_resolution_order/baz/BUILD.in diff --git a/gazelle/testdata/dependency_resolution_order/baz/BUILD.out b/gazelle/python/testdata/dependency_resolution_order/baz/BUILD.out similarity index 100% rename from gazelle/testdata/dependency_resolution_order/baz/BUILD.out rename to gazelle/python/testdata/dependency_resolution_order/baz/BUILD.out diff --git a/gazelle/testdata/dependency_resolution_order/baz/__init__.py b/gazelle/python/testdata/dependency_resolution_order/baz/__init__.py similarity index 100% rename from gazelle/testdata/dependency_resolution_order/baz/__init__.py rename to gazelle/python/testdata/dependency_resolution_order/baz/__init__.py diff --git a/gazelle/testdata/dependency_resolution_order/foo/BUILD.in b/gazelle/python/testdata/dependency_resolution_order/foo/BUILD.in similarity index 100% rename from gazelle/testdata/dependency_resolution_order/foo/BUILD.in rename to gazelle/python/testdata/dependency_resolution_order/foo/BUILD.in diff --git a/gazelle/testdata/dependency_resolution_order/foo/BUILD.out b/gazelle/python/testdata/dependency_resolution_order/foo/BUILD.out similarity index 100% rename from gazelle/testdata/dependency_resolution_order/foo/BUILD.out rename to gazelle/python/testdata/dependency_resolution_order/foo/BUILD.out diff --git a/gazelle/testdata/dependency_resolution_order/foo/__init__.py b/gazelle/python/testdata/dependency_resolution_order/foo/__init__.py similarity index 100% rename from gazelle/testdata/dependency_resolution_order/foo/__init__.py rename to gazelle/python/testdata/dependency_resolution_order/foo/__init__.py diff --git a/gazelle/testdata/dependency_resolution_order/gazelle_python.yaml b/gazelle/python/testdata/dependency_resolution_order/gazelle_python.yaml similarity index 100% rename from gazelle/testdata/dependency_resolution_order/gazelle_python.yaml rename to gazelle/python/testdata/dependency_resolution_order/gazelle_python.yaml diff --git a/gazelle/testdata/dependency_resolution_order/somewhere/bar/BUILD.in b/gazelle/python/testdata/dependency_resolution_order/somewhere/bar/BUILD.in similarity index 100% rename from gazelle/testdata/dependency_resolution_order/somewhere/bar/BUILD.in rename to gazelle/python/testdata/dependency_resolution_order/somewhere/bar/BUILD.in diff --git a/gazelle/testdata/dependency_resolution_order/somewhere/bar/BUILD.out b/gazelle/python/testdata/dependency_resolution_order/somewhere/bar/BUILD.out similarity index 100% rename from gazelle/testdata/dependency_resolution_order/somewhere/bar/BUILD.out rename to gazelle/python/testdata/dependency_resolution_order/somewhere/bar/BUILD.out diff --git a/gazelle/testdata/dependency_resolution_order/somewhere/bar/__init__.py b/gazelle/python/testdata/dependency_resolution_order/somewhere/bar/__init__.py similarity index 100% rename from gazelle/testdata/dependency_resolution_order/somewhere/bar/__init__.py rename to gazelle/python/testdata/dependency_resolution_order/somewhere/bar/__init__.py diff --git a/gazelle/testdata/dependency_resolution_order/test.yaml b/gazelle/python/testdata/dependency_resolution_order/test.yaml similarity index 100% rename from gazelle/testdata/dependency_resolution_order/test.yaml rename to gazelle/python/testdata/dependency_resolution_order/test.yaml diff --git a/gazelle/testdata/disable_import_statements_validation/BUILD.in b/gazelle/python/testdata/disable_import_statements_validation/BUILD.in similarity index 100% rename from gazelle/testdata/disable_import_statements_validation/BUILD.in rename to gazelle/python/testdata/disable_import_statements_validation/BUILD.in diff --git a/gazelle/testdata/disable_import_statements_validation/BUILD.out b/gazelle/python/testdata/disable_import_statements_validation/BUILD.out similarity index 100% rename from gazelle/testdata/disable_import_statements_validation/BUILD.out rename to gazelle/python/testdata/disable_import_statements_validation/BUILD.out diff --git a/gazelle/testdata/disable_import_statements_validation/README.md b/gazelle/python/testdata/disable_import_statements_validation/README.md similarity index 100% rename from gazelle/testdata/disable_import_statements_validation/README.md rename to gazelle/python/testdata/disable_import_statements_validation/README.md diff --git a/gazelle/testdata/disable_import_statements_validation/WORKSPACE b/gazelle/python/testdata/disable_import_statements_validation/WORKSPACE similarity index 100% rename from gazelle/testdata/disable_import_statements_validation/WORKSPACE rename to gazelle/python/testdata/disable_import_statements_validation/WORKSPACE diff --git a/gazelle/testdata/disable_import_statements_validation/__init__.py b/gazelle/python/testdata/disable_import_statements_validation/__init__.py similarity index 100% rename from gazelle/testdata/disable_import_statements_validation/__init__.py rename to gazelle/python/testdata/disable_import_statements_validation/__init__.py diff --git a/gazelle/testdata/disable_import_statements_validation/test.yaml b/gazelle/python/testdata/disable_import_statements_validation/test.yaml similarity index 100% rename from gazelle/testdata/disable_import_statements_validation/test.yaml rename to gazelle/python/testdata/disable_import_statements_validation/test.yaml diff --git a/gazelle/testdata/dont_rename_target/BUILD.in b/gazelle/python/testdata/dont_rename_target/BUILD.in similarity index 100% rename from gazelle/testdata/dont_rename_target/BUILD.in rename to gazelle/python/testdata/dont_rename_target/BUILD.in diff --git a/gazelle/testdata/dont_rename_target/BUILD.out b/gazelle/python/testdata/dont_rename_target/BUILD.out similarity index 100% rename from gazelle/testdata/dont_rename_target/BUILD.out rename to gazelle/python/testdata/dont_rename_target/BUILD.out diff --git a/gazelle/testdata/dont_rename_target/README.md b/gazelle/python/testdata/dont_rename_target/README.md similarity index 100% rename from gazelle/testdata/dont_rename_target/README.md rename to gazelle/python/testdata/dont_rename_target/README.md diff --git a/gazelle/testdata/dont_rename_target/WORKSPACE b/gazelle/python/testdata/dont_rename_target/WORKSPACE similarity index 100% rename from gazelle/testdata/dont_rename_target/WORKSPACE rename to gazelle/python/testdata/dont_rename_target/WORKSPACE diff --git a/gazelle/testdata/dont_rename_target/__init__.py b/gazelle/python/testdata/dont_rename_target/__init__.py similarity index 100% rename from gazelle/testdata/dont_rename_target/__init__.py rename to gazelle/python/testdata/dont_rename_target/__init__.py diff --git a/gazelle/testdata/dont_rename_target/test.yaml b/gazelle/python/testdata/dont_rename_target/test.yaml similarity index 100% rename from gazelle/testdata/dont_rename_target/test.yaml rename to gazelle/python/testdata/dont_rename_target/test.yaml diff --git a/gazelle/testdata/file_name_matches_import_statement/BUILD.in b/gazelle/python/testdata/file_name_matches_import_statement/BUILD.in similarity index 100% rename from gazelle/testdata/file_name_matches_import_statement/BUILD.in rename to gazelle/python/testdata/file_name_matches_import_statement/BUILD.in diff --git a/gazelle/testdata/file_name_matches_import_statement/BUILD.out b/gazelle/python/testdata/file_name_matches_import_statement/BUILD.out similarity index 100% rename from gazelle/testdata/file_name_matches_import_statement/BUILD.out rename to gazelle/python/testdata/file_name_matches_import_statement/BUILD.out diff --git a/gazelle/testdata/file_name_matches_import_statement/README.md b/gazelle/python/testdata/file_name_matches_import_statement/README.md similarity index 100% rename from gazelle/testdata/file_name_matches_import_statement/README.md rename to gazelle/python/testdata/file_name_matches_import_statement/README.md diff --git a/gazelle/testdata/file_name_matches_import_statement/WORKSPACE b/gazelle/python/testdata/file_name_matches_import_statement/WORKSPACE similarity index 100% rename from gazelle/testdata/file_name_matches_import_statement/WORKSPACE rename to gazelle/python/testdata/file_name_matches_import_statement/WORKSPACE diff --git a/gazelle/testdata/file_name_matches_import_statement/__init__.py b/gazelle/python/testdata/file_name_matches_import_statement/__init__.py similarity index 100% rename from gazelle/testdata/file_name_matches_import_statement/__init__.py rename to gazelle/python/testdata/file_name_matches_import_statement/__init__.py diff --git a/gazelle/testdata/file_name_matches_import_statement/gazelle_python.yaml b/gazelle/python/testdata/file_name_matches_import_statement/gazelle_python.yaml similarity index 100% rename from gazelle/testdata/file_name_matches_import_statement/gazelle_python.yaml rename to gazelle/python/testdata/file_name_matches_import_statement/gazelle_python.yaml diff --git a/gazelle/testdata/file_name_matches_import_statement/rest_framework.py b/gazelle/python/testdata/file_name_matches_import_statement/rest_framework.py similarity index 100% rename from gazelle/testdata/file_name_matches_import_statement/rest_framework.py rename to gazelle/python/testdata/file_name_matches_import_statement/rest_framework.py diff --git a/gazelle/testdata/file_name_matches_import_statement/test.yaml b/gazelle/python/testdata/file_name_matches_import_statement/test.yaml similarity index 100% rename from gazelle/testdata/file_name_matches_import_statement/test.yaml rename to gazelle/python/testdata/file_name_matches_import_statement/test.yaml diff --git a/gazelle/testdata/first_party_dependencies/BUILD.in b/gazelle/python/testdata/first_party_dependencies/BUILD.in similarity index 100% rename from gazelle/testdata/first_party_dependencies/BUILD.in rename to gazelle/python/testdata/first_party_dependencies/BUILD.in diff --git a/gazelle/testdata/first_party_dependencies/BUILD.out b/gazelle/python/testdata/first_party_dependencies/BUILD.out similarity index 100% rename from gazelle/testdata/first_party_dependencies/BUILD.out rename to gazelle/python/testdata/first_party_dependencies/BUILD.out diff --git a/gazelle/testdata/first_party_dependencies/README.md b/gazelle/python/testdata/first_party_dependencies/README.md similarity index 100% rename from gazelle/testdata/first_party_dependencies/README.md rename to gazelle/python/testdata/first_party_dependencies/README.md diff --git a/gazelle/testdata/first_party_dependencies/WORKSPACE b/gazelle/python/testdata/first_party_dependencies/WORKSPACE similarity index 100% rename from gazelle/testdata/first_party_dependencies/WORKSPACE rename to gazelle/python/testdata/first_party_dependencies/WORKSPACE diff --git a/gazelle/testdata/first_party_dependencies/one/BUILD.in b/gazelle/python/testdata/first_party_dependencies/one/BUILD.in similarity index 100% rename from gazelle/testdata/first_party_dependencies/one/BUILD.in rename to gazelle/python/testdata/first_party_dependencies/one/BUILD.in diff --git a/gazelle/testdata/first_party_dependencies/one/BUILD.out b/gazelle/python/testdata/first_party_dependencies/one/BUILD.out similarity index 100% rename from gazelle/testdata/first_party_dependencies/one/BUILD.out rename to gazelle/python/testdata/first_party_dependencies/one/BUILD.out diff --git a/gazelle/testdata/first_party_dependencies/one/__main__.py b/gazelle/python/testdata/first_party_dependencies/one/__main__.py similarity index 100% rename from gazelle/testdata/first_party_dependencies/one/__main__.py rename to gazelle/python/testdata/first_party_dependencies/one/__main__.py diff --git a/gazelle/testdata/first_party_dependencies/one/bar/BUILD.in b/gazelle/python/testdata/first_party_dependencies/one/bar/BUILD.in similarity index 100% rename from gazelle/testdata/first_party_dependencies/one/bar/BUILD.in rename to gazelle/python/testdata/first_party_dependencies/one/bar/BUILD.in diff --git a/gazelle/testdata/first_party_dependencies/one/bar/BUILD.out b/gazelle/python/testdata/first_party_dependencies/one/bar/BUILD.out similarity index 100% rename from gazelle/testdata/first_party_dependencies/one/bar/BUILD.out rename to gazelle/python/testdata/first_party_dependencies/one/bar/BUILD.out diff --git a/gazelle/testdata/first_party_dependencies/one/bar/__init__.py b/gazelle/python/testdata/first_party_dependencies/one/bar/__init__.py similarity index 100% rename from gazelle/testdata/first_party_dependencies/one/bar/__init__.py rename to gazelle/python/testdata/first_party_dependencies/one/bar/__init__.py diff --git a/gazelle/testdata/first_party_dependencies/one/bar/baz/BUILD.in b/gazelle/python/testdata/first_party_dependencies/one/bar/baz/BUILD.in similarity index 100% rename from gazelle/testdata/first_party_dependencies/one/bar/baz/BUILD.in rename to gazelle/python/testdata/first_party_dependencies/one/bar/baz/BUILD.in diff --git a/gazelle/testdata/first_party_dependencies/one/bar/baz/BUILD.out b/gazelle/python/testdata/first_party_dependencies/one/bar/baz/BUILD.out similarity index 100% rename from gazelle/testdata/first_party_dependencies/one/bar/baz/BUILD.out rename to gazelle/python/testdata/first_party_dependencies/one/bar/baz/BUILD.out diff --git a/gazelle/testdata/first_party_dependencies/one/bar/baz/__init__.py b/gazelle/python/testdata/first_party_dependencies/one/bar/baz/__init__.py similarity index 100% rename from gazelle/testdata/first_party_dependencies/one/bar/baz/__init__.py rename to gazelle/python/testdata/first_party_dependencies/one/bar/baz/__init__.py diff --git a/gazelle/testdata/first_party_dependencies/one/foo/BUILD.in b/gazelle/python/testdata/first_party_dependencies/one/foo/BUILD.in similarity index 100% rename from gazelle/testdata/first_party_dependencies/one/foo/BUILD.in rename to gazelle/python/testdata/first_party_dependencies/one/foo/BUILD.in diff --git a/gazelle/testdata/first_party_dependencies/one/foo/BUILD.out b/gazelle/python/testdata/first_party_dependencies/one/foo/BUILD.out similarity index 100% rename from gazelle/testdata/first_party_dependencies/one/foo/BUILD.out rename to gazelle/python/testdata/first_party_dependencies/one/foo/BUILD.out diff --git a/gazelle/testdata/first_party_dependencies/one/foo/__init__.py b/gazelle/python/testdata/first_party_dependencies/one/foo/__init__.py similarity index 100% rename from gazelle/testdata/first_party_dependencies/one/foo/__init__.py rename to gazelle/python/testdata/first_party_dependencies/one/foo/__init__.py diff --git a/gazelle/testdata/first_party_dependencies/test.yaml b/gazelle/python/testdata/first_party_dependencies/test.yaml similarity index 100% rename from gazelle/testdata/first_party_dependencies/test.yaml rename to gazelle/python/testdata/first_party_dependencies/test.yaml diff --git a/gazelle/testdata/first_party_dependencies/three/BUILD.in b/gazelle/python/testdata/first_party_dependencies/three/BUILD.in similarity index 100% rename from gazelle/testdata/first_party_dependencies/three/BUILD.in rename to gazelle/python/testdata/first_party_dependencies/three/BUILD.in diff --git a/gazelle/testdata/first_party_dependencies/three/BUILD.out b/gazelle/python/testdata/first_party_dependencies/three/BUILD.out similarity index 100% rename from gazelle/testdata/first_party_dependencies/three/BUILD.out rename to gazelle/python/testdata/first_party_dependencies/three/BUILD.out diff --git a/gazelle/testdata/first_party_dependencies/three/__init__.py b/gazelle/python/testdata/first_party_dependencies/three/__init__.py similarity index 100% rename from gazelle/testdata/first_party_dependencies/three/__init__.py rename to gazelle/python/testdata/first_party_dependencies/three/__init__.py diff --git a/gazelle/testdata/first_party_dependencies/two/BUILD.in b/gazelle/python/testdata/first_party_dependencies/two/BUILD.in similarity index 100% rename from gazelle/testdata/first_party_dependencies/two/BUILD.in rename to gazelle/python/testdata/first_party_dependencies/two/BUILD.in diff --git a/gazelle/testdata/first_party_dependencies/two/BUILD.out b/gazelle/python/testdata/first_party_dependencies/two/BUILD.out similarity index 100% rename from gazelle/testdata/first_party_dependencies/two/BUILD.out rename to gazelle/python/testdata/first_party_dependencies/two/BUILD.out diff --git a/gazelle/testdata/first_party_dependencies/two/__init__.py b/gazelle/python/testdata/first_party_dependencies/two/__init__.py similarity index 100% rename from gazelle/testdata/first_party_dependencies/two/__init__.py rename to gazelle/python/testdata/first_party_dependencies/two/__init__.py diff --git a/gazelle/testdata/first_party_file_and_directory_modules/BUILD.in b/gazelle/python/testdata/first_party_file_and_directory_modules/BUILD.in similarity index 100% rename from gazelle/testdata/first_party_file_and_directory_modules/BUILD.in rename to gazelle/python/testdata/first_party_file_and_directory_modules/BUILD.in diff --git a/gazelle/testdata/first_party_file_and_directory_modules/BUILD.out b/gazelle/python/testdata/first_party_file_and_directory_modules/BUILD.out similarity index 100% rename from gazelle/testdata/first_party_file_and_directory_modules/BUILD.out rename to gazelle/python/testdata/first_party_file_and_directory_modules/BUILD.out diff --git a/gazelle/testdata/first_party_file_and_directory_modules/README.md b/gazelle/python/testdata/first_party_file_and_directory_modules/README.md similarity index 100% rename from gazelle/testdata/first_party_file_and_directory_modules/README.md rename to gazelle/python/testdata/first_party_file_and_directory_modules/README.md diff --git a/gazelle/testdata/first_party_file_and_directory_modules/WORKSPACE b/gazelle/python/testdata/first_party_file_and_directory_modules/WORKSPACE similarity index 100% rename from gazelle/testdata/first_party_file_and_directory_modules/WORKSPACE rename to gazelle/python/testdata/first_party_file_and_directory_modules/WORKSPACE diff --git a/gazelle/testdata/first_party_file_and_directory_modules/__main__.py b/gazelle/python/testdata/first_party_file_and_directory_modules/__main__.py similarity index 100% rename from gazelle/testdata/first_party_file_and_directory_modules/__main__.py rename to gazelle/python/testdata/first_party_file_and_directory_modules/__main__.py diff --git a/gazelle/testdata/first_party_file_and_directory_modules/baz.py b/gazelle/python/testdata/first_party_file_and_directory_modules/baz.py similarity index 100% rename from gazelle/testdata/first_party_file_and_directory_modules/baz.py rename to gazelle/python/testdata/first_party_file_and_directory_modules/baz.py diff --git a/gazelle/testdata/first_party_file_and_directory_modules/foo.py b/gazelle/python/testdata/first_party_file_and_directory_modules/foo.py similarity index 100% rename from gazelle/testdata/first_party_file_and_directory_modules/foo.py rename to gazelle/python/testdata/first_party_file_and_directory_modules/foo.py diff --git a/gazelle/testdata/first_party_file_and_directory_modules/foo/BUILD.in b/gazelle/python/testdata/first_party_file_and_directory_modules/foo/BUILD.in similarity index 100% rename from gazelle/testdata/first_party_file_and_directory_modules/foo/BUILD.in rename to gazelle/python/testdata/first_party_file_and_directory_modules/foo/BUILD.in diff --git a/gazelle/testdata/first_party_file_and_directory_modules/foo/BUILD.out b/gazelle/python/testdata/first_party_file_and_directory_modules/foo/BUILD.out similarity index 100% rename from gazelle/testdata/first_party_file_and_directory_modules/foo/BUILD.out rename to gazelle/python/testdata/first_party_file_and_directory_modules/foo/BUILD.out diff --git a/gazelle/testdata/first_party_file_and_directory_modules/foo/__init__.py b/gazelle/python/testdata/first_party_file_and_directory_modules/foo/__init__.py similarity index 100% rename from gazelle/testdata/first_party_file_and_directory_modules/foo/__init__.py rename to gazelle/python/testdata/first_party_file_and_directory_modules/foo/__init__.py diff --git a/gazelle/testdata/first_party_file_and_directory_modules/foo/bar.py b/gazelle/python/testdata/first_party_file_and_directory_modules/foo/bar.py similarity index 100% rename from gazelle/testdata/first_party_file_and_directory_modules/foo/bar.py rename to gazelle/python/testdata/first_party_file_and_directory_modules/foo/bar.py diff --git a/gazelle/testdata/first_party_file_and_directory_modules/one/BUILD.in b/gazelle/python/testdata/first_party_file_and_directory_modules/one/BUILD.in similarity index 100% rename from gazelle/testdata/first_party_file_and_directory_modules/one/BUILD.in rename to gazelle/python/testdata/first_party_file_and_directory_modules/one/BUILD.in diff --git a/gazelle/testdata/first_party_file_and_directory_modules/one/BUILD.out b/gazelle/python/testdata/first_party_file_and_directory_modules/one/BUILD.out similarity index 100% rename from gazelle/testdata/first_party_file_and_directory_modules/one/BUILD.out rename to gazelle/python/testdata/first_party_file_and_directory_modules/one/BUILD.out diff --git a/gazelle/testdata/first_party_file_and_directory_modules/one/__init__.py b/gazelle/python/testdata/first_party_file_and_directory_modules/one/__init__.py similarity index 100% rename from gazelle/testdata/first_party_file_and_directory_modules/one/__init__.py rename to gazelle/python/testdata/first_party_file_and_directory_modules/one/__init__.py diff --git a/gazelle/testdata/first_party_file_and_directory_modules/one/two.py b/gazelle/python/testdata/first_party_file_and_directory_modules/one/two.py similarity index 100% rename from gazelle/testdata/first_party_file_and_directory_modules/one/two.py rename to gazelle/python/testdata/first_party_file_and_directory_modules/one/two.py diff --git a/gazelle/testdata/first_party_file_and_directory_modules/test.yaml b/gazelle/python/testdata/first_party_file_and_directory_modules/test.yaml similarity index 100% rename from gazelle/testdata/first_party_file_and_directory_modules/test.yaml rename to gazelle/python/testdata/first_party_file_and_directory_modules/test.yaml diff --git a/gazelle/testdata/first_party_file_and_directory_modules/undiscoverable/BUILD.in b/gazelle/python/testdata/first_party_file_and_directory_modules/undiscoverable/BUILD.in similarity index 100% rename from gazelle/testdata/first_party_file_and_directory_modules/undiscoverable/BUILD.in rename to gazelle/python/testdata/first_party_file_and_directory_modules/undiscoverable/BUILD.in diff --git a/gazelle/testdata/first_party_file_and_directory_modules/undiscoverable/BUILD.out b/gazelle/python/testdata/first_party_file_and_directory_modules/undiscoverable/BUILD.out similarity index 100% rename from gazelle/testdata/first_party_file_and_directory_modules/undiscoverable/BUILD.out rename to gazelle/python/testdata/first_party_file_and_directory_modules/undiscoverable/BUILD.out diff --git a/gazelle/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/BUILD.in b/gazelle/python/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/BUILD.in similarity index 100% rename from gazelle/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/BUILD.in rename to gazelle/python/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/BUILD.in diff --git a/gazelle/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/BUILD.out b/gazelle/python/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/BUILD.out similarity index 100% rename from gazelle/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/BUILD.out rename to gazelle/python/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/BUILD.out diff --git a/gazelle/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/__init__.py b/gazelle/python/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/__init__.py similarity index 100% rename from gazelle/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/__init__.py rename to gazelle/python/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/__init__.py diff --git a/gazelle/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/module1.py b/gazelle/python/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/module1.py similarity index 100% rename from gazelle/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/module1.py rename to gazelle/python/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/module1.py diff --git a/gazelle/testdata/from_imports/BUILD.in b/gazelle/python/testdata/from_imports/BUILD.in similarity index 100% rename from gazelle/testdata/from_imports/BUILD.in rename to gazelle/python/testdata/from_imports/BUILD.in diff --git a/gazelle/testdata/from_imports/BUILD.out b/gazelle/python/testdata/from_imports/BUILD.out similarity index 100% rename from gazelle/testdata/from_imports/BUILD.out rename to gazelle/python/testdata/from_imports/BUILD.out diff --git a/gazelle/testdata/from_imports/README.md b/gazelle/python/testdata/from_imports/README.md similarity index 100% rename from gazelle/testdata/from_imports/README.md rename to gazelle/python/testdata/from_imports/README.md diff --git a/gazelle/testdata/from_imports/WORKSPACE b/gazelle/python/testdata/from_imports/WORKSPACE similarity index 100% rename from gazelle/testdata/from_imports/WORKSPACE rename to gazelle/python/testdata/from_imports/WORKSPACE diff --git a/gazelle/testdata/from_imports/foo/BUILD.in b/gazelle/python/testdata/from_imports/foo/BUILD.in similarity index 100% rename from gazelle/testdata/from_imports/foo/BUILD.in rename to gazelle/python/testdata/from_imports/foo/BUILD.in diff --git a/gazelle/testdata/from_imports/foo/BUILD.out b/gazelle/python/testdata/from_imports/foo/BUILD.out similarity index 100% rename from gazelle/testdata/from_imports/foo/BUILD.out rename to gazelle/python/testdata/from_imports/foo/BUILD.out diff --git a/gazelle/testdata/from_imports/foo/__init__.py b/gazelle/python/testdata/from_imports/foo/__init__.py similarity index 100% rename from gazelle/testdata/from_imports/foo/__init__.py rename to gazelle/python/testdata/from_imports/foo/__init__.py diff --git a/gazelle/testdata/from_imports/foo/bar/BUILD.in b/gazelle/python/testdata/from_imports/foo/bar/BUILD.in similarity index 100% rename from gazelle/testdata/from_imports/foo/bar/BUILD.in rename to gazelle/python/testdata/from_imports/foo/bar/BUILD.in diff --git a/gazelle/testdata/from_imports/foo/bar/BUILD.out b/gazelle/python/testdata/from_imports/foo/bar/BUILD.out similarity index 100% rename from gazelle/testdata/from_imports/foo/bar/BUILD.out rename to gazelle/python/testdata/from_imports/foo/bar/BUILD.out diff --git a/gazelle/testdata/from_imports/foo/bar/__init__.py b/gazelle/python/testdata/from_imports/foo/bar/__init__.py similarity index 100% rename from gazelle/testdata/from_imports/foo/bar/__init__.py rename to gazelle/python/testdata/from_imports/foo/bar/__init__.py diff --git a/gazelle/testdata/from_imports/foo/bar/baz.py b/gazelle/python/testdata/from_imports/foo/bar/baz.py similarity index 100% rename from gazelle/testdata/from_imports/foo/bar/baz.py rename to gazelle/python/testdata/from_imports/foo/bar/baz.py diff --git a/gazelle/testdata/from_imports/gazelle_python.yaml b/gazelle/python/testdata/from_imports/gazelle_python.yaml similarity index 100% rename from gazelle/testdata/from_imports/gazelle_python.yaml rename to gazelle/python/testdata/from_imports/gazelle_python.yaml diff --git a/gazelle/testdata/from_imports/import_from_init_py/BUILD.in b/gazelle/python/testdata/from_imports/import_from_init_py/BUILD.in similarity index 100% rename from gazelle/testdata/from_imports/import_from_init_py/BUILD.in rename to gazelle/python/testdata/from_imports/import_from_init_py/BUILD.in diff --git a/gazelle/testdata/from_imports/import_from_init_py/BUILD.out b/gazelle/python/testdata/from_imports/import_from_init_py/BUILD.out similarity index 100% rename from gazelle/testdata/from_imports/import_from_init_py/BUILD.out rename to gazelle/python/testdata/from_imports/import_from_init_py/BUILD.out diff --git a/gazelle/testdata/from_imports/import_from_init_py/__init__.py b/gazelle/python/testdata/from_imports/import_from_init_py/__init__.py similarity index 100% rename from gazelle/testdata/from_imports/import_from_init_py/__init__.py rename to gazelle/python/testdata/from_imports/import_from_init_py/__init__.py diff --git a/gazelle/testdata/from_imports/import_from_multiple/BUILD.in b/gazelle/python/testdata/from_imports/import_from_multiple/BUILD.in similarity index 100% rename from gazelle/testdata/from_imports/import_from_multiple/BUILD.in rename to gazelle/python/testdata/from_imports/import_from_multiple/BUILD.in diff --git a/gazelle/testdata/from_imports/import_from_multiple/BUILD.out b/gazelle/python/testdata/from_imports/import_from_multiple/BUILD.out similarity index 100% rename from gazelle/testdata/from_imports/import_from_multiple/BUILD.out rename to gazelle/python/testdata/from_imports/import_from_multiple/BUILD.out diff --git a/gazelle/testdata/from_imports/import_from_multiple/__init__.py b/gazelle/python/testdata/from_imports/import_from_multiple/__init__.py similarity index 100% rename from gazelle/testdata/from_imports/import_from_multiple/__init__.py rename to gazelle/python/testdata/from_imports/import_from_multiple/__init__.py diff --git a/gazelle/testdata/from_imports/import_nested_file/BUILD.in b/gazelle/python/testdata/from_imports/import_nested_file/BUILD.in similarity index 100% rename from gazelle/testdata/from_imports/import_nested_file/BUILD.in rename to gazelle/python/testdata/from_imports/import_nested_file/BUILD.in diff --git a/gazelle/testdata/from_imports/import_nested_file/BUILD.out b/gazelle/python/testdata/from_imports/import_nested_file/BUILD.out similarity index 100% rename from gazelle/testdata/from_imports/import_nested_file/BUILD.out rename to gazelle/python/testdata/from_imports/import_nested_file/BUILD.out diff --git a/gazelle/testdata/from_imports/import_nested_file/__init__.py b/gazelle/python/testdata/from_imports/import_nested_file/__init__.py similarity index 100% rename from gazelle/testdata/from_imports/import_nested_file/__init__.py rename to gazelle/python/testdata/from_imports/import_nested_file/__init__.py diff --git a/gazelle/testdata/from_imports/import_nested_module/BUILD.in b/gazelle/python/testdata/from_imports/import_nested_module/BUILD.in similarity index 100% rename from gazelle/testdata/from_imports/import_nested_module/BUILD.in rename to gazelle/python/testdata/from_imports/import_nested_module/BUILD.in diff --git a/gazelle/testdata/from_imports/import_nested_module/BUILD.out b/gazelle/python/testdata/from_imports/import_nested_module/BUILD.out similarity index 100% rename from gazelle/testdata/from_imports/import_nested_module/BUILD.out rename to gazelle/python/testdata/from_imports/import_nested_module/BUILD.out diff --git a/gazelle/testdata/from_imports/import_nested_module/__init__.py b/gazelle/python/testdata/from_imports/import_nested_module/__init__.py similarity index 100% rename from gazelle/testdata/from_imports/import_nested_module/__init__.py rename to gazelle/python/testdata/from_imports/import_nested_module/__init__.py diff --git a/gazelle/testdata/from_imports/import_nested_var/BUILD.in b/gazelle/python/testdata/from_imports/import_nested_var/BUILD.in similarity index 100% rename from gazelle/testdata/from_imports/import_nested_var/BUILD.in rename to gazelle/python/testdata/from_imports/import_nested_var/BUILD.in diff --git a/gazelle/testdata/from_imports/import_nested_var/BUILD.out b/gazelle/python/testdata/from_imports/import_nested_var/BUILD.out similarity index 100% rename from gazelle/testdata/from_imports/import_nested_var/BUILD.out rename to gazelle/python/testdata/from_imports/import_nested_var/BUILD.out diff --git a/gazelle/testdata/from_imports/import_nested_var/__init__.py b/gazelle/python/testdata/from_imports/import_nested_var/__init__.py similarity index 100% rename from gazelle/testdata/from_imports/import_nested_var/__init__.py rename to gazelle/python/testdata/from_imports/import_nested_var/__init__.py diff --git a/gazelle/testdata/from_imports/import_top_level_var/BUILD.in b/gazelle/python/testdata/from_imports/import_top_level_var/BUILD.in similarity index 100% rename from gazelle/testdata/from_imports/import_top_level_var/BUILD.in rename to gazelle/python/testdata/from_imports/import_top_level_var/BUILD.in diff --git a/gazelle/testdata/from_imports/import_top_level_var/BUILD.out b/gazelle/python/testdata/from_imports/import_top_level_var/BUILD.out similarity index 100% rename from gazelle/testdata/from_imports/import_top_level_var/BUILD.out rename to gazelle/python/testdata/from_imports/import_top_level_var/BUILD.out diff --git a/gazelle/testdata/from_imports/import_top_level_var/__init__.py b/gazelle/python/testdata/from_imports/import_top_level_var/__init__.py similarity index 100% rename from gazelle/testdata/from_imports/import_top_level_var/__init__.py rename to gazelle/python/testdata/from_imports/import_top_level_var/__init__.py diff --git a/gazelle/testdata/from_imports/std_module/BUILD.in b/gazelle/python/testdata/from_imports/std_module/BUILD.in similarity index 100% rename from gazelle/testdata/from_imports/std_module/BUILD.in rename to gazelle/python/testdata/from_imports/std_module/BUILD.in diff --git a/gazelle/testdata/from_imports/std_module/BUILD.out b/gazelle/python/testdata/from_imports/std_module/BUILD.out similarity index 100% rename from gazelle/testdata/from_imports/std_module/BUILD.out rename to gazelle/python/testdata/from_imports/std_module/BUILD.out diff --git a/gazelle/testdata/from_imports/std_module/__init__.py b/gazelle/python/testdata/from_imports/std_module/__init__.py similarity index 100% rename from gazelle/testdata/from_imports/std_module/__init__.py rename to gazelle/python/testdata/from_imports/std_module/__init__.py diff --git a/gazelle/testdata/from_imports/test.yaml b/gazelle/python/testdata/from_imports/test.yaml similarity index 100% rename from gazelle/testdata/from_imports/test.yaml rename to gazelle/python/testdata/from_imports/test.yaml diff --git a/gazelle/testdata/generated_test_entrypoint/BUILD.in b/gazelle/python/testdata/generated_test_entrypoint/BUILD.in similarity index 100% rename from gazelle/testdata/generated_test_entrypoint/BUILD.in rename to gazelle/python/testdata/generated_test_entrypoint/BUILD.in diff --git a/gazelle/testdata/generated_test_entrypoint/BUILD.out b/gazelle/python/testdata/generated_test_entrypoint/BUILD.out similarity index 100% rename from gazelle/testdata/generated_test_entrypoint/BUILD.out rename to gazelle/python/testdata/generated_test_entrypoint/BUILD.out diff --git a/gazelle/testdata/generated_test_entrypoint/README.md b/gazelle/python/testdata/generated_test_entrypoint/README.md similarity index 100% rename from gazelle/testdata/generated_test_entrypoint/README.md rename to gazelle/python/testdata/generated_test_entrypoint/README.md diff --git a/gazelle/testdata/generated_test_entrypoint/WORKSPACE b/gazelle/python/testdata/generated_test_entrypoint/WORKSPACE similarity index 100% rename from gazelle/testdata/generated_test_entrypoint/WORKSPACE rename to gazelle/python/testdata/generated_test_entrypoint/WORKSPACE diff --git a/gazelle/testdata/generated_test_entrypoint/__init__.py b/gazelle/python/testdata/generated_test_entrypoint/__init__.py similarity index 100% rename from gazelle/testdata/generated_test_entrypoint/__init__.py rename to gazelle/python/testdata/generated_test_entrypoint/__init__.py diff --git a/gazelle/testdata/generated_test_entrypoint/foo.py b/gazelle/python/testdata/generated_test_entrypoint/foo.py similarity index 100% rename from gazelle/testdata/generated_test_entrypoint/foo.py rename to gazelle/python/testdata/generated_test_entrypoint/foo.py diff --git a/gazelle/testdata/generated_test_entrypoint/test.yaml b/gazelle/python/testdata/generated_test_entrypoint/test.yaml similarity index 100% rename from gazelle/testdata/generated_test_entrypoint/test.yaml rename to gazelle/python/testdata/generated_test_entrypoint/test.yaml diff --git a/gazelle/testdata/ignored_invalid_imported_module/BUILD.in b/gazelle/python/testdata/ignored_invalid_imported_module/BUILD.in similarity index 100% rename from gazelle/testdata/ignored_invalid_imported_module/BUILD.in rename to gazelle/python/testdata/ignored_invalid_imported_module/BUILD.in diff --git a/gazelle/testdata/ignored_invalid_imported_module/BUILD.out b/gazelle/python/testdata/ignored_invalid_imported_module/BUILD.out similarity index 100% rename from gazelle/testdata/ignored_invalid_imported_module/BUILD.out rename to gazelle/python/testdata/ignored_invalid_imported_module/BUILD.out diff --git a/gazelle/testdata/ignored_invalid_imported_module/README.md b/gazelle/python/testdata/ignored_invalid_imported_module/README.md similarity index 100% rename from gazelle/testdata/ignored_invalid_imported_module/README.md rename to gazelle/python/testdata/ignored_invalid_imported_module/README.md diff --git a/gazelle/testdata/ignored_invalid_imported_module/WORKSPACE b/gazelle/python/testdata/ignored_invalid_imported_module/WORKSPACE similarity index 100% rename from gazelle/testdata/ignored_invalid_imported_module/WORKSPACE rename to gazelle/python/testdata/ignored_invalid_imported_module/WORKSPACE diff --git a/gazelle/testdata/ignored_invalid_imported_module/__init__.py b/gazelle/python/testdata/ignored_invalid_imported_module/__init__.py similarity index 100% rename from gazelle/testdata/ignored_invalid_imported_module/__init__.py rename to gazelle/python/testdata/ignored_invalid_imported_module/__init__.py diff --git a/gazelle/testdata/ignored_invalid_imported_module/gazelle_python.yaml b/gazelle/python/testdata/ignored_invalid_imported_module/gazelle_python.yaml similarity index 100% rename from gazelle/testdata/ignored_invalid_imported_module/gazelle_python.yaml rename to gazelle/python/testdata/ignored_invalid_imported_module/gazelle_python.yaml diff --git a/gazelle/testdata/ignored_invalid_imported_module/test.yaml b/gazelle/python/testdata/ignored_invalid_imported_module/test.yaml similarity index 100% rename from gazelle/testdata/ignored_invalid_imported_module/test.yaml rename to gazelle/python/testdata/ignored_invalid_imported_module/test.yaml diff --git a/gazelle/testdata/invalid_annotation/BUILD.in b/gazelle/python/testdata/invalid_annotation/BUILD.in similarity index 100% rename from gazelle/testdata/invalid_annotation/BUILD.in rename to gazelle/python/testdata/invalid_annotation/BUILD.in diff --git a/gazelle/testdata/invalid_annotation/BUILD.out b/gazelle/python/testdata/invalid_annotation/BUILD.out similarity index 100% rename from gazelle/testdata/invalid_annotation/BUILD.out rename to gazelle/python/testdata/invalid_annotation/BUILD.out diff --git a/gazelle/testdata/invalid_annotation/README.md b/gazelle/python/testdata/invalid_annotation/README.md similarity index 100% rename from gazelle/testdata/invalid_annotation/README.md rename to gazelle/python/testdata/invalid_annotation/README.md diff --git a/gazelle/testdata/invalid_annotation/WORKSPACE b/gazelle/python/testdata/invalid_annotation/WORKSPACE similarity index 100% rename from gazelle/testdata/invalid_annotation/WORKSPACE rename to gazelle/python/testdata/invalid_annotation/WORKSPACE diff --git a/gazelle/testdata/invalid_annotation/__init__.py b/gazelle/python/testdata/invalid_annotation/__init__.py similarity index 100% rename from gazelle/testdata/invalid_annotation/__init__.py rename to gazelle/python/testdata/invalid_annotation/__init__.py diff --git a/gazelle/testdata/invalid_annotation/test.yaml b/gazelle/python/testdata/invalid_annotation/test.yaml similarity index 100% rename from gazelle/testdata/invalid_annotation/test.yaml rename to gazelle/python/testdata/invalid_annotation/test.yaml diff --git a/gazelle/testdata/invalid_imported_module/BUILD.in b/gazelle/python/testdata/invalid_imported_module/BUILD.in similarity index 100% rename from gazelle/testdata/invalid_imported_module/BUILD.in rename to gazelle/python/testdata/invalid_imported_module/BUILD.in diff --git a/gazelle/testdata/invalid_imported_module/BUILD.out b/gazelle/python/testdata/invalid_imported_module/BUILD.out similarity index 100% rename from gazelle/testdata/invalid_imported_module/BUILD.out rename to gazelle/python/testdata/invalid_imported_module/BUILD.out diff --git a/gazelle/testdata/invalid_imported_module/README.md b/gazelle/python/testdata/invalid_imported_module/README.md similarity index 100% rename from gazelle/testdata/invalid_imported_module/README.md rename to gazelle/python/testdata/invalid_imported_module/README.md diff --git a/gazelle/testdata/invalid_imported_module/WORKSPACE b/gazelle/python/testdata/invalid_imported_module/WORKSPACE similarity index 100% rename from gazelle/testdata/invalid_imported_module/WORKSPACE rename to gazelle/python/testdata/invalid_imported_module/WORKSPACE diff --git a/gazelle/testdata/invalid_imported_module/__init__.py b/gazelle/python/testdata/invalid_imported_module/__init__.py similarity index 100% rename from gazelle/testdata/invalid_imported_module/__init__.py rename to gazelle/python/testdata/invalid_imported_module/__init__.py diff --git a/gazelle/testdata/invalid_imported_module/test.yaml b/gazelle/python/testdata/invalid_imported_module/test.yaml similarity index 100% rename from gazelle/testdata/invalid_imported_module/test.yaml rename to gazelle/python/testdata/invalid_imported_module/test.yaml diff --git a/gazelle/testdata/monorepo/BUILD.in b/gazelle/python/testdata/monorepo/BUILD.in similarity index 100% rename from gazelle/testdata/monorepo/BUILD.in rename to gazelle/python/testdata/monorepo/BUILD.in diff --git a/gazelle/testdata/monorepo/BUILD.out b/gazelle/python/testdata/monorepo/BUILD.out similarity index 100% rename from gazelle/testdata/monorepo/BUILD.out rename to gazelle/python/testdata/monorepo/BUILD.out diff --git a/gazelle/testdata/monorepo/README.md b/gazelle/python/testdata/monorepo/README.md similarity index 100% rename from gazelle/testdata/monorepo/README.md rename to gazelle/python/testdata/monorepo/README.md diff --git a/gazelle/testdata/monorepo/WORKSPACE b/gazelle/python/testdata/monorepo/WORKSPACE similarity index 100% rename from gazelle/testdata/monorepo/WORKSPACE rename to gazelle/python/testdata/monorepo/WORKSPACE diff --git a/gazelle/testdata/monorepo/coarse_grained/BUILD.in b/gazelle/python/testdata/monorepo/coarse_grained/BUILD.in similarity index 100% rename from gazelle/testdata/monorepo/coarse_grained/BUILD.in rename to gazelle/python/testdata/monorepo/coarse_grained/BUILD.in diff --git a/gazelle/testdata/monorepo/coarse_grained/BUILD.out b/gazelle/python/testdata/monorepo/coarse_grained/BUILD.out similarity index 100% rename from gazelle/testdata/monorepo/coarse_grained/BUILD.out rename to gazelle/python/testdata/monorepo/coarse_grained/BUILD.out diff --git a/gazelle/testdata/monorepo/coarse_grained/__init__.py b/gazelle/python/testdata/monorepo/coarse_grained/__init__.py similarity index 100% rename from gazelle/testdata/monorepo/coarse_grained/__init__.py rename to gazelle/python/testdata/monorepo/coarse_grained/__init__.py diff --git a/gazelle/testdata/monorepo/coarse_grained/_boundary/BUILD.in b/gazelle/python/testdata/monorepo/coarse_grained/_boundary/BUILD.in similarity index 100% rename from gazelle/testdata/monorepo/coarse_grained/_boundary/BUILD.in rename to gazelle/python/testdata/monorepo/coarse_grained/_boundary/BUILD.in diff --git a/gazelle/testdata/monorepo/coarse_grained/_boundary/BUILD.out b/gazelle/python/testdata/monorepo/coarse_grained/_boundary/BUILD.out similarity index 100% rename from gazelle/testdata/monorepo/coarse_grained/_boundary/BUILD.out rename to gazelle/python/testdata/monorepo/coarse_grained/_boundary/BUILD.out diff --git a/gazelle/testdata/monorepo/coarse_grained/_boundary/README.md b/gazelle/python/testdata/monorepo/coarse_grained/_boundary/README.md similarity index 100% rename from gazelle/testdata/monorepo/coarse_grained/_boundary/README.md rename to gazelle/python/testdata/monorepo/coarse_grained/_boundary/README.md diff --git a/gazelle/testdata/monorepo/coarse_grained/_boundary/__init__.py b/gazelle/python/testdata/monorepo/coarse_grained/_boundary/__init__.py similarity index 100% rename from gazelle/testdata/monorepo/coarse_grained/_boundary/__init__.py rename to gazelle/python/testdata/monorepo/coarse_grained/_boundary/__init__.py diff --git a/gazelle/testdata/monorepo/coarse_grained/bar/__init__.py b/gazelle/python/testdata/monorepo/coarse_grained/bar/__init__.py similarity index 100% rename from gazelle/testdata/monorepo/coarse_grained/bar/__init__.py rename to gazelle/python/testdata/monorepo/coarse_grained/bar/__init__.py diff --git a/gazelle/testdata/monorepo/coarse_grained/bar/baz/__init__.py b/gazelle/python/testdata/monorepo/coarse_grained/bar/baz/__init__.py similarity index 100% rename from gazelle/testdata/monorepo/coarse_grained/bar/baz/__init__.py rename to gazelle/python/testdata/monorepo/coarse_grained/bar/baz/__init__.py diff --git a/gazelle/testdata/monorepo/coarse_grained/bar/baz/first_excluded.py b/gazelle/python/testdata/monorepo/coarse_grained/bar/baz/first_excluded.py similarity index 100% rename from gazelle/testdata/monorepo/coarse_grained/bar/baz/first_excluded.py rename to gazelle/python/testdata/monorepo/coarse_grained/bar/baz/first_excluded.py diff --git a/gazelle/testdata/monorepo/coarse_grained/bar/baz/hue.py b/gazelle/python/testdata/monorepo/coarse_grained/bar/baz/hue.py similarity index 100% rename from gazelle/testdata/monorepo/coarse_grained/bar/baz/hue.py rename to gazelle/python/testdata/monorepo/coarse_grained/bar/baz/hue.py diff --git a/gazelle/testdata/monorepo/coarse_grained/bar/baz/second_excluded.py b/gazelle/python/testdata/monorepo/coarse_grained/bar/baz/second_excluded.py similarity index 100% rename from gazelle/testdata/monorepo/coarse_grained/bar/baz/second_excluded.py rename to gazelle/python/testdata/monorepo/coarse_grained/bar/baz/second_excluded.py diff --git a/gazelle/testdata/monorepo/coarse_grained/foo/__init__.py b/gazelle/python/testdata/monorepo/coarse_grained/foo/__init__.py similarity index 100% rename from gazelle/testdata/monorepo/coarse_grained/foo/__init__.py rename to gazelle/python/testdata/monorepo/coarse_grained/foo/__init__.py diff --git a/gazelle/testdata/monorepo/gazelle_python.yaml b/gazelle/python/testdata/monorepo/gazelle_python.yaml similarity index 100% rename from gazelle/testdata/monorepo/gazelle_python.yaml rename to gazelle/python/testdata/monorepo/gazelle_python.yaml diff --git a/gazelle/testdata/monorepo/one/BUILD.in b/gazelle/python/testdata/monorepo/one/BUILD.in similarity index 100% rename from gazelle/testdata/monorepo/one/BUILD.in rename to gazelle/python/testdata/monorepo/one/BUILD.in diff --git a/gazelle/testdata/monorepo/one/BUILD.out b/gazelle/python/testdata/monorepo/one/BUILD.out similarity index 100% rename from gazelle/testdata/monorepo/one/BUILD.out rename to gazelle/python/testdata/monorepo/one/BUILD.out diff --git a/gazelle/testdata/monorepo/one/__main__.py b/gazelle/python/testdata/monorepo/one/__main__.py similarity index 100% rename from gazelle/testdata/monorepo/one/__main__.py rename to gazelle/python/testdata/monorepo/one/__main__.py diff --git a/gazelle/testdata/monorepo/one/bar/BUILD.in b/gazelle/python/testdata/monorepo/one/bar/BUILD.in similarity index 100% rename from gazelle/testdata/monorepo/one/bar/BUILD.in rename to gazelle/python/testdata/monorepo/one/bar/BUILD.in diff --git a/gazelle/testdata/monorepo/one/bar/BUILD.out b/gazelle/python/testdata/monorepo/one/bar/BUILD.out similarity index 100% rename from gazelle/testdata/monorepo/one/bar/BUILD.out rename to gazelle/python/testdata/monorepo/one/bar/BUILD.out diff --git a/gazelle/testdata/monorepo/one/bar/__init__.py b/gazelle/python/testdata/monorepo/one/bar/__init__.py similarity index 100% rename from gazelle/testdata/monorepo/one/bar/__init__.py rename to gazelle/python/testdata/monorepo/one/bar/__init__.py diff --git a/gazelle/testdata/monorepo/one/bar/baz/BUILD.in b/gazelle/python/testdata/monorepo/one/bar/baz/BUILD.in similarity index 100% rename from gazelle/testdata/monorepo/one/bar/baz/BUILD.in rename to gazelle/python/testdata/monorepo/one/bar/baz/BUILD.in diff --git a/gazelle/testdata/monorepo/one/bar/baz/BUILD.out b/gazelle/python/testdata/monorepo/one/bar/baz/BUILD.out similarity index 100% rename from gazelle/testdata/monorepo/one/bar/baz/BUILD.out rename to gazelle/python/testdata/monorepo/one/bar/baz/BUILD.out diff --git a/gazelle/testdata/monorepo/one/bar/baz/__init__.py b/gazelle/python/testdata/monorepo/one/bar/baz/__init__.py similarity index 100% rename from gazelle/testdata/monorepo/one/bar/baz/__init__.py rename to gazelle/python/testdata/monorepo/one/bar/baz/__init__.py diff --git a/gazelle/testdata/monorepo/one/foo/BUILD.in b/gazelle/python/testdata/monorepo/one/foo/BUILD.in similarity index 100% rename from gazelle/testdata/monorepo/one/foo/BUILD.in rename to gazelle/python/testdata/monorepo/one/foo/BUILD.in diff --git a/gazelle/testdata/monorepo/one/foo/BUILD.out b/gazelle/python/testdata/monorepo/one/foo/BUILD.out similarity index 100% rename from gazelle/testdata/monorepo/one/foo/BUILD.out rename to gazelle/python/testdata/monorepo/one/foo/BUILD.out diff --git a/gazelle/testdata/monorepo/one/foo/__init__.py b/gazelle/python/testdata/monorepo/one/foo/__init__.py similarity index 100% rename from gazelle/testdata/monorepo/one/foo/__init__.py rename to gazelle/python/testdata/monorepo/one/foo/__init__.py diff --git a/gazelle/testdata/monorepo/one/gazelle_python.yaml b/gazelle/python/testdata/monorepo/one/gazelle_python.yaml similarity index 100% rename from gazelle/testdata/monorepo/one/gazelle_python.yaml rename to gazelle/python/testdata/monorepo/one/gazelle_python.yaml diff --git a/gazelle/testdata/monorepo/test.yaml b/gazelle/python/testdata/monorepo/test.yaml similarity index 100% rename from gazelle/testdata/monorepo/test.yaml rename to gazelle/python/testdata/monorepo/test.yaml diff --git a/gazelle/testdata/monorepo/three/BUILD.in b/gazelle/python/testdata/monorepo/three/BUILD.in similarity index 100% rename from gazelle/testdata/monorepo/three/BUILD.in rename to gazelle/python/testdata/monorepo/three/BUILD.in diff --git a/gazelle/testdata/monorepo/three/BUILD.out b/gazelle/python/testdata/monorepo/three/BUILD.out similarity index 100% rename from gazelle/testdata/monorepo/three/BUILD.out rename to gazelle/python/testdata/monorepo/three/BUILD.out diff --git a/gazelle/testdata/monorepo/three/__init__.py b/gazelle/python/testdata/monorepo/three/__init__.py similarity index 100% rename from gazelle/testdata/monorepo/three/__init__.py rename to gazelle/python/testdata/monorepo/three/__init__.py diff --git a/gazelle/testdata/monorepo/three/gazelle_python.yaml b/gazelle/python/testdata/monorepo/three/gazelle_python.yaml similarity index 100% rename from gazelle/testdata/monorepo/three/gazelle_python.yaml rename to gazelle/python/testdata/monorepo/three/gazelle_python.yaml diff --git a/gazelle/testdata/monorepo/two/BUILD.in b/gazelle/python/testdata/monorepo/two/BUILD.in similarity index 100% rename from gazelle/testdata/monorepo/two/BUILD.in rename to gazelle/python/testdata/monorepo/two/BUILD.in diff --git a/gazelle/testdata/monorepo/two/BUILD.out b/gazelle/python/testdata/monorepo/two/BUILD.out similarity index 100% rename from gazelle/testdata/monorepo/two/BUILD.out rename to gazelle/python/testdata/monorepo/two/BUILD.out diff --git a/gazelle/testdata/monorepo/two/__init__.py b/gazelle/python/testdata/monorepo/two/__init__.py similarity index 100% rename from gazelle/testdata/monorepo/two/__init__.py rename to gazelle/python/testdata/monorepo/two/__init__.py diff --git a/gazelle/testdata/monorepo/two/gazelle_python.yaml b/gazelle/python/testdata/monorepo/two/gazelle_python.yaml similarity index 100% rename from gazelle/testdata/monorepo/two/gazelle_python.yaml rename to gazelle/python/testdata/monorepo/two/gazelle_python.yaml diff --git a/gazelle/testdata/monorepo/wont_generate/BUILD.in b/gazelle/python/testdata/monorepo/wont_generate/BUILD.in similarity index 100% rename from gazelle/testdata/monorepo/wont_generate/BUILD.in rename to gazelle/python/testdata/monorepo/wont_generate/BUILD.in diff --git a/gazelle/testdata/monorepo/wont_generate/BUILD.out b/gazelle/python/testdata/monorepo/wont_generate/BUILD.out similarity index 100% rename from gazelle/testdata/monorepo/wont_generate/BUILD.out rename to gazelle/python/testdata/monorepo/wont_generate/BUILD.out diff --git a/gazelle/testdata/monorepo/wont_generate/__main__.py b/gazelle/python/testdata/monorepo/wont_generate/__main__.py similarity index 100% rename from gazelle/testdata/monorepo/wont_generate/__main__.py rename to gazelle/python/testdata/monorepo/wont_generate/__main__.py diff --git a/gazelle/testdata/monorepo/wont_generate/bar/BUILD.in b/gazelle/python/testdata/monorepo/wont_generate/bar/BUILD.in similarity index 100% rename from gazelle/testdata/monorepo/wont_generate/bar/BUILD.in rename to gazelle/python/testdata/monorepo/wont_generate/bar/BUILD.in diff --git a/gazelle/testdata/monorepo/wont_generate/bar/BUILD.out b/gazelle/python/testdata/monorepo/wont_generate/bar/BUILD.out similarity index 100% rename from gazelle/testdata/monorepo/wont_generate/bar/BUILD.out rename to gazelle/python/testdata/monorepo/wont_generate/bar/BUILD.out diff --git a/gazelle/testdata/monorepo/wont_generate/bar/__init__.py b/gazelle/python/testdata/monorepo/wont_generate/bar/__init__.py similarity index 100% rename from gazelle/testdata/monorepo/wont_generate/bar/__init__.py rename to gazelle/python/testdata/monorepo/wont_generate/bar/__init__.py diff --git a/gazelle/testdata/monorepo/wont_generate/bar/baz/BUILD.in b/gazelle/python/testdata/monorepo/wont_generate/bar/baz/BUILD.in similarity index 100% rename from gazelle/testdata/monorepo/wont_generate/bar/baz/BUILD.in rename to gazelle/python/testdata/monorepo/wont_generate/bar/baz/BUILD.in diff --git a/gazelle/testdata/monorepo/wont_generate/bar/baz/BUILD.out b/gazelle/python/testdata/monorepo/wont_generate/bar/baz/BUILD.out similarity index 100% rename from gazelle/testdata/monorepo/wont_generate/bar/baz/BUILD.out rename to gazelle/python/testdata/monorepo/wont_generate/bar/baz/BUILD.out diff --git a/gazelle/testdata/monorepo/wont_generate/bar/baz/__init__.py b/gazelle/python/testdata/monorepo/wont_generate/bar/baz/__init__.py similarity index 100% rename from gazelle/testdata/monorepo/wont_generate/bar/baz/__init__.py rename to gazelle/python/testdata/monorepo/wont_generate/bar/baz/__init__.py diff --git a/gazelle/testdata/monorepo/wont_generate/foo/BUILD.in b/gazelle/python/testdata/monorepo/wont_generate/foo/BUILD.in similarity index 100% rename from gazelle/testdata/monorepo/wont_generate/foo/BUILD.in rename to gazelle/python/testdata/monorepo/wont_generate/foo/BUILD.in diff --git a/gazelle/testdata/monorepo/wont_generate/foo/BUILD.out b/gazelle/python/testdata/monorepo/wont_generate/foo/BUILD.out similarity index 100% rename from gazelle/testdata/monorepo/wont_generate/foo/BUILD.out rename to gazelle/python/testdata/monorepo/wont_generate/foo/BUILD.out diff --git a/gazelle/testdata/monorepo/wont_generate/foo/__init__.py b/gazelle/python/testdata/monorepo/wont_generate/foo/__init__.py similarity index 100% rename from gazelle/testdata/monorepo/wont_generate/foo/__init__.py rename to gazelle/python/testdata/monorepo/wont_generate/foo/__init__.py diff --git a/gazelle/testdata/naming_convention/BUILD.in b/gazelle/python/testdata/naming_convention/BUILD.in similarity index 100% rename from gazelle/testdata/naming_convention/BUILD.in rename to gazelle/python/testdata/naming_convention/BUILD.in diff --git a/gazelle/testdata/naming_convention/BUILD.out b/gazelle/python/testdata/naming_convention/BUILD.out similarity index 100% rename from gazelle/testdata/naming_convention/BUILD.out rename to gazelle/python/testdata/naming_convention/BUILD.out diff --git a/gazelle/testdata/naming_convention/README.md b/gazelle/python/testdata/naming_convention/README.md similarity index 100% rename from gazelle/testdata/naming_convention/README.md rename to gazelle/python/testdata/naming_convention/README.md diff --git a/gazelle/testdata/naming_convention/WORKSPACE b/gazelle/python/testdata/naming_convention/WORKSPACE similarity index 100% rename from gazelle/testdata/naming_convention/WORKSPACE rename to gazelle/python/testdata/naming_convention/WORKSPACE diff --git a/gazelle/testdata/naming_convention/__init__.py b/gazelle/python/testdata/naming_convention/__init__.py similarity index 100% rename from gazelle/testdata/naming_convention/__init__.py rename to gazelle/python/testdata/naming_convention/__init__.py diff --git a/gazelle/testdata/naming_convention/__main__.py b/gazelle/python/testdata/naming_convention/__main__.py similarity index 100% rename from gazelle/testdata/naming_convention/__main__.py rename to gazelle/python/testdata/naming_convention/__main__.py diff --git a/gazelle/testdata/naming_convention/__test__.py b/gazelle/python/testdata/naming_convention/__test__.py similarity index 100% rename from gazelle/testdata/naming_convention/__test__.py rename to gazelle/python/testdata/naming_convention/__test__.py diff --git a/gazelle/testdata/naming_convention/dont_rename/BUILD.in b/gazelle/python/testdata/naming_convention/dont_rename/BUILD.in similarity index 100% rename from gazelle/testdata/naming_convention/dont_rename/BUILD.in rename to gazelle/python/testdata/naming_convention/dont_rename/BUILD.in diff --git a/gazelle/testdata/naming_convention/dont_rename/BUILD.out b/gazelle/python/testdata/naming_convention/dont_rename/BUILD.out similarity index 100% rename from gazelle/testdata/naming_convention/dont_rename/BUILD.out rename to gazelle/python/testdata/naming_convention/dont_rename/BUILD.out diff --git a/gazelle/testdata/naming_convention/dont_rename/__init__.py b/gazelle/python/testdata/naming_convention/dont_rename/__init__.py similarity index 100% rename from gazelle/testdata/naming_convention/dont_rename/__init__.py rename to gazelle/python/testdata/naming_convention/dont_rename/__init__.py diff --git a/gazelle/testdata/naming_convention/dont_rename/__main__.py b/gazelle/python/testdata/naming_convention/dont_rename/__main__.py similarity index 100% rename from gazelle/testdata/naming_convention/dont_rename/__main__.py rename to gazelle/python/testdata/naming_convention/dont_rename/__main__.py diff --git a/gazelle/testdata/naming_convention/dont_rename/__test__.py b/gazelle/python/testdata/naming_convention/dont_rename/__test__.py similarity index 100% rename from gazelle/testdata/naming_convention/dont_rename/__test__.py rename to gazelle/python/testdata/naming_convention/dont_rename/__test__.py diff --git a/gazelle/testdata/naming_convention/resolve_conflict/BUILD.in b/gazelle/python/testdata/naming_convention/resolve_conflict/BUILD.in similarity index 100% rename from gazelle/testdata/naming_convention/resolve_conflict/BUILD.in rename to gazelle/python/testdata/naming_convention/resolve_conflict/BUILD.in diff --git a/gazelle/testdata/naming_convention/resolve_conflict/BUILD.out b/gazelle/python/testdata/naming_convention/resolve_conflict/BUILD.out similarity index 100% rename from gazelle/testdata/naming_convention/resolve_conflict/BUILD.out rename to gazelle/python/testdata/naming_convention/resolve_conflict/BUILD.out diff --git a/gazelle/testdata/naming_convention/resolve_conflict/__init__.py b/gazelle/python/testdata/naming_convention/resolve_conflict/__init__.py similarity index 100% rename from gazelle/testdata/naming_convention/resolve_conflict/__init__.py rename to gazelle/python/testdata/naming_convention/resolve_conflict/__init__.py diff --git a/gazelle/testdata/naming_convention/resolve_conflict/__main__.py b/gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py similarity index 100% rename from gazelle/testdata/naming_convention/resolve_conflict/__main__.py rename to gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py diff --git a/gazelle/testdata/naming_convention/resolve_conflict/__test__.py b/gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py similarity index 100% rename from gazelle/testdata/naming_convention/resolve_conflict/__test__.py rename to gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py diff --git a/gazelle/testdata/naming_convention/test.yaml b/gazelle/python/testdata/naming_convention/test.yaml similarity index 100% rename from gazelle/testdata/naming_convention/test.yaml rename to gazelle/python/testdata/naming_convention/test.yaml diff --git a/gazelle/testdata/naming_convention_binary_fail/BUILD.in b/gazelle/python/testdata/naming_convention_binary_fail/BUILD.in similarity index 100% rename from gazelle/testdata/naming_convention_binary_fail/BUILD.in rename to gazelle/python/testdata/naming_convention_binary_fail/BUILD.in diff --git a/gazelle/testdata/naming_convention_binary_fail/BUILD.out b/gazelle/python/testdata/naming_convention_binary_fail/BUILD.out similarity index 100% rename from gazelle/testdata/naming_convention_binary_fail/BUILD.out rename to gazelle/python/testdata/naming_convention_binary_fail/BUILD.out diff --git a/gazelle/testdata/naming_convention_binary_fail/README.md b/gazelle/python/testdata/naming_convention_binary_fail/README.md similarity index 100% rename from gazelle/testdata/naming_convention_binary_fail/README.md rename to gazelle/python/testdata/naming_convention_binary_fail/README.md diff --git a/gazelle/testdata/naming_convention_binary_fail/WORKSPACE b/gazelle/python/testdata/naming_convention_binary_fail/WORKSPACE similarity index 100% rename from gazelle/testdata/naming_convention_binary_fail/WORKSPACE rename to gazelle/python/testdata/naming_convention_binary_fail/WORKSPACE diff --git a/gazelle/testdata/naming_convention_binary_fail/__main__.py b/gazelle/python/testdata/naming_convention_binary_fail/__main__.py similarity index 100% rename from gazelle/testdata/naming_convention_binary_fail/__main__.py rename to gazelle/python/testdata/naming_convention_binary_fail/__main__.py diff --git a/gazelle/testdata/naming_convention_binary_fail/test.yaml b/gazelle/python/testdata/naming_convention_binary_fail/test.yaml similarity index 100% rename from gazelle/testdata/naming_convention_binary_fail/test.yaml rename to gazelle/python/testdata/naming_convention_binary_fail/test.yaml diff --git a/gazelle/testdata/naming_convention_library_fail/BUILD.in b/gazelle/python/testdata/naming_convention_library_fail/BUILD.in similarity index 100% rename from gazelle/testdata/naming_convention_library_fail/BUILD.in rename to gazelle/python/testdata/naming_convention_library_fail/BUILD.in diff --git a/gazelle/testdata/naming_convention_library_fail/BUILD.out b/gazelle/python/testdata/naming_convention_library_fail/BUILD.out similarity index 100% rename from gazelle/testdata/naming_convention_library_fail/BUILD.out rename to gazelle/python/testdata/naming_convention_library_fail/BUILD.out diff --git a/gazelle/testdata/naming_convention_library_fail/README.md b/gazelle/python/testdata/naming_convention_library_fail/README.md similarity index 100% rename from gazelle/testdata/naming_convention_library_fail/README.md rename to gazelle/python/testdata/naming_convention_library_fail/README.md diff --git a/gazelle/testdata/naming_convention_library_fail/WORKSPACE b/gazelle/python/testdata/naming_convention_library_fail/WORKSPACE similarity index 100% rename from gazelle/testdata/naming_convention_library_fail/WORKSPACE rename to gazelle/python/testdata/naming_convention_library_fail/WORKSPACE diff --git a/gazelle/testdata/naming_convention_library_fail/__init__.py b/gazelle/python/testdata/naming_convention_library_fail/__init__.py similarity index 100% rename from gazelle/testdata/naming_convention_library_fail/__init__.py rename to gazelle/python/testdata/naming_convention_library_fail/__init__.py diff --git a/gazelle/testdata/naming_convention_library_fail/test.yaml b/gazelle/python/testdata/naming_convention_library_fail/test.yaml similarity index 100% rename from gazelle/testdata/naming_convention_library_fail/test.yaml rename to gazelle/python/testdata/naming_convention_library_fail/test.yaml diff --git a/gazelle/testdata/naming_convention_test_fail/BUILD.in b/gazelle/python/testdata/naming_convention_test_fail/BUILD.in similarity index 100% rename from gazelle/testdata/naming_convention_test_fail/BUILD.in rename to gazelle/python/testdata/naming_convention_test_fail/BUILD.in diff --git a/gazelle/testdata/naming_convention_test_fail/BUILD.out b/gazelle/python/testdata/naming_convention_test_fail/BUILD.out similarity index 100% rename from gazelle/testdata/naming_convention_test_fail/BUILD.out rename to gazelle/python/testdata/naming_convention_test_fail/BUILD.out diff --git a/gazelle/testdata/naming_convention_test_fail/README.md b/gazelle/python/testdata/naming_convention_test_fail/README.md similarity index 100% rename from gazelle/testdata/naming_convention_test_fail/README.md rename to gazelle/python/testdata/naming_convention_test_fail/README.md diff --git a/gazelle/testdata/naming_convention_test_fail/WORKSPACE b/gazelle/python/testdata/naming_convention_test_fail/WORKSPACE similarity index 100% rename from gazelle/testdata/naming_convention_test_fail/WORKSPACE rename to gazelle/python/testdata/naming_convention_test_fail/WORKSPACE diff --git a/gazelle/testdata/naming_convention_test_fail/__test__.py b/gazelle/python/testdata/naming_convention_test_fail/__test__.py similarity index 100% rename from gazelle/testdata/naming_convention_test_fail/__test__.py rename to gazelle/python/testdata/naming_convention_test_fail/__test__.py diff --git a/gazelle/testdata/naming_convention_test_fail/test.yaml b/gazelle/python/testdata/naming_convention_test_fail/test.yaml similarity index 100% rename from gazelle/testdata/naming_convention_test_fail/test.yaml rename to gazelle/python/testdata/naming_convention_test_fail/test.yaml diff --git a/gazelle/testdata/python_ignore_dependencies_directive/BUILD.in b/gazelle/python/testdata/python_ignore_dependencies_directive/BUILD.in similarity index 100% rename from gazelle/testdata/python_ignore_dependencies_directive/BUILD.in rename to gazelle/python/testdata/python_ignore_dependencies_directive/BUILD.in diff --git a/gazelle/testdata/python_ignore_dependencies_directive/BUILD.out b/gazelle/python/testdata/python_ignore_dependencies_directive/BUILD.out similarity index 100% rename from gazelle/testdata/python_ignore_dependencies_directive/BUILD.out rename to gazelle/python/testdata/python_ignore_dependencies_directive/BUILD.out diff --git a/gazelle/testdata/python_ignore_dependencies_directive/README.md b/gazelle/python/testdata/python_ignore_dependencies_directive/README.md similarity index 100% rename from gazelle/testdata/python_ignore_dependencies_directive/README.md rename to gazelle/python/testdata/python_ignore_dependencies_directive/README.md diff --git a/gazelle/testdata/python_ignore_dependencies_directive/WORKSPACE b/gazelle/python/testdata/python_ignore_dependencies_directive/WORKSPACE similarity index 100% rename from gazelle/testdata/python_ignore_dependencies_directive/WORKSPACE rename to gazelle/python/testdata/python_ignore_dependencies_directive/WORKSPACE diff --git a/gazelle/testdata/python_ignore_dependencies_directive/__init__.py b/gazelle/python/testdata/python_ignore_dependencies_directive/__init__.py similarity index 100% rename from gazelle/testdata/python_ignore_dependencies_directive/__init__.py rename to gazelle/python/testdata/python_ignore_dependencies_directive/__init__.py diff --git a/gazelle/testdata/python_ignore_dependencies_directive/gazelle_python.yaml b/gazelle/python/testdata/python_ignore_dependencies_directive/gazelle_python.yaml similarity index 100% rename from gazelle/testdata/python_ignore_dependencies_directive/gazelle_python.yaml rename to gazelle/python/testdata/python_ignore_dependencies_directive/gazelle_python.yaml diff --git a/gazelle/testdata/python_ignore_dependencies_directive/test.yaml b/gazelle/python/testdata/python_ignore_dependencies_directive/test.yaml similarity index 100% rename from gazelle/testdata/python_ignore_dependencies_directive/test.yaml rename to gazelle/python/testdata/python_ignore_dependencies_directive/test.yaml diff --git a/gazelle/testdata/python_ignore_files_directive/BUILD.in b/gazelle/python/testdata/python_ignore_files_directive/BUILD.in similarity index 100% rename from gazelle/testdata/python_ignore_files_directive/BUILD.in rename to gazelle/python/testdata/python_ignore_files_directive/BUILD.in diff --git a/gazelle/testdata/python_ignore_files_directive/BUILD.out b/gazelle/python/testdata/python_ignore_files_directive/BUILD.out similarity index 100% rename from gazelle/testdata/python_ignore_files_directive/BUILD.out rename to gazelle/python/testdata/python_ignore_files_directive/BUILD.out diff --git a/gazelle/testdata/python_ignore_files_directive/README.md b/gazelle/python/testdata/python_ignore_files_directive/README.md similarity index 100% rename from gazelle/testdata/python_ignore_files_directive/README.md rename to gazelle/python/testdata/python_ignore_files_directive/README.md diff --git a/gazelle/testdata/python_ignore_files_directive/WORKSPACE b/gazelle/python/testdata/python_ignore_files_directive/WORKSPACE similarity index 100% rename from gazelle/testdata/python_ignore_files_directive/WORKSPACE rename to gazelle/python/testdata/python_ignore_files_directive/WORKSPACE diff --git a/gazelle/testdata/python_ignore_files_directive/__init__.py b/gazelle/python/testdata/python_ignore_files_directive/__init__.py similarity index 100% rename from gazelle/testdata/python_ignore_files_directive/__init__.py rename to gazelle/python/testdata/python_ignore_files_directive/__init__.py diff --git a/gazelle/testdata/python_ignore_files_directive/bar/BUILD.in b/gazelle/python/testdata/python_ignore_files_directive/bar/BUILD.in similarity index 100% rename from gazelle/testdata/python_ignore_files_directive/bar/BUILD.in rename to gazelle/python/testdata/python_ignore_files_directive/bar/BUILD.in diff --git a/gazelle/testdata/python_ignore_files_directive/bar/BUILD.out b/gazelle/python/testdata/python_ignore_files_directive/bar/BUILD.out similarity index 100% rename from gazelle/testdata/python_ignore_files_directive/bar/BUILD.out rename to gazelle/python/testdata/python_ignore_files_directive/bar/BUILD.out diff --git a/gazelle/testdata/python_ignore_files_directive/bar/baz.py b/gazelle/python/testdata/python_ignore_files_directive/bar/baz.py similarity index 100% rename from gazelle/testdata/python_ignore_files_directive/bar/baz.py rename to gazelle/python/testdata/python_ignore_files_directive/bar/baz.py diff --git a/gazelle/testdata/python_ignore_files_directive/bar/some_other.py b/gazelle/python/testdata/python_ignore_files_directive/bar/some_other.py similarity index 100% rename from gazelle/testdata/python_ignore_files_directive/bar/some_other.py rename to gazelle/python/testdata/python_ignore_files_directive/bar/some_other.py diff --git a/gazelle/testdata/python_ignore_files_directive/foo/BUILD.in b/gazelle/python/testdata/python_ignore_files_directive/foo/BUILD.in similarity index 100% rename from gazelle/testdata/python_ignore_files_directive/foo/BUILD.in rename to gazelle/python/testdata/python_ignore_files_directive/foo/BUILD.in diff --git a/gazelle/testdata/python_ignore_files_directive/foo/BUILD.out b/gazelle/python/testdata/python_ignore_files_directive/foo/BUILD.out similarity index 100% rename from gazelle/testdata/python_ignore_files_directive/foo/BUILD.out rename to gazelle/python/testdata/python_ignore_files_directive/foo/BUILD.out diff --git a/gazelle/testdata/python_ignore_files_directive/foo/baz.py b/gazelle/python/testdata/python_ignore_files_directive/foo/baz.py similarity index 100% rename from gazelle/testdata/python_ignore_files_directive/foo/baz.py rename to gazelle/python/testdata/python_ignore_files_directive/foo/baz.py diff --git a/gazelle/testdata/python_ignore_files_directive/setup.py b/gazelle/python/testdata/python_ignore_files_directive/setup.py similarity index 100% rename from gazelle/testdata/python_ignore_files_directive/setup.py rename to gazelle/python/testdata/python_ignore_files_directive/setup.py diff --git a/gazelle/testdata/python_ignore_files_directive/some_other.py b/gazelle/python/testdata/python_ignore_files_directive/some_other.py similarity index 100% rename from gazelle/testdata/python_ignore_files_directive/some_other.py rename to gazelle/python/testdata/python_ignore_files_directive/some_other.py diff --git a/gazelle/testdata/python_ignore_files_directive/test.yaml b/gazelle/python/testdata/python_ignore_files_directive/test.yaml similarity index 100% rename from gazelle/testdata/python_ignore_files_directive/test.yaml rename to gazelle/python/testdata/python_ignore_files_directive/test.yaml diff --git a/gazelle/testdata/python_target_with_test_in_name/BUILD.in b/gazelle/python/testdata/python_target_with_test_in_name/BUILD.in similarity index 100% rename from gazelle/testdata/python_target_with_test_in_name/BUILD.in rename to gazelle/python/testdata/python_target_with_test_in_name/BUILD.in diff --git a/gazelle/testdata/python_target_with_test_in_name/BUILD.out b/gazelle/python/testdata/python_target_with_test_in_name/BUILD.out similarity index 100% rename from gazelle/testdata/python_target_with_test_in_name/BUILD.out rename to gazelle/python/testdata/python_target_with_test_in_name/BUILD.out diff --git a/gazelle/testdata/python_target_with_test_in_name/README.md b/gazelle/python/testdata/python_target_with_test_in_name/README.md similarity index 100% rename from gazelle/testdata/python_target_with_test_in_name/README.md rename to gazelle/python/testdata/python_target_with_test_in_name/README.md diff --git a/gazelle/testdata/python_target_with_test_in_name/WORKSPACE b/gazelle/python/testdata/python_target_with_test_in_name/WORKSPACE similarity index 100% rename from gazelle/testdata/python_target_with_test_in_name/WORKSPACE rename to gazelle/python/testdata/python_target_with_test_in_name/WORKSPACE diff --git a/gazelle/testdata/python_target_with_test_in_name/__init__.py b/gazelle/python/testdata/python_target_with_test_in_name/__init__.py similarity index 100% rename from gazelle/testdata/python_target_with_test_in_name/__init__.py rename to gazelle/python/testdata/python_target_with_test_in_name/__init__.py diff --git a/gazelle/testdata/python_target_with_test_in_name/gazelle_python.yaml b/gazelle/python/testdata/python_target_with_test_in_name/gazelle_python.yaml similarity index 100% rename from gazelle/testdata/python_target_with_test_in_name/gazelle_python.yaml rename to gazelle/python/testdata/python_target_with_test_in_name/gazelle_python.yaml diff --git a/gazelle/testdata/python_target_with_test_in_name/real_test.py b/gazelle/python/testdata/python_target_with_test_in_name/real_test.py similarity index 100% rename from gazelle/testdata/python_target_with_test_in_name/real_test.py rename to gazelle/python/testdata/python_target_with_test_in_name/real_test.py diff --git a/gazelle/testdata/python_target_with_test_in_name/test.yaml b/gazelle/python/testdata/python_target_with_test_in_name/test.yaml similarity index 100% rename from gazelle/testdata/python_target_with_test_in_name/test.yaml rename to gazelle/python/testdata/python_target_with_test_in_name/test.yaml diff --git a/gazelle/testdata/python_target_with_test_in_name/test_reality.py b/gazelle/python/testdata/python_target_with_test_in_name/test_reality.py similarity index 100% rename from gazelle/testdata/python_target_with_test_in_name/test_reality.py rename to gazelle/python/testdata/python_target_with_test_in_name/test_reality.py diff --git a/gazelle/testdata/relative_imports/BUILD.in b/gazelle/python/testdata/relative_imports/BUILD.in similarity index 100% rename from gazelle/testdata/relative_imports/BUILD.in rename to gazelle/python/testdata/relative_imports/BUILD.in diff --git a/gazelle/testdata/relative_imports/BUILD.out b/gazelle/python/testdata/relative_imports/BUILD.out similarity index 100% rename from gazelle/testdata/relative_imports/BUILD.out rename to gazelle/python/testdata/relative_imports/BUILD.out diff --git a/gazelle/testdata/relative_imports/README.md b/gazelle/python/testdata/relative_imports/README.md similarity index 100% rename from gazelle/testdata/relative_imports/README.md rename to gazelle/python/testdata/relative_imports/README.md diff --git a/gazelle/testdata/relative_imports/WORKSPACE b/gazelle/python/testdata/relative_imports/WORKSPACE similarity index 100% rename from gazelle/testdata/relative_imports/WORKSPACE rename to gazelle/python/testdata/relative_imports/WORKSPACE diff --git a/gazelle/testdata/relative_imports/__main__.py b/gazelle/python/testdata/relative_imports/__main__.py similarity index 100% rename from gazelle/testdata/relative_imports/__main__.py rename to gazelle/python/testdata/relative_imports/__main__.py diff --git a/gazelle/testdata/relative_imports/package1/module1.py b/gazelle/python/testdata/relative_imports/package1/module1.py similarity index 100% rename from gazelle/testdata/relative_imports/package1/module1.py rename to gazelle/python/testdata/relative_imports/package1/module1.py diff --git a/gazelle/testdata/relative_imports/package1/module2.py b/gazelle/python/testdata/relative_imports/package1/module2.py similarity index 100% rename from gazelle/testdata/relative_imports/package1/module2.py rename to gazelle/python/testdata/relative_imports/package1/module2.py diff --git a/gazelle/testdata/relative_imports/package2/BUILD.in b/gazelle/python/testdata/relative_imports/package2/BUILD.in similarity index 100% rename from gazelle/testdata/relative_imports/package2/BUILD.in rename to gazelle/python/testdata/relative_imports/package2/BUILD.in diff --git a/gazelle/testdata/relative_imports/package2/BUILD.out b/gazelle/python/testdata/relative_imports/package2/BUILD.out similarity index 100% rename from gazelle/testdata/relative_imports/package2/BUILD.out rename to gazelle/python/testdata/relative_imports/package2/BUILD.out diff --git a/gazelle/testdata/relative_imports/package2/__init__.py b/gazelle/python/testdata/relative_imports/package2/__init__.py similarity index 100% rename from gazelle/testdata/relative_imports/package2/__init__.py rename to gazelle/python/testdata/relative_imports/package2/__init__.py diff --git a/gazelle/testdata/relative_imports/package2/module3.py b/gazelle/python/testdata/relative_imports/package2/module3.py similarity index 100% rename from gazelle/testdata/relative_imports/package2/module3.py rename to gazelle/python/testdata/relative_imports/package2/module3.py diff --git a/gazelle/testdata/relative_imports/package2/module4.py b/gazelle/python/testdata/relative_imports/package2/module4.py similarity index 100% rename from gazelle/testdata/relative_imports/package2/module4.py rename to gazelle/python/testdata/relative_imports/package2/module4.py diff --git a/gazelle/testdata/relative_imports/package2/subpackage1/module5.py b/gazelle/python/testdata/relative_imports/package2/subpackage1/module5.py similarity index 100% rename from gazelle/testdata/relative_imports/package2/subpackage1/module5.py rename to gazelle/python/testdata/relative_imports/package2/subpackage1/module5.py diff --git a/gazelle/testdata/relative_imports/test.yaml b/gazelle/python/testdata/relative_imports/test.yaml similarity index 100% rename from gazelle/testdata/relative_imports/test.yaml rename to gazelle/python/testdata/relative_imports/test.yaml diff --git a/gazelle/testdata/simple_binary/BUILD.in b/gazelle/python/testdata/simple_binary/BUILD.in similarity index 100% rename from gazelle/testdata/simple_binary/BUILD.in rename to gazelle/python/testdata/simple_binary/BUILD.in diff --git a/gazelle/testdata/simple_binary/BUILD.out b/gazelle/python/testdata/simple_binary/BUILD.out similarity index 100% rename from gazelle/testdata/simple_binary/BUILD.out rename to gazelle/python/testdata/simple_binary/BUILD.out diff --git a/gazelle/testdata/simple_binary/README.md b/gazelle/python/testdata/simple_binary/README.md similarity index 100% rename from gazelle/testdata/simple_binary/README.md rename to gazelle/python/testdata/simple_binary/README.md diff --git a/gazelle/testdata/simple_binary/WORKSPACE b/gazelle/python/testdata/simple_binary/WORKSPACE similarity index 100% rename from gazelle/testdata/simple_binary/WORKSPACE rename to gazelle/python/testdata/simple_binary/WORKSPACE diff --git a/gazelle/testdata/simple_binary/__main__.py b/gazelle/python/testdata/simple_binary/__main__.py similarity index 100% rename from gazelle/testdata/simple_binary/__main__.py rename to gazelle/python/testdata/simple_binary/__main__.py diff --git a/gazelle/testdata/simple_binary/test.yaml b/gazelle/python/testdata/simple_binary/test.yaml similarity index 100% rename from gazelle/testdata/simple_binary/test.yaml rename to gazelle/python/testdata/simple_binary/test.yaml diff --git a/gazelle/testdata/simple_binary_with_library/BUILD.in b/gazelle/python/testdata/simple_binary_with_library/BUILD.in similarity index 100% rename from gazelle/testdata/simple_binary_with_library/BUILD.in rename to gazelle/python/testdata/simple_binary_with_library/BUILD.in diff --git a/gazelle/testdata/simple_binary_with_library/BUILD.out b/gazelle/python/testdata/simple_binary_with_library/BUILD.out similarity index 100% rename from gazelle/testdata/simple_binary_with_library/BUILD.out rename to gazelle/python/testdata/simple_binary_with_library/BUILD.out diff --git a/gazelle/testdata/simple_binary_with_library/README.md b/gazelle/python/testdata/simple_binary_with_library/README.md similarity index 100% rename from gazelle/testdata/simple_binary_with_library/README.md rename to gazelle/python/testdata/simple_binary_with_library/README.md diff --git a/gazelle/testdata/simple_binary_with_library/WORKSPACE b/gazelle/python/testdata/simple_binary_with_library/WORKSPACE similarity index 100% rename from gazelle/testdata/simple_binary_with_library/WORKSPACE rename to gazelle/python/testdata/simple_binary_with_library/WORKSPACE diff --git a/gazelle/testdata/simple_binary_with_library/__init__.py b/gazelle/python/testdata/simple_binary_with_library/__init__.py similarity index 100% rename from gazelle/testdata/simple_binary_with_library/__init__.py rename to gazelle/python/testdata/simple_binary_with_library/__init__.py diff --git a/gazelle/testdata/simple_binary_with_library/__main__.py b/gazelle/python/testdata/simple_binary_with_library/__main__.py similarity index 100% rename from gazelle/testdata/simple_binary_with_library/__main__.py rename to gazelle/python/testdata/simple_binary_with_library/__main__.py diff --git a/gazelle/testdata/simple_binary_with_library/bar.py b/gazelle/python/testdata/simple_binary_with_library/bar.py similarity index 100% rename from gazelle/testdata/simple_binary_with_library/bar.py rename to gazelle/python/testdata/simple_binary_with_library/bar.py diff --git a/gazelle/testdata/simple_binary_with_library/foo.py b/gazelle/python/testdata/simple_binary_with_library/foo.py similarity index 100% rename from gazelle/testdata/simple_binary_with_library/foo.py rename to gazelle/python/testdata/simple_binary_with_library/foo.py diff --git a/gazelle/testdata/simple_binary_with_library/test.yaml b/gazelle/python/testdata/simple_binary_with_library/test.yaml similarity index 100% rename from gazelle/testdata/simple_binary_with_library/test.yaml rename to gazelle/python/testdata/simple_binary_with_library/test.yaml diff --git a/gazelle/testdata/simple_library/BUILD.in b/gazelle/python/testdata/simple_library/BUILD.in similarity index 100% rename from gazelle/testdata/simple_library/BUILD.in rename to gazelle/python/testdata/simple_library/BUILD.in diff --git a/gazelle/testdata/simple_library/BUILD.out b/gazelle/python/testdata/simple_library/BUILD.out similarity index 100% rename from gazelle/testdata/simple_library/BUILD.out rename to gazelle/python/testdata/simple_library/BUILD.out diff --git a/gazelle/testdata/simple_library/README.md b/gazelle/python/testdata/simple_library/README.md similarity index 100% rename from gazelle/testdata/simple_library/README.md rename to gazelle/python/testdata/simple_library/README.md diff --git a/gazelle/testdata/simple_library/WORKSPACE b/gazelle/python/testdata/simple_library/WORKSPACE similarity index 100% rename from gazelle/testdata/simple_library/WORKSPACE rename to gazelle/python/testdata/simple_library/WORKSPACE diff --git a/gazelle/testdata/simple_library/__init__.py b/gazelle/python/testdata/simple_library/__init__.py similarity index 100% rename from gazelle/testdata/simple_library/__init__.py rename to gazelle/python/testdata/simple_library/__init__.py diff --git a/gazelle/testdata/simple_library/test.yaml b/gazelle/python/testdata/simple_library/test.yaml similarity index 100% rename from gazelle/testdata/simple_library/test.yaml rename to gazelle/python/testdata/simple_library/test.yaml diff --git a/gazelle/testdata/simple_library_without_init/BUILD.in b/gazelle/python/testdata/simple_library_without_init/BUILD.in similarity index 100% rename from gazelle/testdata/simple_library_without_init/BUILD.in rename to gazelle/python/testdata/simple_library_without_init/BUILD.in diff --git a/gazelle/testdata/simple_library_without_init/BUILD.out b/gazelle/python/testdata/simple_library_without_init/BUILD.out similarity index 100% rename from gazelle/testdata/simple_library_without_init/BUILD.out rename to gazelle/python/testdata/simple_library_without_init/BUILD.out diff --git a/gazelle/testdata/simple_library_without_init/README.md b/gazelle/python/testdata/simple_library_without_init/README.md similarity index 100% rename from gazelle/testdata/simple_library_without_init/README.md rename to gazelle/python/testdata/simple_library_without_init/README.md diff --git a/gazelle/testdata/simple_library_without_init/WORKSPACE b/gazelle/python/testdata/simple_library_without_init/WORKSPACE similarity index 100% rename from gazelle/testdata/simple_library_without_init/WORKSPACE rename to gazelle/python/testdata/simple_library_without_init/WORKSPACE diff --git a/gazelle/testdata/simple_library_without_init/foo/BUILD.in b/gazelle/python/testdata/simple_library_without_init/foo/BUILD.in similarity index 100% rename from gazelle/testdata/simple_library_without_init/foo/BUILD.in rename to gazelle/python/testdata/simple_library_without_init/foo/BUILD.in diff --git a/gazelle/testdata/simple_library_without_init/foo/BUILD.out b/gazelle/python/testdata/simple_library_without_init/foo/BUILD.out similarity index 100% rename from gazelle/testdata/simple_library_without_init/foo/BUILD.out rename to gazelle/python/testdata/simple_library_without_init/foo/BUILD.out diff --git a/gazelle/testdata/simple_library_without_init/foo/foo.py b/gazelle/python/testdata/simple_library_without_init/foo/foo.py similarity index 100% rename from gazelle/testdata/simple_library_without_init/foo/foo.py rename to gazelle/python/testdata/simple_library_without_init/foo/foo.py diff --git a/gazelle/testdata/simple_library_without_init/test.yaml b/gazelle/python/testdata/simple_library_without_init/test.yaml similarity index 100% rename from gazelle/testdata/simple_library_without_init/test.yaml rename to gazelle/python/testdata/simple_library_without_init/test.yaml diff --git a/gazelle/testdata/simple_test/BUILD.in b/gazelle/python/testdata/simple_test/BUILD.in similarity index 100% rename from gazelle/testdata/simple_test/BUILD.in rename to gazelle/python/testdata/simple_test/BUILD.in diff --git a/gazelle/testdata/simple_test/BUILD.out b/gazelle/python/testdata/simple_test/BUILD.out similarity index 100% rename from gazelle/testdata/simple_test/BUILD.out rename to gazelle/python/testdata/simple_test/BUILD.out diff --git a/gazelle/testdata/simple_test/README.md b/gazelle/python/testdata/simple_test/README.md similarity index 100% rename from gazelle/testdata/simple_test/README.md rename to gazelle/python/testdata/simple_test/README.md diff --git a/gazelle/testdata/simple_test/WORKSPACE b/gazelle/python/testdata/simple_test/WORKSPACE similarity index 100% rename from gazelle/testdata/simple_test/WORKSPACE rename to gazelle/python/testdata/simple_test/WORKSPACE diff --git a/gazelle/testdata/simple_test/__init__.py b/gazelle/python/testdata/simple_test/__init__.py similarity index 100% rename from gazelle/testdata/simple_test/__init__.py rename to gazelle/python/testdata/simple_test/__init__.py diff --git a/gazelle/testdata/simple_test/__test__.py b/gazelle/python/testdata/simple_test/__test__.py similarity index 100% rename from gazelle/testdata/simple_test/__test__.py rename to gazelle/python/testdata/simple_test/__test__.py diff --git a/gazelle/testdata/simple_test/foo.py b/gazelle/python/testdata/simple_test/foo.py similarity index 100% rename from gazelle/testdata/simple_test/foo.py rename to gazelle/python/testdata/simple_test/foo.py diff --git a/gazelle/testdata/simple_test/test.yaml b/gazelle/python/testdata/simple_test/test.yaml similarity index 100% rename from gazelle/testdata/simple_test/test.yaml rename to gazelle/python/testdata/simple_test/test.yaml diff --git a/gazelle/testdata/simple_test_with_conftest/BUILD.in b/gazelle/python/testdata/simple_test_with_conftest/BUILD.in similarity index 100% rename from gazelle/testdata/simple_test_with_conftest/BUILD.in rename to gazelle/python/testdata/simple_test_with_conftest/BUILD.in diff --git a/gazelle/testdata/simple_test_with_conftest/BUILD.out b/gazelle/python/testdata/simple_test_with_conftest/BUILD.out similarity index 100% rename from gazelle/testdata/simple_test_with_conftest/BUILD.out rename to gazelle/python/testdata/simple_test_with_conftest/BUILD.out diff --git a/gazelle/testdata/simple_test_with_conftest/README.md b/gazelle/python/testdata/simple_test_with_conftest/README.md similarity index 100% rename from gazelle/testdata/simple_test_with_conftest/README.md rename to gazelle/python/testdata/simple_test_with_conftest/README.md diff --git a/gazelle/testdata/simple_test_with_conftest/WORKSPACE b/gazelle/python/testdata/simple_test_with_conftest/WORKSPACE similarity index 100% rename from gazelle/testdata/simple_test_with_conftest/WORKSPACE rename to gazelle/python/testdata/simple_test_with_conftest/WORKSPACE diff --git a/gazelle/testdata/simple_test_with_conftest/__init__.py b/gazelle/python/testdata/simple_test_with_conftest/__init__.py similarity index 100% rename from gazelle/testdata/simple_test_with_conftest/__init__.py rename to gazelle/python/testdata/simple_test_with_conftest/__init__.py diff --git a/gazelle/testdata/simple_test_with_conftest/__test__.py b/gazelle/python/testdata/simple_test_with_conftest/__test__.py similarity index 100% rename from gazelle/testdata/simple_test_with_conftest/__test__.py rename to gazelle/python/testdata/simple_test_with_conftest/__test__.py diff --git a/gazelle/testdata/simple_test_with_conftest/conftest.py b/gazelle/python/testdata/simple_test_with_conftest/conftest.py similarity index 100% rename from gazelle/testdata/simple_test_with_conftest/conftest.py rename to gazelle/python/testdata/simple_test_with_conftest/conftest.py diff --git a/gazelle/testdata/simple_test_with_conftest/foo.py b/gazelle/python/testdata/simple_test_with_conftest/foo.py similarity index 100% rename from gazelle/testdata/simple_test_with_conftest/foo.py rename to gazelle/python/testdata/simple_test_with_conftest/foo.py diff --git a/gazelle/testdata/simple_test_with_conftest/test.yaml b/gazelle/python/testdata/simple_test_with_conftest/test.yaml similarity index 100% rename from gazelle/testdata/simple_test_with_conftest/test.yaml rename to gazelle/python/testdata/simple_test_with_conftest/test.yaml diff --git a/gazelle/testdata/subdir_sources/BUILD.in b/gazelle/python/testdata/subdir_sources/BUILD.in similarity index 100% rename from gazelle/testdata/subdir_sources/BUILD.in rename to gazelle/python/testdata/subdir_sources/BUILD.in diff --git a/gazelle/testdata/subdir_sources/BUILD.out b/gazelle/python/testdata/subdir_sources/BUILD.out similarity index 100% rename from gazelle/testdata/subdir_sources/BUILD.out rename to gazelle/python/testdata/subdir_sources/BUILD.out diff --git a/gazelle/testdata/subdir_sources/README.md b/gazelle/python/testdata/subdir_sources/README.md similarity index 100% rename from gazelle/testdata/subdir_sources/README.md rename to gazelle/python/testdata/subdir_sources/README.md diff --git a/gazelle/testdata/subdir_sources/WORKSPACE b/gazelle/python/testdata/subdir_sources/WORKSPACE similarity index 100% rename from gazelle/testdata/subdir_sources/WORKSPACE rename to gazelle/python/testdata/subdir_sources/WORKSPACE diff --git a/gazelle/testdata/subdir_sources/__main__.py b/gazelle/python/testdata/subdir_sources/__main__.py similarity index 100% rename from gazelle/testdata/subdir_sources/__main__.py rename to gazelle/python/testdata/subdir_sources/__main__.py diff --git a/gazelle/testdata/subdir_sources/foo/BUILD.in b/gazelle/python/testdata/subdir_sources/foo/BUILD.in similarity index 100% rename from gazelle/testdata/subdir_sources/foo/BUILD.in rename to gazelle/python/testdata/subdir_sources/foo/BUILD.in diff --git a/gazelle/testdata/subdir_sources/foo/BUILD.out b/gazelle/python/testdata/subdir_sources/foo/BUILD.out similarity index 100% rename from gazelle/testdata/subdir_sources/foo/BUILD.out rename to gazelle/python/testdata/subdir_sources/foo/BUILD.out diff --git a/gazelle/testdata/subdir_sources/foo/__init__.py b/gazelle/python/testdata/subdir_sources/foo/__init__.py similarity index 100% rename from gazelle/testdata/subdir_sources/foo/__init__.py rename to gazelle/python/testdata/subdir_sources/foo/__init__.py diff --git a/gazelle/testdata/subdir_sources/foo/bar/bar.py b/gazelle/python/testdata/subdir_sources/foo/bar/bar.py similarity index 100% rename from gazelle/testdata/subdir_sources/foo/bar/bar.py rename to gazelle/python/testdata/subdir_sources/foo/bar/bar.py diff --git a/gazelle/testdata/subdir_sources/foo/baz/baz.py b/gazelle/python/testdata/subdir_sources/foo/baz/baz.py similarity index 100% rename from gazelle/testdata/subdir_sources/foo/baz/baz.py rename to gazelle/python/testdata/subdir_sources/foo/baz/baz.py diff --git a/gazelle/testdata/subdir_sources/foo/foo.py b/gazelle/python/testdata/subdir_sources/foo/foo.py similarity index 100% rename from gazelle/testdata/subdir_sources/foo/foo.py rename to gazelle/python/testdata/subdir_sources/foo/foo.py diff --git a/gazelle/testdata/subdir_sources/foo/has_build/BUILD.in b/gazelle/python/testdata/subdir_sources/foo/has_build/BUILD.in similarity index 100% rename from gazelle/testdata/subdir_sources/foo/has_build/BUILD.in rename to gazelle/python/testdata/subdir_sources/foo/has_build/BUILD.in diff --git a/gazelle/testdata/subdir_sources/foo/has_build/BUILD.out b/gazelle/python/testdata/subdir_sources/foo/has_build/BUILD.out similarity index 100% rename from gazelle/testdata/subdir_sources/foo/has_build/BUILD.out rename to gazelle/python/testdata/subdir_sources/foo/has_build/BUILD.out diff --git a/gazelle/testdata/subdir_sources/foo/has_build/python/my_module.py b/gazelle/python/testdata/subdir_sources/foo/has_build/python/my_module.py similarity index 100% rename from gazelle/testdata/subdir_sources/foo/has_build/python/my_module.py rename to gazelle/python/testdata/subdir_sources/foo/has_build/python/my_module.py diff --git a/gazelle/testdata/subdir_sources/foo/has_build_bazel/BUILD.bazel.in b/gazelle/python/testdata/subdir_sources/foo/has_build_bazel/BUILD.bazel.in similarity index 100% rename from gazelle/testdata/subdir_sources/foo/has_build_bazel/BUILD.bazel.in rename to gazelle/python/testdata/subdir_sources/foo/has_build_bazel/BUILD.bazel.in diff --git a/gazelle/testdata/subdir_sources/foo/has_build_bazel/python/my_module.py b/gazelle/python/testdata/subdir_sources/foo/has_build_bazel/python/my_module.py similarity index 100% rename from gazelle/testdata/subdir_sources/foo/has_build_bazel/python/my_module.py rename to gazelle/python/testdata/subdir_sources/foo/has_build_bazel/python/my_module.py diff --git a/gazelle/testdata/subdir_sources/foo/has_init/BUILD.in b/gazelle/python/testdata/subdir_sources/foo/has_init/BUILD.in similarity index 100% rename from gazelle/testdata/subdir_sources/foo/has_init/BUILD.in rename to gazelle/python/testdata/subdir_sources/foo/has_init/BUILD.in diff --git a/gazelle/testdata/subdir_sources/foo/has_init/BUILD.out b/gazelle/python/testdata/subdir_sources/foo/has_init/BUILD.out similarity index 100% rename from gazelle/testdata/subdir_sources/foo/has_init/BUILD.out rename to gazelle/python/testdata/subdir_sources/foo/has_init/BUILD.out diff --git a/gazelle/testdata/subdir_sources/foo/has_init/__init__.py b/gazelle/python/testdata/subdir_sources/foo/has_init/__init__.py similarity index 100% rename from gazelle/testdata/subdir_sources/foo/has_init/__init__.py rename to gazelle/python/testdata/subdir_sources/foo/has_init/__init__.py diff --git a/gazelle/testdata/subdir_sources/foo/has_init/python/my_module.py b/gazelle/python/testdata/subdir_sources/foo/has_init/python/my_module.py similarity index 100% rename from gazelle/testdata/subdir_sources/foo/has_init/python/my_module.py rename to gazelle/python/testdata/subdir_sources/foo/has_init/python/my_module.py diff --git a/gazelle/testdata/subdir_sources/foo/has_main/BUILD.in b/gazelle/python/testdata/subdir_sources/foo/has_main/BUILD.in similarity index 100% rename from gazelle/testdata/subdir_sources/foo/has_main/BUILD.in rename to gazelle/python/testdata/subdir_sources/foo/has_main/BUILD.in diff --git a/gazelle/testdata/subdir_sources/foo/has_main/BUILD.out b/gazelle/python/testdata/subdir_sources/foo/has_main/BUILD.out similarity index 100% rename from gazelle/testdata/subdir_sources/foo/has_main/BUILD.out rename to gazelle/python/testdata/subdir_sources/foo/has_main/BUILD.out diff --git a/gazelle/testdata/subdir_sources/foo/has_main/__main__.py b/gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py similarity index 100% rename from gazelle/testdata/subdir_sources/foo/has_main/__main__.py rename to gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py diff --git a/gazelle/testdata/subdir_sources/foo/has_main/python/my_module.py b/gazelle/python/testdata/subdir_sources/foo/has_main/python/my_module.py similarity index 100% rename from gazelle/testdata/subdir_sources/foo/has_main/python/my_module.py rename to gazelle/python/testdata/subdir_sources/foo/has_main/python/my_module.py diff --git a/gazelle/testdata/subdir_sources/foo/has_test/BUILD.in b/gazelle/python/testdata/subdir_sources/foo/has_test/BUILD.in similarity index 100% rename from gazelle/testdata/subdir_sources/foo/has_test/BUILD.in rename to gazelle/python/testdata/subdir_sources/foo/has_test/BUILD.in diff --git a/gazelle/testdata/subdir_sources/foo/has_test/BUILD.out b/gazelle/python/testdata/subdir_sources/foo/has_test/BUILD.out similarity index 100% rename from gazelle/testdata/subdir_sources/foo/has_test/BUILD.out rename to gazelle/python/testdata/subdir_sources/foo/has_test/BUILD.out diff --git a/gazelle/testdata/subdir_sources/foo/has_test/__test__.py b/gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py similarity index 100% rename from gazelle/testdata/subdir_sources/foo/has_test/__test__.py rename to gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py diff --git a/gazelle/testdata/subdir_sources/foo/has_test/python/my_module.py b/gazelle/python/testdata/subdir_sources/foo/has_test/python/my_module.py similarity index 100% rename from gazelle/testdata/subdir_sources/foo/has_test/python/my_module.py rename to gazelle/python/testdata/subdir_sources/foo/has_test/python/my_module.py diff --git a/gazelle/testdata/subdir_sources/one/BUILD.in b/gazelle/python/testdata/subdir_sources/one/BUILD.in similarity index 100% rename from gazelle/testdata/subdir_sources/one/BUILD.in rename to gazelle/python/testdata/subdir_sources/one/BUILD.in diff --git a/gazelle/testdata/subdir_sources/one/BUILD.out b/gazelle/python/testdata/subdir_sources/one/BUILD.out similarity index 100% rename from gazelle/testdata/subdir_sources/one/BUILD.out rename to gazelle/python/testdata/subdir_sources/one/BUILD.out diff --git a/gazelle/testdata/subdir_sources/one/__init__.py b/gazelle/python/testdata/subdir_sources/one/__init__.py similarity index 100% rename from gazelle/testdata/subdir_sources/one/__init__.py rename to gazelle/python/testdata/subdir_sources/one/__init__.py diff --git a/gazelle/testdata/subdir_sources/one/two/BUILD.in b/gazelle/python/testdata/subdir_sources/one/two/BUILD.in similarity index 100% rename from gazelle/testdata/subdir_sources/one/two/BUILD.in rename to gazelle/python/testdata/subdir_sources/one/two/BUILD.in diff --git a/gazelle/testdata/subdir_sources/one/two/BUILD.out b/gazelle/python/testdata/subdir_sources/one/two/BUILD.out similarity index 100% rename from gazelle/testdata/subdir_sources/one/two/BUILD.out rename to gazelle/python/testdata/subdir_sources/one/two/BUILD.out diff --git a/gazelle/testdata/subdir_sources/one/two/__init__.py b/gazelle/python/testdata/subdir_sources/one/two/__init__.py similarity index 100% rename from gazelle/testdata/subdir_sources/one/two/__init__.py rename to gazelle/python/testdata/subdir_sources/one/two/__init__.py diff --git a/gazelle/testdata/subdir_sources/one/two/three.py b/gazelle/python/testdata/subdir_sources/one/two/three.py similarity index 100% rename from gazelle/testdata/subdir_sources/one/two/three.py rename to gazelle/python/testdata/subdir_sources/one/two/three.py diff --git a/gazelle/testdata/subdir_sources/test.yaml b/gazelle/python/testdata/subdir_sources/test.yaml similarity index 100% rename from gazelle/testdata/subdir_sources/test.yaml rename to gazelle/python/testdata/subdir_sources/test.yaml diff --git a/gazelle/testdata/with_nested_import_statements/BUILD.in b/gazelle/python/testdata/with_nested_import_statements/BUILD.in similarity index 100% rename from gazelle/testdata/with_nested_import_statements/BUILD.in rename to gazelle/python/testdata/with_nested_import_statements/BUILD.in diff --git a/gazelle/testdata/with_nested_import_statements/BUILD.out b/gazelle/python/testdata/with_nested_import_statements/BUILD.out similarity index 100% rename from gazelle/testdata/with_nested_import_statements/BUILD.out rename to gazelle/python/testdata/with_nested_import_statements/BUILD.out diff --git a/gazelle/testdata/with_nested_import_statements/README.md b/gazelle/python/testdata/with_nested_import_statements/README.md similarity index 100% rename from gazelle/testdata/with_nested_import_statements/README.md rename to gazelle/python/testdata/with_nested_import_statements/README.md diff --git a/gazelle/testdata/with_nested_import_statements/WORKSPACE b/gazelle/python/testdata/with_nested_import_statements/WORKSPACE similarity index 100% rename from gazelle/testdata/with_nested_import_statements/WORKSPACE rename to gazelle/python/testdata/with_nested_import_statements/WORKSPACE diff --git a/gazelle/testdata/with_nested_import_statements/__init__.py b/gazelle/python/testdata/with_nested_import_statements/__init__.py similarity index 100% rename from gazelle/testdata/with_nested_import_statements/__init__.py rename to gazelle/python/testdata/with_nested_import_statements/__init__.py diff --git a/gazelle/testdata/with_nested_import_statements/gazelle_python.yaml b/gazelle/python/testdata/with_nested_import_statements/gazelle_python.yaml similarity index 100% rename from gazelle/testdata/with_nested_import_statements/gazelle_python.yaml rename to gazelle/python/testdata/with_nested_import_statements/gazelle_python.yaml diff --git a/gazelle/testdata/with_nested_import_statements/test.yaml b/gazelle/python/testdata/with_nested_import_statements/test.yaml similarity index 100% rename from gazelle/testdata/with_nested_import_statements/test.yaml rename to gazelle/python/testdata/with_nested_import_statements/test.yaml diff --git a/gazelle/testdata/with_std_requirements/BUILD.in b/gazelle/python/testdata/with_std_requirements/BUILD.in similarity index 100% rename from gazelle/testdata/with_std_requirements/BUILD.in rename to gazelle/python/testdata/with_std_requirements/BUILD.in diff --git a/gazelle/testdata/with_std_requirements/BUILD.out b/gazelle/python/testdata/with_std_requirements/BUILD.out similarity index 100% rename from gazelle/testdata/with_std_requirements/BUILD.out rename to gazelle/python/testdata/with_std_requirements/BUILD.out diff --git a/gazelle/testdata/with_std_requirements/README.md b/gazelle/python/testdata/with_std_requirements/README.md similarity index 100% rename from gazelle/testdata/with_std_requirements/README.md rename to gazelle/python/testdata/with_std_requirements/README.md diff --git a/gazelle/testdata/with_std_requirements/WORKSPACE b/gazelle/python/testdata/with_std_requirements/WORKSPACE similarity index 100% rename from gazelle/testdata/with_std_requirements/WORKSPACE rename to gazelle/python/testdata/with_std_requirements/WORKSPACE diff --git a/gazelle/testdata/with_std_requirements/__init__.py b/gazelle/python/testdata/with_std_requirements/__init__.py similarity index 100% rename from gazelle/testdata/with_std_requirements/__init__.py rename to gazelle/python/testdata/with_std_requirements/__init__.py diff --git a/gazelle/testdata/with_std_requirements/test.yaml b/gazelle/python/testdata/with_std_requirements/test.yaml similarity index 100% rename from gazelle/testdata/with_std_requirements/test.yaml rename to gazelle/python/testdata/with_std_requirements/test.yaml diff --git a/gazelle/testdata/with_third_party_requirements/BUILD.in b/gazelle/python/testdata/with_third_party_requirements/BUILD.in similarity index 100% rename from gazelle/testdata/with_third_party_requirements/BUILD.in rename to gazelle/python/testdata/with_third_party_requirements/BUILD.in diff --git a/gazelle/testdata/with_third_party_requirements/BUILD.out b/gazelle/python/testdata/with_third_party_requirements/BUILD.out similarity index 100% rename from gazelle/testdata/with_third_party_requirements/BUILD.out rename to gazelle/python/testdata/with_third_party_requirements/BUILD.out diff --git a/gazelle/testdata/with_third_party_requirements/README.md b/gazelle/python/testdata/with_third_party_requirements/README.md similarity index 100% rename from gazelle/testdata/with_third_party_requirements/README.md rename to gazelle/python/testdata/with_third_party_requirements/README.md diff --git a/gazelle/testdata/with_third_party_requirements/WORKSPACE b/gazelle/python/testdata/with_third_party_requirements/WORKSPACE similarity index 100% rename from gazelle/testdata/with_third_party_requirements/WORKSPACE rename to gazelle/python/testdata/with_third_party_requirements/WORKSPACE diff --git a/gazelle/testdata/with_third_party_requirements/__init__.py b/gazelle/python/testdata/with_third_party_requirements/__init__.py similarity index 100% rename from gazelle/testdata/with_third_party_requirements/__init__.py rename to gazelle/python/testdata/with_third_party_requirements/__init__.py diff --git a/gazelle/testdata/with_third_party_requirements/__main__.py b/gazelle/python/testdata/with_third_party_requirements/__main__.py similarity index 100% rename from gazelle/testdata/with_third_party_requirements/__main__.py rename to gazelle/python/testdata/with_third_party_requirements/__main__.py diff --git a/gazelle/testdata/with_third_party_requirements/bar.py b/gazelle/python/testdata/with_third_party_requirements/bar.py similarity index 100% rename from gazelle/testdata/with_third_party_requirements/bar.py rename to gazelle/python/testdata/with_third_party_requirements/bar.py diff --git a/gazelle/testdata/with_third_party_requirements/foo.py b/gazelle/python/testdata/with_third_party_requirements/foo.py similarity index 100% rename from gazelle/testdata/with_third_party_requirements/foo.py rename to gazelle/python/testdata/with_third_party_requirements/foo.py diff --git a/gazelle/testdata/with_third_party_requirements/gazelle_python.yaml b/gazelle/python/testdata/with_third_party_requirements/gazelle_python.yaml similarity index 100% rename from gazelle/testdata/with_third_party_requirements/gazelle_python.yaml rename to gazelle/python/testdata/with_third_party_requirements/gazelle_python.yaml diff --git a/gazelle/testdata/with_third_party_requirements/test.yaml b/gazelle/python/testdata/with_third_party_requirements/test.yaml similarity index 100% rename from gazelle/testdata/with_third_party_requirements/test.yaml rename to gazelle/python/testdata/with_third_party_requirements/test.yaml diff --git a/gazelle/testdata/with_third_party_requirements_from_imports/BUILD.in b/gazelle/python/testdata/with_third_party_requirements_from_imports/BUILD.in similarity index 100% rename from gazelle/testdata/with_third_party_requirements_from_imports/BUILD.in rename to gazelle/python/testdata/with_third_party_requirements_from_imports/BUILD.in diff --git a/gazelle/testdata/with_third_party_requirements_from_imports/BUILD.out b/gazelle/python/testdata/with_third_party_requirements_from_imports/BUILD.out similarity index 100% rename from gazelle/testdata/with_third_party_requirements_from_imports/BUILD.out rename to gazelle/python/testdata/with_third_party_requirements_from_imports/BUILD.out diff --git a/gazelle/testdata/with_third_party_requirements_from_imports/README.md b/gazelle/python/testdata/with_third_party_requirements_from_imports/README.md similarity index 100% rename from gazelle/testdata/with_third_party_requirements_from_imports/README.md rename to gazelle/python/testdata/with_third_party_requirements_from_imports/README.md diff --git a/gazelle/testdata/with_third_party_requirements_from_imports/WORKSPACE b/gazelle/python/testdata/with_third_party_requirements_from_imports/WORKSPACE similarity index 100% rename from gazelle/testdata/with_third_party_requirements_from_imports/WORKSPACE rename to gazelle/python/testdata/with_third_party_requirements_from_imports/WORKSPACE diff --git a/gazelle/testdata/with_third_party_requirements_from_imports/__init__.py b/gazelle/python/testdata/with_third_party_requirements_from_imports/__init__.py similarity index 100% rename from gazelle/testdata/with_third_party_requirements_from_imports/__init__.py rename to gazelle/python/testdata/with_third_party_requirements_from_imports/__init__.py diff --git a/gazelle/testdata/with_third_party_requirements_from_imports/__main__.py b/gazelle/python/testdata/with_third_party_requirements_from_imports/__main__.py similarity index 100% rename from gazelle/testdata/with_third_party_requirements_from_imports/__main__.py rename to gazelle/python/testdata/with_third_party_requirements_from_imports/__main__.py diff --git a/gazelle/testdata/with_third_party_requirements_from_imports/bar.py b/gazelle/python/testdata/with_third_party_requirements_from_imports/bar.py similarity index 100% rename from gazelle/testdata/with_third_party_requirements_from_imports/bar.py rename to gazelle/python/testdata/with_third_party_requirements_from_imports/bar.py diff --git a/gazelle/testdata/with_third_party_requirements_from_imports/gazelle_python.yaml b/gazelle/python/testdata/with_third_party_requirements_from_imports/gazelle_python.yaml similarity index 100% rename from gazelle/testdata/with_third_party_requirements_from_imports/gazelle_python.yaml rename to gazelle/python/testdata/with_third_party_requirements_from_imports/gazelle_python.yaml diff --git a/gazelle/testdata/with_third_party_requirements_from_imports/test.yaml b/gazelle/python/testdata/with_third_party_requirements_from_imports/test.yaml similarity index 100% rename from gazelle/testdata/with_third_party_requirements_from_imports/test.yaml rename to gazelle/python/testdata/with_third_party_requirements_from_imports/test.yaml diff --git a/gazelle/testdata/subdir_sources/foo/has_build_bazel/BUILD.bazel.out b/gazelle/testdata/subdir_sources/foo/has_build_bazel/BUILD.bazel.out deleted file mode 100644 index 79bd70a258..0000000000 --- a/gazelle/testdata/subdir_sources/foo/has_build_bazel/BUILD.bazel.out +++ /dev/null @@ -1,8 +0,0 @@ -load("@rules_python//python:defs.bzl", "py_library") - -py_library( - name = "has_build_bazel", - srcs = ["python/my_module.py"], - imports = ["../.."], - visibility = ["//:__subpackages__"], -) From ba45af08a58701caeb81609c06bbed45fcbb7999 Mon Sep 17 00:00:00 2001 From: Lukas Date: Tue, 24 Jan 2023 17:52:01 +0100 Subject: [PATCH 126/234] fix: windows `*.lib` interface in `python_headers` (#976) fix: add the windows `*.lib` interface file to the `python_headers` library A user might use `python_headers` to build an extension module that does not itself pull in the python shared library. On Windows, this needs to expose the `*.lib` interface file to compile correctly. --- python/repositories.bzl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/python/repositories.bzl b/python/repositories.bzl index 011d4f9112..25e8f88547 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -246,6 +246,12 @@ filegroup( ), ) +cc_import( + name = "interface", + interface_library = "libs/python{python_version_nodot}.lib", + system_provided = True, +) + filegroup( name = "includes", srcs = glob(["include/**/*.h"]), @@ -253,6 +259,10 @@ filegroup( cc_library( name = "python_headers", + deps = select({{ + "@bazel_tools//src/conditions:windows": [":interface"], + "//conditions:default": None, + }}), hdrs = [":includes"], includes = [ "include", From f94c195922923f69d2f16e23a8181a96d7022c6c Mon Sep 17 00:00:00 2001 From: Daniel Wagner-Hall Date: Tue, 24 Jan 2023 16:52:45 +0000 Subject: [PATCH 127/234] python_repository: Exclude pycache files (#907) python_repository: Exclude pycache files when root Some of these are missing from the upstream python distributions, and when they are, if running as root, this causes the files to be generated the first time their associated .py file is evaluated, causing analysis and execution cache misses due to extra files matching the repository glob. --- python/repositories.bzl | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/python/repositories.bzl b/python/repositories.bzl index 25e8f88547..d1fba51f83 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -196,8 +196,20 @@ def _python_repository_impl(rctx): python_bin = "python.exe" if ("windows" in platform) else "bin/python3" + glob_include = [] + + if rctx.attr.ignore_root_user_error: + glob_include += [ + "# These pycache files are created on first use of the associated python files.", + "# Exclude them from the glob because otherwise between the first time and second time a python toolchain is used,", + "# the definition of this filegroup will change, and depending rules will get invalidated.", + "# See https://github.com/bazelbuild/rules_python/issues/1008 for unconditionally adding these to toolchains so we can stop ignoring them.", + "**/__pycache__/*.pyc", + "**/__pycache__/*.pyo", + ] + if "windows" in platform: - glob_include = [ + glob_include += [ "*.exe", "*.dll", "bin/**", @@ -210,7 +222,7 @@ def _python_repository_impl(rctx): "share/**", ] else: - glob_include = [ + glob_include += [ "bin/**", "extensions/**", "include/**", From 86b01a3a1b30b2244b86c80181f42492abaa09a1 Mon Sep 17 00:00:00 2001 From: Fabian Meumertzheim Date: Wed, 25 Jan 2023 17:19:50 +0100 Subject: [PATCH 128/234] runfiles: Remove dead code (#1011) Runfiles discovery relative to `argv[0]` isn't used as that logic lives in the launcher. --- python/runfiles/runfiles.py | 53 ------------- tests/runfiles/runfiles_test.py | 128 -------------------------------- 2 files changed, 181 deletions(-) diff --git a/python/runfiles/runfiles.py b/python/runfiles/runfiles.py index 01413fc529..9bdb61b56a 100644 --- a/python/runfiles/runfiles.py +++ b/python/runfiles/runfiles.py @@ -366,56 +366,3 @@ def EnvVars(self): # pick up RUNFILES_DIR. "JAVA_RUNFILES": self._runfiles_root, } - - -def _PathsFrom( - argv0, runfiles_mf, runfiles_dir, is_runfiles_manifest, is_runfiles_directory -): - # type: (str, str, str, Callable[[str], bool], Callable[[str], bool]) -> Tuple[str, str] - """Discover runfiles manifest and runfiles directory paths. - - Args: - argv0: string; the value of sys.argv[0] - runfiles_mf: string; the value of the RUNFILES_MANIFEST_FILE environment - variable - runfiles_dir: string; the value of the RUNFILES_DIR environment variable - is_runfiles_manifest: lambda(string):bool; returns true if the argument is - the path of a runfiles manifest file - is_runfiles_directory: lambda(string):bool; returns true if the argument is - the path of a runfiles directory - - Returns: - (string, string) pair, first element is the path to the runfiles manifest, - second element is the path to the runfiles directory. If the first element - is non-empty, then is_runfiles_manifest returns true for it. Same goes for - the second element and is_runfiles_directory respectively. If both elements - are empty, then this function could not find a manifest or directory for - which is_runfiles_manifest or is_runfiles_directory returns true. - """ - mf_alid = is_runfiles_manifest(runfiles_mf) - dir_valid = is_runfiles_directory(runfiles_dir) - - if not mf_alid and not dir_valid: - runfiles_mf = argv0 + ".runfiles/MANIFEST" - runfiles_dir = argv0 + ".runfiles" - mf_alid = is_runfiles_manifest(runfiles_mf) - dir_valid = is_runfiles_directory(runfiles_dir) - if not mf_alid: - runfiles_mf = argv0 + ".runfiles_manifest" - mf_alid = is_runfiles_manifest(runfiles_mf) - - if not mf_alid and not dir_valid: - return ("", "") - - if not mf_alid: - runfiles_mf = runfiles_dir + "/MANIFEST" - mf_alid = is_runfiles_manifest(runfiles_mf) - if not mf_alid: - runfiles_mf = runfiles_dir + "_manifest" - mf_alid = is_runfiles_manifest(runfiles_mf) - - if not dir_valid: - runfiles_dir = runfiles_mf[:-9] # "_manifest" or "/MANIFEST" - dir_valid = is_runfiles_directory(runfiles_dir) - - return (runfiles_mf if mf_alid else "", runfiles_dir if dir_valid else "") diff --git a/tests/runfiles/runfiles_test.py b/tests/runfiles/runfiles_test.py index 966d012c77..9fa2a18e6d 100644 --- a/tests/runfiles/runfiles_test.py +++ b/tests/runfiles/runfiles_test.py @@ -505,134 +505,6 @@ def testDirectoryBasedRlocationWithRepoMappingFromOtherRepo(self): r.Rlocation("config.json", "protobuf~3.19.2"), dir + "/config.json" ) - def testPathsFromEnvvars(self): - # Both envvars have a valid value. - mf, dr = runfiles._PathsFrom( - "argv0", - "mock1/MANIFEST", - "mock2", - lambda path: path == "mock1/MANIFEST", - lambda path: path == "mock2", - ) - self.assertEqual(mf, "mock1/MANIFEST") - self.assertEqual(dr, "mock2") - - # RUNFILES_MANIFEST_FILE is invalid but RUNFILES_DIR is good and there's a - # runfiles manifest in the runfiles directory. - mf, dr = runfiles._PathsFrom( - "argv0", - "mock1/MANIFEST", - "mock2", - lambda path: path == "mock2/MANIFEST", - lambda path: path == "mock2", - ) - self.assertEqual(mf, "mock2/MANIFEST") - self.assertEqual(dr, "mock2") - - # RUNFILES_MANIFEST_FILE is invalid but RUNFILES_DIR is good, but there's no - # runfiles manifest in the runfiles directory. - mf, dr = runfiles._PathsFrom( - "argv0", - "mock1/MANIFEST", - "mock2", - lambda path: False, - lambda path: path == "mock2", - ) - self.assertEqual(mf, "") - self.assertEqual(dr, "mock2") - - # RUNFILES_DIR is invalid but RUNFILES_MANIFEST_FILE is good, and it is in - # a valid-looking runfiles directory. - mf, dr = runfiles._PathsFrom( - "argv0", - "mock1/MANIFEST", - "mock2", - lambda path: path == "mock1/MANIFEST", - lambda path: path == "mock1", - ) - self.assertEqual(mf, "mock1/MANIFEST") - self.assertEqual(dr, "mock1") - - # RUNFILES_DIR is invalid but RUNFILES_MANIFEST_FILE is good, but it is not - # in any valid-looking runfiles directory. - mf, dr = runfiles._PathsFrom( - "argv0", - "mock1/MANIFEST", - "mock2", - lambda path: path == "mock1/MANIFEST", - lambda path: False, - ) - self.assertEqual(mf, "mock1/MANIFEST") - self.assertEqual(dr, "") - - # Both envvars are invalid, but there's a manifest in a runfiles directory - # next to argv0, however there's no other content in the runfiles directory. - mf, dr = runfiles._PathsFrom( - "argv0", - "mock1/MANIFEST", - "mock2", - lambda path: path == "argv0.runfiles/MANIFEST", - lambda path: False, - ) - self.assertEqual(mf, "argv0.runfiles/MANIFEST") - self.assertEqual(dr, "") - - # Both envvars are invalid, but there's a manifest next to argv0. There's - # no runfiles tree anywhere. - mf, dr = runfiles._PathsFrom( - "argv0", - "mock1/MANIFEST", - "mock2", - lambda path: path == "argv0.runfiles_manifest", - lambda path: False, - ) - self.assertEqual(mf, "argv0.runfiles_manifest") - self.assertEqual(dr, "") - - # Both envvars are invalid, but there's a valid manifest next to argv0, and - # a valid runfiles directory (without a manifest in it). - mf, dr = runfiles._PathsFrom( - "argv0", - "mock1/MANIFEST", - "mock2", - lambda path: path == "argv0.runfiles_manifest", - lambda path: path == "argv0.runfiles", - ) - self.assertEqual(mf, "argv0.runfiles_manifest") - self.assertEqual(dr, "argv0.runfiles") - - # Both envvars are invalid, but there's a valid runfiles directory next to - # argv0, though no manifest in it. - mf, dr = runfiles._PathsFrom( - "argv0", - "mock1/MANIFEST", - "mock2", - lambda path: False, - lambda path: path == "argv0.runfiles", - ) - self.assertEqual(mf, "") - self.assertEqual(dr, "argv0.runfiles") - - # Both envvars are invalid, but there's a valid runfiles directory next to - # argv0 with a valid manifest in it. - mf, dr = runfiles._PathsFrom( - "argv0", - "mock1/MANIFEST", - "mock2", - lambda path: path == "argv0.runfiles/MANIFEST", - lambda path: path == "argv0.runfiles", - ) - self.assertEqual(mf, "argv0.runfiles/MANIFEST") - self.assertEqual(dr, "argv0.runfiles") - - # Both envvars are invalid and there's no runfiles directory or manifest - # next to the argv0. - mf, dr = runfiles._PathsFrom( - "argv0", "mock1/MANIFEST", "mock2", lambda path: False, lambda path: False - ) - self.assertEqual(mf, "") - self.assertEqual(dr, "") - def testCurrentRepository(self): # This test assumes that it is running without --enable_bzlmod as the # correct result with Bzlmod would be the empty string - the canonical From da106c59d08d74759bbdbacee91fb68f4d45f4ef Mon Sep 17 00:00:00 2001 From: Fabian Meumertzheim Date: Wed, 25 Jan 2023 17:20:29 +0100 Subject: [PATCH 129/234] runfiles: Add proper test coverage for an edge case (#1012) The repo mapping wasn't set up correctly to actually test that root symlinks aren't subject to repo mapping. --- tests/runfiles/runfiles_test.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/runfiles/runfiles_test.py b/tests/runfiles/runfiles_test.py index 9fa2a18e6d..3a1f49201b 100644 --- a/tests/runfiles/runfiles_test.py +++ b/tests/runfiles/runfiles_test.py @@ -208,9 +208,11 @@ def testManifestBasedRlocation(self): def testManifestBasedRlocationWithRepoMappingFromMain(self): with _MockFile( contents=[ + ",config.json,config.json~1.2.3", ",my_module,_main", ",my_protobuf,protobuf~3.19.2", ",my_workspace,_main", + "protobuf~3.19.2,config.json,config.json~1.2.3", "protobuf~3.19.2,protobuf,protobuf~3.19.2", ] ) as rm, _MockFile( @@ -281,9 +283,11 @@ def testManifestBasedRlocationWithRepoMappingFromMain(self): def testManifestBasedRlocationWithRepoMappingFromOtherRepo(self): with _MockFile( contents=[ + ",config.json,config.json~1.2.3", ",my_module,_main", ",my_protobuf,protobuf~3.19.2", ",my_workspace,_main", + "protobuf~3.19.2,config.json,config.json~1.2.3", "protobuf~3.19.2,protobuf,protobuf~3.19.2", ] ) as rm, _MockFile( @@ -374,9 +378,11 @@ def testDirectoryBasedRlocationWithRepoMappingFromMain(self): with _MockFile( name="_repo_mapping", contents=[ + "_,config.json,config.json~1.2.3", ",my_module,_main", ",my_protobuf,protobuf~3.19.2", ",my_workspace,_main", + "protobuf~3.19.2,config.json,config.json~1.2.3", "protobuf~3.19.2,protobuf,protobuf~3.19.2", ], ) as rm: @@ -439,9 +445,11 @@ def testDirectoryBasedRlocationWithRepoMappingFromOtherRepo(self): with _MockFile( name="_repo_mapping", contents=[ + "_,config.json,config.json~1.2.3", ",my_module,_main", ",my_protobuf,protobuf~3.19.2", ",my_workspace,_main", + "protobuf~3.19.2,config.json,config.json~1.2.3", "protobuf~3.19.2,protobuf,protobuf~3.19.2", ], ) as rm: From 6c6c70bca0bd82ec0fe22e7c0e26c264971d0994 Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Wed, 25 Jan 2023 10:23:17 -0800 Subject: [PATCH 130/234] refactor: pull implementations out of packaging.bzl (#1013) This is a pre-factoring to allow py_wheel to become a macro which produces a py_wheel rule, in addition to a publishing target. Part of #99 --- docs/BUILD.bazel | 2 + docs/packaging.md | 5 +- python/packaging.bzl | 422 +--------------------------------- python/private/BUILD.bazel | 2 + python/private/py_package.bzl | 61 +++++ python/private/py_wheel.bzl | 359 +++++++++++++++++++++++++++++ 6 files changed, 437 insertions(+), 414 deletions(-) create mode 100644 python/private/py_package.bzl create mode 100644 python/private/py_wheel.bzl diff --git a/docs/BUILD.bazel b/docs/BUILD.bazel index 105a68e3be..3abff033ae 100644 --- a/docs/BUILD.bazel +++ b/docs/BUILD.bazel @@ -81,6 +81,8 @@ bzl_library( name = "packaging_bzl", srcs = [ "//python:packaging.bzl", + "//python/private:py_package.bzl", + "//python/private:py_wheel.bzl", "//python/private:stamp.bzl", ], ) diff --git a/docs/packaging.md b/docs/packaging.md index 22e6419d1d..86ba81e477 100755 --- a/docs/packaging.md +++ b/docs/packaging.md @@ -1,6 +1,6 @@ -Rules for building wheels. +Public API for for building wheels. @@ -13,7 +13,7 @@ py_package(name, deps< A rule to select all files in transitive dependencies of deps which belong to given set of Python packages. -This rule is intended to be used as data dependency to py_wheel rule +This rule is intended to be used as data dependency to py_wheel rule. **ATTRIBUTES** @@ -36,7 +36,6 @@ py_wheel(name, abi, platform, python_requires, python_tag, requires, stamp, strip_path_prefixes, version) - A rule for building Python Wheels. Wheels are Python distribution format defined in https://www.python.org/dev/peps/pep-0427/. diff --git a/python/packaging.bzl b/python/packaging.bzl index 5bb50173cf..763d7c5486 100644 --- a/python/packaging.bzl +++ b/python/packaging.bzl @@ -12,404 +12,28 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Rules for building wheels.""" +"""Public API for for building wheels.""" -load("//python/private:stamp.bzl", "is_stamping_enabled") +load("//python/private:py_package.bzl", "py_package_lib") +load("//python/private:py_wheel.bzl", "py_wheel_lib", _PyWheelInfo = "PyWheelInfo") -PyWheelInfo = provider( - doc = "Information about a wheel produced by `py_wheel`", - fields = { - "name_file": ( - "File: A file containing the canonical name of the wheel (after " + - "stamping, if enabled)." - ), - "wheel": "File: The wheel file itself.", - }, -) - -def _path_inside_wheel(input_file): - # input_file.short_path is sometimes relative ("../${repository_root}/foobar") - # which is not a valid path within a zip file. Fix that. - short_path = input_file.short_path - if short_path.startswith("..") and len(short_path) >= 3: - # Path separator. '/' on linux. - separator = short_path[2] - - # Consume '../' part. - short_path = short_path[3:] - - # Find position of next '/' and consume everything up to that character. - pos = short_path.find(separator) - short_path = short_path[pos + 1:] - return short_path - -def _input_file_to_arg(input_file): - """Converts a File object to string for --input_file argument to wheelmaker""" - return "%s;%s" % (_path_inside_wheel(input_file), input_file.path) - -def _py_package_impl(ctx): - inputs = depset( - transitive = [dep[DefaultInfo].data_runfiles.files for dep in ctx.attr.deps] + - [dep[DefaultInfo].default_runfiles.files for dep in ctx.attr.deps], - ) - - # TODO: '/' is wrong on windows, but the path separator is not available in starlark. - # Fix this once ctx.configuration has directory separator information. - packages = [p.replace(".", "/") for p in ctx.attr.packages] - if not packages: - filtered_inputs = inputs - else: - filtered_files = [] - - # TODO: flattening depset to list gives poor performance, - for input_file in inputs.to_list(): - wheel_path = _path_inside_wheel(input_file) - for package in packages: - if wheel_path.startswith(package): - filtered_files.append(input_file) - filtered_inputs = depset(direct = filtered_files) - - return [DefaultInfo( - files = filtered_inputs, - )] +# Re-export as public API +PyWheelInfo = _PyWheelInfo py_package = rule( - implementation = _py_package_impl, + implementation = py_package_lib.implementation, doc = """\ A rule to select all files in transitive dependencies of deps which belong to given set of Python packages. -This rule is intended to be used as data dependency to py_wheel rule +This rule is intended to be used as data dependency to py_wheel rule. """, - attrs = { - "deps": attr.label_list( - doc = "", - ), - "packages": attr.string_list( - mandatory = False, - allow_empty = True, - doc = """\ -List of Python packages to include in the distribution. -Sub-packages are automatically included. -""", - ), - }, + attrs = py_package_lib.attrs, ) -def _escape_filename_segment(segment): - """Escape a segment of the wheel filename. - - See https://www.python.org/dev/peps/pep-0427/#escaping-and-unicode - """ - - # TODO: this is wrong, isalnum replaces non-ascii letters, while we should - # not replace them. - # TODO: replace this with a regexp once starlark supports them. - escaped = "" - for character in segment.elems(): - # isalnum doesn't handle unicode characters properly. - if character.isalnum() or character == ".": - escaped += character - elif not escaped.endswith("_"): - escaped += "_" - return escaped - -def _replace_make_variables(flag, ctx): - """Replace $(VERSION) etc make variables in flag""" - if "$" in flag: - for varname, varsub in ctx.var.items(): - flag = flag.replace("$(%s)" % varname, varsub) - return flag - -def _py_wheel_impl(ctx): - version = _replace_make_variables(ctx.attr.version, ctx) - outfile = ctx.actions.declare_file("-".join([ - _escape_filename_segment(ctx.attr.distribution), - _escape_filename_segment(version), - _escape_filename_segment(ctx.attr.python_tag), - _escape_filename_segment(ctx.attr.abi), - _escape_filename_segment(ctx.attr.platform), - ]) + ".whl") - - name_file = ctx.actions.declare_file(ctx.label.name + ".name") - - inputs_to_package = depset( - direct = ctx.files.deps, - ) - - # Inputs to this rule which are not to be packaged. - # Currently this is only the description file (if used). - other_inputs = [] - - # Wrap the inputs into a file to reduce command line length. - packageinputfile = ctx.actions.declare_file(ctx.attr.name + "_target_wrapped_inputs.txt") - content = "" - for input_file in inputs_to_package.to_list(): - content += _input_file_to_arg(input_file) + "\n" - ctx.actions.write(output = packageinputfile, content = content) - other_inputs.append(packageinputfile) - - args = ctx.actions.args() - args.add("--name", ctx.attr.distribution) - args.add("--version", version) - args.add("--python_tag", ctx.attr.python_tag) - args.add("--abi", ctx.attr.abi) - args.add("--platform", ctx.attr.platform) - args.add("--out", outfile) - args.add("--name_file", name_file) - args.add_all(ctx.attr.strip_path_prefixes, format_each = "--strip_path_prefix=%s") - - # Pass workspace status files if stamping is enabled - if is_stamping_enabled(ctx.attr): - args.add("--volatile_status_file", ctx.version_file) - args.add("--stable_status_file", ctx.info_file) - other_inputs.extend([ctx.version_file, ctx.info_file]) - - args.add("--input_file_list", packageinputfile) - - # Note: Description file and version are not embedded into metadata.txt yet, - # it will be done later by wheelmaker script. - metadata_file = ctx.actions.declare_file(ctx.attr.name + ".metadata.txt") - metadata_contents = ["Metadata-Version: 2.1"] - metadata_contents.append("Name: %s" % ctx.attr.distribution) - - if ctx.attr.author: - metadata_contents.append("Author: %s" % ctx.attr.author) - if ctx.attr.author_email: - metadata_contents.append("Author-email: %s" % ctx.attr.author_email) - if ctx.attr.homepage: - metadata_contents.append("Home-page: %s" % ctx.attr.homepage) - if ctx.attr.license: - metadata_contents.append("License: %s" % ctx.attr.license) - - for c in ctx.attr.classifiers: - metadata_contents.append("Classifier: %s" % c) - - if ctx.attr.python_requires: - metadata_contents.append("Requires-Python: %s" % ctx.attr.python_requires) - for requirement in ctx.attr.requires: - metadata_contents.append("Requires-Dist: %s" % requirement) - - for option, option_requirements in sorted(ctx.attr.extra_requires.items()): - metadata_contents.append("Provides-Extra: %s" % option) - for requirement in option_requirements: - metadata_contents.append( - "Requires-Dist: %s; extra == '%s'" % (requirement, option), - ) - ctx.actions.write( - output = metadata_file, - content = "\n".join(metadata_contents) + "\n", - ) - other_inputs.append(metadata_file) - args.add("--metadata_file", metadata_file) - - # Merge console_scripts into entry_points. - entrypoints = dict(ctx.attr.entry_points) # Copy so we can mutate it - if ctx.attr.console_scripts: - # Copy a console_scripts group that may already exist, so we can mutate it. - console_scripts = list(entrypoints.get("console_scripts", [])) - entrypoints["console_scripts"] = console_scripts - for name, ref in ctx.attr.console_scripts.items(): - console_scripts.append("{name} = {ref}".format(name = name, ref = ref)) - - # If any entry_points are provided, construct the file here and add it to the files to be packaged. - # see: https://packaging.python.org/specifications/entry-points/ - if entrypoints: - lines = [] - for group, entries in sorted(entrypoints.items()): - if lines: - # Blank line between groups - lines.append("") - lines.append("[{group}]".format(group = group)) - lines += sorted(entries) - entry_points_file = ctx.actions.declare_file(ctx.attr.name + "_entry_points.txt") - content = "\n".join(lines) - ctx.actions.write(output = entry_points_file, content = content) - other_inputs.append(entry_points_file) - args.add("--entry_points_file", entry_points_file) - - if ctx.attr.description_file: - description_file = ctx.file.description_file - args.add("--description_file", description_file) - other_inputs.append(description_file) - - for target, filename in ctx.attr.extra_distinfo_files.items(): - target_files = target.files.to_list() - if len(target_files) != 1: - fail( - "Multi-file target listed in extra_distinfo_files %s", - filename, - ) - other_inputs.extend(target_files) - args.add( - "--extra_distinfo_file", - filename + ";" + target_files[0].path, - ) - - ctx.actions.run( - inputs = depset(direct = other_inputs, transitive = [inputs_to_package]), - outputs = [outfile, name_file], - arguments = [args], - executable = ctx.executable._wheelmaker, - progress_message = "Building wheel {}".format(ctx.label), - ) - return [ - DefaultInfo( - files = depset([outfile]), - runfiles = ctx.runfiles(files = [outfile]), - ), - PyWheelInfo( - wheel = outfile, - name_file = name_file, - ), - ] - -def _concat_dicts(*dicts): - result = {} - for d in dicts: - result.update(d) - return result - -_distribution_attrs = { - "abi": attr.string( - default = "none", - doc = "Python ABI tag. 'none' for pure-Python wheels.", - ), - "distribution": attr.string( - mandatory = True, - doc = """\ -Name of the distribution. - -This should match the project name onm PyPI. It's also the name that is used to -refer to the package in other packages' dependencies. -""", - ), - "platform": attr.string( - default = "any", - doc = """\ -Supported platform. Use 'any' for pure-Python wheel. - -If you have included platform-specific data, such as a .pyd or .so -extension module, you will need to specify the platform in standard -pip format. If you support multiple platforms, you can define -platform constraints, then use a select() to specify the appropriate -specifier, eg: - -` -platform = select({ - "//platforms:windows_x86_64": "win_amd64", - "//platforms:macos_x86_64": "macosx_10_7_x86_64", - "//platforms:linux_x86_64": "manylinux2014_x86_64", -}) -` -""", - ), - "python_tag": attr.string( - default = "py3", - doc = "Supported Python version(s), eg `py3`, `cp35.cp36`, etc", - ), - "stamp": attr.int( - doc = """\ -Whether to encode build information into the wheel. Possible values: - -- `stamp = 1`: Always stamp the build information into the wheel, even in \ -[--nostamp](https://docs.bazel.build/versions/main/user-manual.html#flag--stamp) builds. \ -This setting should be avoided, since it potentially kills remote caching for the target and \ -any downstream actions that depend on it. - -- `stamp = 0`: Always replace build information by constant values. This gives good build result caching. - -- `stamp = -1`: Embedding of build information is controlled by the \ -[--[no]stamp](https://docs.bazel.build/versions/main/user-manual.html#flag--stamp) flag. - -Stamped targets are not rebuilt unless their dependencies change. - """, - default = -1, - values = [1, 0, -1], - ), - "version": attr.string( - mandatory = True, - doc = ( - "Version number of the package. Note that this attribute " + - "supports stamp format strings (eg. `1.2.3-{BUILD_TIMESTAMP}`) " + - "as well as 'make variables' (e.g. `1.2.3-$(VERSION)`)." - ), - ), - "_stamp_flag": attr.label( - doc = "A setting used to determine whether or not the `--stamp` flag is enabled", - default = Label("//python/private:stamp"), - ), -} - -_requirement_attrs = { - "extra_requires": attr.string_list_dict( - doc = "List of optional requirements for this package", - ), - "requires": attr.string_list( - doc = ("List of requirements for this package. See the section on " + - "[Declaring required dependency](https://setuptools.readthedocs.io/en/latest/userguide/dependency_management.html#declaring-dependencies) " + - "for details and examples of the format of this argument."), - ), -} - -_entrypoint_attrs = { - "console_scripts": attr.string_dict( - doc = """\ -Deprecated console_script entry points, e.g. `{'main': 'examples.wheel.main:main'}`. - -Deprecated: prefer the `entry_points` attribute, which supports `console_scripts` as well as other entry points. -""", - ), - "entry_points": attr.string_list_dict( - doc = """\ -entry_points, e.g. `{'console_scripts': ['main = examples.wheel.main:main']}`. -""", - ), -} - -_other_attrs = { - "author": attr.string( - doc = "A string specifying the author of the package.", - default = "", - ), - "author_email": attr.string( - doc = "A string specifying the email address of the package author.", - default = "", - ), - "classifiers": attr.string_list( - doc = "A list of strings describing the categories for the package. For valid classifiers see https://pypi.org/classifiers", - ), - "description_file": attr.label( - doc = "A file containing text describing the package.", - allow_single_file = True, - ), - "extra_distinfo_files": attr.label_keyed_string_dict( - doc = "Extra files to add to distinfo directory in the archive.", - allow_files = True, - ), - "homepage": attr.string( - doc = "A string specifying the URL for the package homepage.", - default = "", - ), - "license": attr.string( - doc = "A string specifying the license of the package.", - default = "", - ), - "python_requires": attr.string( - doc = ( - "Python versions required by this distribution, e.g. '>=3.5,<3.7'" - ), - default = "", - ), - "strip_path_prefixes": attr.string_list( - default = [], - doc = "path prefixes to strip from files added to the generated package", - ), -} - py_wheel = rule( - implementation = _py_wheel_impl, - doc = """ + implementation = py_wheel_lib.implementation, + doc = """\ A rule for building Python Wheels. Wheels are Python distribution format defined in https://www.python.org/dev/peps/pep-0427/. @@ -453,29 +77,5 @@ py_wheel( ) ``` """, - attrs = _concat_dicts( - { - "deps": attr.label_list( - doc = """\ -Targets to be included in the distribution. - -The targets to package are usually `py_library` rules or filesets (for packaging data files). - -Note it's usually better to package `py_library` targets and use -`entry_points` attribute to specify `console_scripts` than to package -`py_binary` rules. `py_binary` targets would wrap a executable script that -tries to locate `.runfiles` directory which is not packaged in the wheel. -""", - ), - "_wheelmaker": attr.label( - executable = True, - cfg = "exec", - default = "//tools:wheelmaker", - ), - }, - _distribution_attrs, - _requirement_attrs, - _entrypoint_attrs, - _other_attrs, - ), + attrs = py_wheel_lib.attrs, ) diff --git a/python/private/BUILD.bazel b/python/private/BUILD.bazel index 75e48bc70a..811f28599f 100644 --- a/python/private/BUILD.bazel +++ b/python/private/BUILD.bazel @@ -36,6 +36,8 @@ filegroup( # on Skylib.) exports_files( [ + "py_package.bzl", + "py_wheel.bzl", "reexports.bzl", "stamp.bzl", ], diff --git a/python/private/py_package.bzl b/python/private/py_package.bzl new file mode 100644 index 0000000000..25e5bb6389 --- /dev/null +++ b/python/private/py_package.bzl @@ -0,0 +1,61 @@ +"Implementation of py_package rule" + +def _path_inside_wheel(input_file): + # input_file.short_path is sometimes relative ("../${repository_root}/foobar") + # which is not a valid path within a zip file. Fix that. + short_path = input_file.short_path + if short_path.startswith("..") and len(short_path) >= 3: + # Path separator. '/' on linux. + separator = short_path[2] + + # Consume '../' part. + short_path = short_path[3:] + + # Find position of next '/' and consume everything up to that character. + pos = short_path.find(separator) + short_path = short_path[pos + 1:] + return short_path + +def _py_package_impl(ctx): + inputs = depset( + transitive = [dep[DefaultInfo].data_runfiles.files for dep in ctx.attr.deps] + + [dep[DefaultInfo].default_runfiles.files for dep in ctx.attr.deps], + ) + + # TODO: '/' is wrong on windows, but the path separator is not available in starlark. + # Fix this once ctx.configuration has directory separator information. + packages = [p.replace(".", "/") for p in ctx.attr.packages] + if not packages: + filtered_inputs = inputs + else: + filtered_files = [] + + # TODO: flattening depset to list gives poor performance, + for input_file in inputs.to_list(): + wheel_path = _path_inside_wheel(input_file) + for package in packages: + if wheel_path.startswith(package): + filtered_files.append(input_file) + filtered_inputs = depset(direct = filtered_files) + + return [DefaultInfo( + files = filtered_inputs, + )] + +py_package_lib = struct( + implementation = _py_package_impl, + attrs = { + "deps": attr.label_list( + doc = "", + ), + "packages": attr.string_list( + mandatory = False, + allow_empty = True, + doc = """\ +List of Python packages to include in the distribution. +Sub-packages are automatically included. +""", + ), + }, + path_inside_wheel = _path_inside_wheel, +) diff --git a/python/private/py_wheel.bzl b/python/private/py_wheel.bzl new file mode 100644 index 0000000000..6d2c9b36bb --- /dev/null +++ b/python/private/py_wheel.bzl @@ -0,0 +1,359 @@ +"Implementation of py_wheel rule" + +load("//python/private:stamp.bzl", "is_stamping_enabled") +load(":py_package.bzl", "py_package_lib") + +PyWheelInfo = provider( + doc = "Information about a wheel produced by `py_wheel`", + fields = { + "name_file": ( + "File: A file containing the canonical name of the wheel (after " + + "stamping, if enabled)." + ), + "wheel": "File: The wheel file itself.", + }, +) + +_distribution_attrs = { + "abi": attr.string( + default = "none", + doc = "Python ABI tag. 'none' for pure-Python wheels.", + ), + "distribution": attr.string( + mandatory = True, + doc = """\ +Name of the distribution. + +This should match the project name onm PyPI. It's also the name that is used to +refer to the package in other packages' dependencies. +""", + ), + "platform": attr.string( + default = "any", + doc = """\ +Supported platform. Use 'any' for pure-Python wheel. + +If you have included platform-specific data, such as a .pyd or .so +extension module, you will need to specify the platform in standard +pip format. If you support multiple platforms, you can define +platform constraints, then use a select() to specify the appropriate +specifier, eg: + +` +platform = select({ + "//platforms:windows_x86_64": "win_amd64", + "//platforms:macos_x86_64": "macosx_10_7_x86_64", + "//platforms:linux_x86_64": "manylinux2014_x86_64", +}) +` +""", + ), + "python_tag": attr.string( + default = "py3", + doc = "Supported Python version(s), eg `py3`, `cp35.cp36`, etc", + ), + "stamp": attr.int( + doc = """\ +Whether to encode build information into the wheel. Possible values: + +- `stamp = 1`: Always stamp the build information into the wheel, even in \ +[--nostamp](https://docs.bazel.build/versions/main/user-manual.html#flag--stamp) builds. \ +This setting should be avoided, since it potentially kills remote caching for the target and \ +any downstream actions that depend on it. + +- `stamp = 0`: Always replace build information by constant values. This gives good build result caching. + +- `stamp = -1`: Embedding of build information is controlled by the \ +[--[no]stamp](https://docs.bazel.build/versions/main/user-manual.html#flag--stamp) flag. + +Stamped targets are not rebuilt unless their dependencies change. + """, + default = -1, + values = [1, 0, -1], + ), + "version": attr.string( + mandatory = True, + doc = ( + "Version number of the package. Note that this attribute " + + "supports stamp format strings (eg. `1.2.3-{BUILD_TIMESTAMP}`) " + + "as well as 'make variables' (e.g. `1.2.3-$(VERSION)`)." + ), + ), + "_stamp_flag": attr.label( + doc = "A setting used to determine whether or not the `--stamp` flag is enabled", + default = Label("//python/private:stamp"), + ), +} + +_requirement_attrs = { + "extra_requires": attr.string_list_dict( + doc = "List of optional requirements for this package", + ), + "requires": attr.string_list( + doc = ("List of requirements for this package. See the section on " + + "[Declaring required dependency](https://setuptools.readthedocs.io/en/latest/userguide/dependency_management.html#declaring-dependencies) " + + "for details and examples of the format of this argument."), + ), +} + +_entrypoint_attrs = { + "console_scripts": attr.string_dict( + doc = """\ +Deprecated console_script entry points, e.g. `{'main': 'examples.wheel.main:main'}`. + +Deprecated: prefer the `entry_points` attribute, which supports `console_scripts` as well as other entry points. +""", + ), + "entry_points": attr.string_list_dict( + doc = """\ +entry_points, e.g. `{'console_scripts': ['main = examples.wheel.main:main']}`. +""", + ), +} + +_other_attrs = { + "author": attr.string( + doc = "A string specifying the author of the package.", + default = "", + ), + "author_email": attr.string( + doc = "A string specifying the email address of the package author.", + default = "", + ), + "classifiers": attr.string_list( + doc = "A list of strings describing the categories for the package. For valid classifiers see https://pypi.org/classifiers", + ), + "description_file": attr.label( + doc = "A file containing text describing the package.", + allow_single_file = True, + ), + "extra_distinfo_files": attr.label_keyed_string_dict( + doc = "Extra files to add to distinfo directory in the archive.", + allow_files = True, + ), + "homepage": attr.string( + doc = "A string specifying the URL for the package homepage.", + default = "", + ), + "license": attr.string( + doc = "A string specifying the license of the package.", + default = "", + ), + "python_requires": attr.string( + doc = ( + "Python versions required by this distribution, e.g. '>=3.5,<3.7'" + ), + default = "", + ), + "strip_path_prefixes": attr.string_list( + default = [], + doc = "path prefixes to strip from files added to the generated package", + ), +} + +def _escape_filename_segment(segment): + """Escape a segment of the wheel filename. + + See https://www.python.org/dev/peps/pep-0427/#escaping-and-unicode + """ + + # TODO: this is wrong, isalnum replaces non-ascii letters, while we should + # not replace them. + # TODO: replace this with a regexp once starlark supports them. + escaped = "" + for character in segment.elems(): + # isalnum doesn't handle unicode characters properly. + if character.isalnum() or character == ".": + escaped += character + elif not escaped.endswith("_"): + escaped += "_" + return escaped + +def _replace_make_variables(flag, ctx): + """Replace $(VERSION) etc make variables in flag""" + if "$" in flag: + for varname, varsub in ctx.var.items(): + flag = flag.replace("$(%s)" % varname, varsub) + return flag + +def _input_file_to_arg(input_file): + """Converts a File object to string for --input_file argument to wheelmaker""" + return "%s;%s" % (py_package_lib.path_inside_wheel(input_file), input_file.path) + +def _py_wheel_impl(ctx): + version = _replace_make_variables(ctx.attr.version, ctx) + outfile = ctx.actions.declare_file("-".join([ + _escape_filename_segment(ctx.attr.distribution), + _escape_filename_segment(version), + _escape_filename_segment(ctx.attr.python_tag), + _escape_filename_segment(ctx.attr.abi), + _escape_filename_segment(ctx.attr.platform), + ]) + ".whl") + + name_file = ctx.actions.declare_file(ctx.label.name + ".name") + + inputs_to_package = depset( + direct = ctx.files.deps, + ) + + # Inputs to this rule which are not to be packaged. + # Currently this is only the description file (if used). + other_inputs = [] + + # Wrap the inputs into a file to reduce command line length. + packageinputfile = ctx.actions.declare_file(ctx.attr.name + "_target_wrapped_inputs.txt") + content = "" + for input_file in inputs_to_package.to_list(): + content += _input_file_to_arg(input_file) + "\n" + ctx.actions.write(output = packageinputfile, content = content) + other_inputs.append(packageinputfile) + + args = ctx.actions.args() + args.add("--name", ctx.attr.distribution) + args.add("--version", version) + args.add("--python_tag", ctx.attr.python_tag) + args.add("--abi", ctx.attr.abi) + args.add("--platform", ctx.attr.platform) + args.add("--out", outfile) + args.add("--name_file", name_file) + args.add_all(ctx.attr.strip_path_prefixes, format_each = "--strip_path_prefix=%s") + + # Pass workspace status files if stamping is enabled + if is_stamping_enabled(ctx.attr): + args.add("--volatile_status_file", ctx.version_file) + args.add("--stable_status_file", ctx.info_file) + other_inputs.extend([ctx.version_file, ctx.info_file]) + + args.add("--input_file_list", packageinputfile) + + # Note: Description file and version are not embedded into metadata.txt yet, + # it will be done later by wheelmaker script. + metadata_file = ctx.actions.declare_file(ctx.attr.name + ".metadata.txt") + metadata_contents = ["Metadata-Version: 2.1"] + metadata_contents.append("Name: %s" % ctx.attr.distribution) + + if ctx.attr.author: + metadata_contents.append("Author: %s" % ctx.attr.author) + if ctx.attr.author_email: + metadata_contents.append("Author-email: %s" % ctx.attr.author_email) + if ctx.attr.homepage: + metadata_contents.append("Home-page: %s" % ctx.attr.homepage) + if ctx.attr.license: + metadata_contents.append("License: %s" % ctx.attr.license) + + for c in ctx.attr.classifiers: + metadata_contents.append("Classifier: %s" % c) + + if ctx.attr.python_requires: + metadata_contents.append("Requires-Python: %s" % ctx.attr.python_requires) + for requirement in ctx.attr.requires: + metadata_contents.append("Requires-Dist: %s" % requirement) + + for option, option_requirements in sorted(ctx.attr.extra_requires.items()): + metadata_contents.append("Provides-Extra: %s" % option) + for requirement in option_requirements: + metadata_contents.append( + "Requires-Dist: %s; extra == '%s'" % (requirement, option), + ) + ctx.actions.write( + output = metadata_file, + content = "\n".join(metadata_contents) + "\n", + ) + other_inputs.append(metadata_file) + args.add("--metadata_file", metadata_file) + + # Merge console_scripts into entry_points. + entrypoints = dict(ctx.attr.entry_points) # Copy so we can mutate it + if ctx.attr.console_scripts: + # Copy a console_scripts group that may already exist, so we can mutate it. + console_scripts = list(entrypoints.get("console_scripts", [])) + entrypoints["console_scripts"] = console_scripts + for name, ref in ctx.attr.console_scripts.items(): + console_scripts.append("{name} = {ref}".format(name = name, ref = ref)) + + # If any entry_points are provided, construct the file here and add it to the files to be packaged. + # see: https://packaging.python.org/specifications/entry-points/ + if entrypoints: + lines = [] + for group, entries in sorted(entrypoints.items()): + if lines: + # Blank line between groups + lines.append("") + lines.append("[{group}]".format(group = group)) + lines += sorted(entries) + entry_points_file = ctx.actions.declare_file(ctx.attr.name + "_entry_points.txt") + content = "\n".join(lines) + ctx.actions.write(output = entry_points_file, content = content) + other_inputs.append(entry_points_file) + args.add("--entry_points_file", entry_points_file) + + if ctx.attr.description_file: + description_file = ctx.file.description_file + args.add("--description_file", description_file) + other_inputs.append(description_file) + + for target, filename in ctx.attr.extra_distinfo_files.items(): + target_files = target.files.to_list() + if len(target_files) != 1: + fail( + "Multi-file target listed in extra_distinfo_files %s", + filename, + ) + other_inputs.extend(target_files) + args.add( + "--extra_distinfo_file", + filename + ";" + target_files[0].path, + ) + + ctx.actions.run( + inputs = depset(direct = other_inputs, transitive = [inputs_to_package]), + outputs = [outfile, name_file], + arguments = [args], + executable = ctx.executable._wheelmaker, + progress_message = "Building wheel {}".format(ctx.label), + ) + return [ + DefaultInfo( + files = depset([outfile]), + runfiles = ctx.runfiles(files = [outfile]), + ), + PyWheelInfo( + wheel = outfile, + name_file = name_file, + ), + ] + +def _concat_dicts(*dicts): + result = {} + for d in dicts: + result.update(d) + return result + +py_wheel_lib = struct( + implementation = _py_wheel_impl, + attrs = _concat_dicts( + { + "deps": attr.label_list( + doc = """\ +Targets to be included in the distribution. + +The targets to package are usually `py_library` rules or filesets (for packaging data files). + +Note it's usually better to package `py_library` targets and use +`entry_points` attribute to specify `console_scripts` than to package +`py_binary` rules. `py_binary` targets would wrap a executable script that +tries to locate `.runfiles` directory which is not packaged in the wheel. +""", + ), + "_wheelmaker": attr.label( + executable = True, + cfg = "exec", + default = "//tools:wheelmaker", + ), + }, + _distribution_attrs, + _requirement_attrs, + _entrypoint_attrs, + _other_attrs, + ), +) From 43e18f000e322214e77c1d0d49e42007b4f1f9c3 Mon Sep 17 00:00:00 2001 From: Tianyu Geng Date: Wed, 25 Jan 2023 10:31:12 -0800 Subject: [PATCH 131/234] Fix requirement parser (#1009) Fix requirements_parser.bzl Space in requirement.txt should delimit options into distinct arguments. Otherwise, `pip` would be invoked with incorrect argument containing space. --- .../private/test/requirements_parser_tests.bzl | 8 ++++---- python/pip_install/requirements_parser.bzl | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/python/pip_install/private/test/requirements_parser_tests.bzl b/python/pip_install/private/test/requirements_parser_tests.bzl index 037e7ea9df..23b67456ab 100644 --- a/python/pip_install/private/test/requirements_parser_tests.bzl +++ b/python/pip_install/private/test/requirements_parser_tests.bzl @@ -60,16 +60,16 @@ certifi==2021.10.8 \ # Options asserts.equals(env, ["--pre"], parse("--pre\n").options) - asserts.equals(env, ["--find-links /my/local/archives"], parse("--find-links /my/local/archives\n").options) - asserts.equals(env, ["--pre", "--find-links /my/local/archives"], parse("""\ + asserts.equals(env, ["--find-links", "/my/local/archives"], parse("--find-links /my/local/archives\n").options) + asserts.equals(env, ["--pre", "--find-links", "/my/local/archives"], parse("""\ --pre --find-links /my/local/archives """).options) - asserts.equals(env, ["--pre", "--find-links /my/local/archives"], parse("""\ + asserts.equals(env, ["--pre", "--find-links", "/my/local/archives"], parse("""\ --pre # Comment --find-links /my/local/archives """).options) - asserts.equals(env, struct(requirements = [("FooProject", "FooProject==1.0.0")], options = ["--pre", "--find-links /my/local/archives"]), parse("""\ + asserts.equals(env, struct(requirements = [("FooProject", "FooProject==1.0.0")], options = ["--pre", "--find-links", "/my/local/archives"]), parse("""\ --pre # Comment FooProject==1.0.0 --find-links /my/local/archives diff --git a/python/pip_install/requirements_parser.bzl b/python/pip_install/requirements_parser.bzl index 2e62bcc699..6200382f4f 100644 --- a/python/pip_install/requirements_parser.bzl +++ b/python/pip_install/requirements_parser.bzl @@ -96,6 +96,9 @@ def _handleParseDependency(input, buffer, result): def _handleParseOption(input, buffer, result): if input == "\n" and buffer.endswith("\\"): return (_STATE.ParseOption, buffer[0:-1]) + elif input == " ": + result.options.append(buffer.rstrip("\n")) + return (_STATE.ParseOption, "") elif input == "\n" or input == EOF: result.options.append(buffer.rstrip("\n")) return (_STATE.ConsumeSpace, "") From fd5f5318cdcac1dac4a69bf284a40e21a45fdb50 Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius Date: Thu, 26 Jan 2023 04:20:12 +0900 Subject: [PATCH 132/234] feat(gazelle)!: Move the plugin to a separate workspace (#972) feat!(gazelle): Move the plugin to a separate workspace Summary: * Move go.mod to gazelle. * Move gazelle definition. * Fix file distribution for the gazelle module. * Update the example test. * Include rules_python_gazelle_plugin during integration tests * Update ignored packages * Update CI configuration --- .bazelci/presubmit.yml | 11 ++--- .github/workflows/workspace_snippet.sh | 16 ++++++- .gitignore | 5 -- BUILD.bazel | 20 +------- WORKSPACE | 19 ++++++-- examples/build_file_generation/BUILD.bazel | 8 ++-- examples/build_file_generation/WORKSPACE | 18 ++++++- .../build_file_generation/gazelle_python.yaml | 2 +- gazelle/.bazelrc | 13 +++++ gazelle/.gitignore | 12 +++++ gazelle/BUILD.bazel | 43 +++++++++++------ gazelle/README.md | 18 +++++-- gazelle/WORKSPACE | 47 +++++++++++++++++++ gazelle/def.bzl | 4 +- go.mod => gazelle/go.mod | 2 +- go.sum => gazelle/go.sum | 0 gazelle/manifest/BUILD.bazel | 7 +-- gazelle/manifest/defs.bzl | 12 ++--- gazelle/manifest/generate/BUILD.bazel | 6 +-- gazelle/manifest/hasher/BUILD.bazel | 6 +++ gazelle/manifest/test/BUILD.bazel | 4 +- gazelle/modules_mapping/BUILD.bazel | 2 +- gazelle/modules_mapping/def.bzl | 2 +- gazelle/python/BUILD.bazel | 6 +-- gazelle/python/parser.go | 2 +- gazelle/python/python_test.go | 2 +- gazelle/python/std_modules.go | 2 +- gazelle/pythonconfig/BUILD.bazel | 4 +- internal_deps.bzl | 2 + internal_setup.bzl | 12 ----- tools/bazel_integration_test/test_runner.py | 4 ++ 31 files changed, 208 insertions(+), 103 deletions(-) create mode 100644 gazelle/.bazelrc create mode 100644 gazelle/.gitignore create mode 100644 gazelle/WORKSPACE rename go.mod => gazelle/go.mod (90%) rename go.sum => gazelle/go.sum (100%) diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 41c75b7f6c..085a873001 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -10,17 +10,11 @@ buildifier: # As a regression test for #225, check that wheel targets still build when # their package path is qualified with the repo name. - "@rules_python//examples/wheel/..." - - "-//gazelle/..." build_flags: - "--keep_going" test_targets: - "--" - "..." - # The gazelle tests are not compatible with Windows, so we only test them - # on Linux. The build file generation, which uses this Gazelle extension, - # runs on all platforms, and is asserted by the build_file_generation - # integration tests below. - - "-//gazelle/..." test_flags: - "--test_tag_filters=-integration-test" .reusable_build_test_all: &reusable_build_test_all @@ -30,8 +24,9 @@ tasks: gazelle_extension: name: Test the Gazelle extension platform: ubuntu2004 - build_targets: ["//gazelle/..."] - test_targets: ["//gazelle/..."] + build_targets: ["//..."] + test_targets: ["//..."] + working_directory: gazelle ubuntu: <<: *reusable_config name: Default test on Ubuntu diff --git a/.github/workflows/workspace_snippet.sh b/.github/workflows/workspace_snippet.sh index 4837f731e7..843be7a2f4 100755 --- a/.github/workflows/workspace_snippet.sh +++ b/.github/workflows/workspace_snippet.sh @@ -40,7 +40,7 @@ register_toolchains( ) \`\`\` -## Using WORKSPACE: +## Using WORKSPACE Paste this snippet into your \`WORKSPACE\` file: @@ -58,4 +58,18 @@ load("@rules_python//python:repositories.bzl", "py_repositories") py_repositories() \`\`\` + +### Gazelle plugin + +Paste this snippet into your \`WORKSPACE\` file: + +\`\`\`starlark +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +http_archive( + name = "rules_python_gazelle_plugin", + sha256 = "${SHA}", + strip_prefix = "${PREFIX}/gazelle", + url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/${TAG}.tar.gz", +) +\`\`\` EOF diff --git a/.gitignore b/.gitignore index a68c6f05cc..bf901e2fca 100644 --- a/.gitignore +++ b/.gitignore @@ -43,10 +43,5 @@ user.bazelrc *.swp *.swo -# Go/Gazelle files -# These otherwise match patterns above -!go.mod -!BUILD.out - # Python cache **/__pycache__/ diff --git a/BUILD.bazel b/BUILD.bazel index 5e9b5920a7..fc95328a89 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -load("@bazel_gazelle//:def.bzl", "gazelle") load(":version.bzl", "BAZEL_VERSION") package(default_visibility = ["//visibility:public"]) @@ -32,10 +31,10 @@ filegroup( "WORKSPACE", "internal_deps.bzl", "internal_setup.bzl", - "//gazelle:distribution", "//python:distribution", "//python/pip_install:distribution", "//tools:distribution", + "@rules_python_gazelle_plugin//:distribution", ], visibility = [ "//examples:__pkg__", @@ -61,23 +60,6 @@ filegroup( visibility = ["//visibility:public"], ) -# Gazelle configuration options. -# See https://github.com/bazelbuild/bazel-gazelle#running-gazelle-with-bazel -# gazelle:prefix github.com/bazelbuild/rules_python -# gazelle:exclude bazel-out -# gazelle:exclude examples/** -gazelle(name = "gazelle") - -gazelle( - name = "gazelle_update_repos", - args = [ - "-from_file=go.mod", - "-to_macro=gazelle/deps.bzl%gazelle_deps", - "-prune", - ], - command = "update-repos", -) - genrule( name = "assert_bazelversion", srcs = [".bazelversion"], diff --git a/WORKSPACE b/WORKSPACE index 1d9d5e4e48..b7059b6271 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -34,11 +34,6 @@ python_register_multi_toolchains( python_versions = MINOR_MAPPING.values(), ) -load("//gazelle:deps.bzl", "gazelle_deps") - -# gazelle:repository_macro gazelle/deps.bzl%gazelle_deps -gazelle_deps() - load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") # Used for Bazel CI @@ -58,3 +53,17 @@ rbe_preconfig( name = "buildkite_config", toolchain = "ubuntu1804-bazel-java11", ) + +local_repository( + name = "rules_python_gazelle_plugin", + path = "gazelle", +) + +# The rules_python gazelle extension has some third-party go dependencies +# which we need to fetch in order to compile it. +load("@rules_python_gazelle_plugin//:deps.bzl", _py_gazelle_deps = "gazelle_deps") + +# See: https://github.com/bazelbuild/rules_python/blob/main/gazelle/README.md +# This rule loads and compiles various go dependencies that running gazelle +# for python requirements. +_py_gazelle_deps() diff --git a/examples/build_file_generation/BUILD.bazel b/examples/build_file_generation/BUILD.bazel index 6bd1a929de..6419ef2c70 100644 --- a/examples/build_file_generation/BUILD.bazel +++ b/examples/build_file_generation/BUILD.bazel @@ -4,11 +4,11 @@ # ruleset. When the symbol is loaded you can use the rule. load("@bazel_gazelle//:def.bzl", "gazelle") load("@pip//:requirements.bzl", "all_whl_requirements") -load("@rules_python//gazelle:def.bzl", "GAZELLE_PYTHON_RUNTIME_DEPS") -load("@rules_python//gazelle/manifest:defs.bzl", "gazelle_python_manifest") -load("@rules_python//gazelle/modules_mapping:def.bzl", "modules_mapping") load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test") load("@rules_python//python:pip.bzl", "compile_pip_requirements") +load("@rules_python_gazelle_plugin//:def.bzl", "GAZELLE_PYTHON_RUNTIME_DEPS") +load("@rules_python_gazelle_plugin//manifest:defs.bzl", "gazelle_python_manifest") +load("@rules_python_gazelle_plugin//modules_mapping:def.bzl", "modules_mapping") compile_pip_requirements( name = "requirements", @@ -53,7 +53,7 @@ gazelle_python_manifest( gazelle( name = "gazelle", data = GAZELLE_PYTHON_RUNTIME_DEPS, - gazelle = "@rules_python//gazelle:gazelle_python_binary", + gazelle = "@rules_python_gazelle_plugin//python:gazelle_binary", ) # This rule is auto-generated and managed by Gazelle, diff --git a/examples/build_file_generation/WORKSPACE b/examples/build_file_generation/WORKSPACE index 1f411d6cb9..674b9eb7ea 100644 --- a/examples/build_file_generation/WORKSPACE +++ b/examples/build_file_generation/WORKSPACE @@ -82,6 +82,22 @@ local_repository( # url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/0.16.1.tar.gz", # ) +# We import the repository-local rules_python_gazelle_plugin version in order to +# be able to test development changes to the plugin. +local_repository( + name = "rules_python_gazelle_plugin", + path = "../../gazelle", +) + +# When loading the gazelle plugin outside this repo, use the http_archive rule as follows: +# +#http_archive( +# name = "rules_python_gazelle_plugin", +# sha256 = "497ca47374f48c8b067d786b512ac10a276211810f4a580178ee9b9ad139323a", +# strip_prefix = "rules_python-0.16.1/gazelle", +# url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/0.16.1.tar.gz", +#) + # Next we load the toolchain from rules_python. load("@rules_python//python:repositories.bzl", "python_register_toolchains") @@ -124,7 +140,7 @@ install_deps() # The rules_python gazelle extension has some third-party go dependencies # which we need to fetch in order to compile it. -load("@rules_python//gazelle:deps.bzl", _py_gazelle_deps = "gazelle_deps") +load("@rules_python_gazelle_plugin//:deps.bzl", _py_gazelle_deps = "gazelle_deps") # See: https://github.com/bazelbuild/rules_python/blob/main/gazelle/README.md # This rule loads and compiles various go dependencies that running gazelle diff --git a/examples/build_file_generation/gazelle_python.yaml b/examples/build_file_generation/gazelle_python.yaml index 0be959a67e..847d1ecc55 100644 --- a/examples/build_file_generation/gazelle_python.yaml +++ b/examples/build_file_generation/gazelle_python.yaml @@ -114,4 +114,4 @@ manifest: zipp.py310compat: zipp pip_repository: name: pip -integrity: 4153df7683d64d7d6ad56c14ea1c7f7bec84a2ddf9ef8f075d1bb9313b8d11aa +integrity: 2c84a3cabeaff134a1d045e5a173a3178086f236ab20f895ffbd7f3b7a6e5bb0 diff --git a/gazelle/.bazelrc b/gazelle/.bazelrc new file mode 100644 index 0000000000..f48d0a97ee --- /dev/null +++ b/gazelle/.bazelrc @@ -0,0 +1,13 @@ +test --test_output=errors + +# Do NOT implicitly create empty __init__.py files in the runfiles tree. +# By default, these are created in every directory containing Python source code +# or shared libraries, and every parent directory of those directories, +# excluding the repo root directory. With this flag set, we are responsible for +# creating (possibly empty) __init__.py files and adding them to the srcs of +# Python targets as required. +build --incompatible_default_to_explicit_init_py + +# Windows makes use of runfiles for some rules +build --enable_runfiles +startup --windows_enable_symlinks diff --git a/gazelle/.gitignore b/gazelle/.gitignore new file mode 100644 index 0000000000..8481c9668c --- /dev/null +++ b/gazelle/.gitignore @@ -0,0 +1,12 @@ +# Bazel directories +/bazel-* +/bazel-bin +/bazel-genfiles +/bazel-out +/bazel-testlogs +user.bazelrc + +# Go/Gazelle files +# These otherwise match patterns above +!go.mod +!BUILD.out diff --git a/gazelle/BUILD.bazel b/gazelle/BUILD.bazel index 8a67e1a2f9..6016145516 100644 --- a/gazelle/BUILD.bazel +++ b/gazelle/BUILD.bazel @@ -1,22 +1,35 @@ -alias( - name = "gazelle", - actual = "//gazelle/python", - visibility = ["//visibility:public"], -) +load("@bazel_gazelle//:def.bzl", "gazelle") + +# Gazelle configuration options. +# See https://github.com/bazelbuild/bazel-gazelle#running-gazelle-with-bazel +# gazelle:prefix github.com/bazelbuild/rules_python/gazelle +# gazelle:exclude bazel-out +gazelle(name = "gazelle") -alias( - name = "gazelle_python_binary", - actual = "//gazelle/python:gazelle_binary", - visibility = ["//visibility:public"], +gazelle( + name = "gazelle_update_repos", + args = [ + "-from_file=go.mod", + "-to_macro=deps.bzl%gazelle_deps", + "-prune", + ], + command = "update-repos", ) filegroup( name = "distribution", - srcs = glob(["**"]) + [ - "//gazelle/manifest:distribution", - "//gazelle/modules_mapping:distribution", - "//gazelle/python:distribution", - "//gazelle/pythonconfig:distribution", + srcs = [ + ":BUILD.bazel", + ":README.md", + ":WORKSPACE", + ":def.bzl", + ":deps.bzl", + ":go.mod", + ":go.sum", + "//manifest:distribution", + "//modules_mapping:distribution", + "//python:distribution", + "//pythonconfig:distribution", ], - visibility = ["//:__pkg__"], + visibility = ["@rules_python//:__pkg__"], ) diff --git a/gazelle/README.md b/gazelle/README.md index a54db64ed8..a76ac59199 100644 --- a/gazelle/README.md +++ b/gazelle/README.md @@ -17,9 +17,17 @@ depends on. Add this to your `WORKSPACE`: ```starlark +http_archive( + name = "rules_python_gazelle_plugin", + sha256 = "", + strip_prefix = "rules_python-0.17.0/gazelle", + url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/0.17.0.tar.gz", +) + # To compile the rules_python gazelle extension from source, # we must fetch some third-party go dependencies that it uses. -load("@rules_python//gazelle:deps.bzl", _py_gazelle_deps = "gazelle_deps") + +load("@rules_python_gazelle_plugin//:deps.bzl", _py_gazelle_deps = "gazelle_deps") _py_gazelle_deps() ``` @@ -40,8 +48,8 @@ To keep the metadata updated, put this in your `BUILD.bazel` file next to `gazel ```starlark load("@pip//:requirements.bzl", "all_whl_requirements") -load("@rules_python//gazelle/manifest:defs.bzl", "gazelle_python_manifest") -load("@rules_python//gazelle/modules_mapping:def.bzl", "modules_mapping") +load("@rules_python_gazelle_plugin//manifest:defs.bzl", "gazelle_python_manifest") +load("@rules_python_gazelle_plugin//modules_mapping:def.bzl", "modules_mapping") # This rule fetches the metadata for python packages we depend on. That data is # required for the gazelle_python_manifest rule to update our manifest file. @@ -75,7 +83,7 @@ with the rules_python extension included. This typically goes in your root ``` load("@bazel_gazelle//:def.bzl", "gazelle") -load("@rules_python//gazelle:def.bzl", "GAZELLE_PYTHON_RUNTIME_DEPS") +load("@rules_python_gazelle_plugin//:def.bzl", "GAZELLE_PYTHON_RUNTIME_DEPS") # Our gazelle target points to the python gazelle binary. # This is the simple case where we only need one language supported. @@ -85,7 +93,7 @@ load("@rules_python//gazelle:def.bzl", "GAZELLE_PYTHON_RUNTIME_DEPS") gazelle( name = "gazelle", data = GAZELLE_PYTHON_RUNTIME_DEPS, - gazelle = "@rules_python//gazelle:gazelle_python_binary", + gazelle = "@rules_python_gazelle_plugin//python:gazelle_binary", ) ``` diff --git a/gazelle/WORKSPACE b/gazelle/WORKSPACE new file mode 100644 index 0000000000..55cf1b0d40 --- /dev/null +++ b/gazelle/WORKSPACE @@ -0,0 +1,47 @@ +workspace(name = "rules_python_gazelle_plugin") + +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +http_archive( + name = "io_bazel_rules_go", + sha256 = "099a9fb96a376ccbbb7d291ed4ecbdfd42f6bc822ab77ae6f1b5cb9e914e94fa", + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.35.0/rules_go-v0.35.0.zip", + "https://github.com/bazelbuild/rules_go/releases/download/v0.35.0/rules_go-v0.35.0.zip", + ], +) + +http_archive( + name = "bazel_gazelle", + sha256 = "448e37e0dbf61d6fa8f00aaa12d191745e14f07c31cabfa731f0c8e8a4f41b97", + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.28.0/bazel-gazelle-v0.28.0.tar.gz", + "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.28.0/bazel-gazelle-v0.28.0.tar.gz", + ], +) + +load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies") +load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") + +go_rules_dependencies() + +go_register_toolchains(version = "1.19.4") + +gazelle_dependencies() + +local_repository( + name = "rules_python", + path = "..", +) + +load("@rules_python//python:repositories.bzl", "python_register_toolchains") + +python_register_toolchains( + name = "python39", + python_version = "3.9", +) + +load("//:deps.bzl", _py_gazelle_deps = "gazelle_deps") + +# gazelle:repository_macro deps.bzl%gazelle_deps +_py_gazelle_deps() diff --git a/gazelle/def.bzl b/gazelle/def.bzl index aa6c23eb76..bb53c30276 100644 --- a/gazelle/def.bzl +++ b/gazelle/def.bzl @@ -2,6 +2,6 @@ """ GAZELLE_PYTHON_RUNTIME_DEPS = [ - "@rules_python//gazelle/python:parse", - "@rules_python//gazelle/python:std_modules", + "@rules_python_gazelle_plugin//python:parse", + "@rules_python_gazelle_plugin//python:std_modules", ] diff --git a/go.mod b/gazelle/go.mod similarity index 90% rename from go.mod rename to gazelle/go.mod index 0afdf52445..322cf0db98 100644 --- a/go.mod +++ b/gazelle/go.mod @@ -1,4 +1,4 @@ -module github.com/bazelbuild/rules_python +module github.com/bazelbuild/rules_python/gazelle go 1.19 diff --git a/go.sum b/gazelle/go.sum similarity index 100% rename from go.sum rename to gazelle/go.sum diff --git a/gazelle/manifest/BUILD.bazel b/gazelle/manifest/BUILD.bazel index a769d0d64d..fc7fa09632 100644 --- a/gazelle/manifest/BUILD.bazel +++ b/gazelle/manifest/BUILD.bazel @@ -21,8 +21,9 @@ go_test( filegroup( name = "distribution", srcs = glob(["**"]) + [ - "//gazelle/manifest/generate:distribution", - "//gazelle/manifest/test:distribution", + "//manifest/generate:distribution", + "//manifest/hasher:distribution", + "//manifest/test:distribution", ], - visibility = ["//gazelle:__pkg__"], + visibility = ["//:__pkg__"], ) diff --git a/gazelle/manifest/defs.bzl b/gazelle/manifest/defs.bzl index 57f52f986e..3bbcf99701 100644 --- a/gazelle/manifest/defs.bzl +++ b/gazelle/manifest/defs.bzl @@ -36,7 +36,7 @@ def gazelle_python_manifest( update_target = "{}.update".format(name) update_target_label = "//{}:{}".format(native.package_name(), update_target) - manifest_generator_hash = Label("//gazelle/manifest/generate:generate_lib_sources_hash") + manifest_generator_hash = Label("//manifest/generate:generate_lib_sources_hash") update_args = [ "--manifest-generator-hash", @@ -55,7 +55,7 @@ def gazelle_python_manifest( go_binary( name = update_target, - embed = [Label("//gazelle/manifest/generate:generate_lib")], + embed = [Label("//manifest/generate:generate_lib")], data = [ manifest, modules_mapping, @@ -71,13 +71,13 @@ def gazelle_python_manifest( go_binary( name = test_binary, - embed = [Label("//gazelle/manifest/test:test_lib")], + embed = [Label("//manifest/test:test_lib")], visibility = ["//visibility:private"], ) native.sh_test( name = "{}.test".format(name), - srcs = [Label("//gazelle/manifest/test:run.sh")], + srcs = [Label("//manifest/test:run.sh")], data = [ ":{}".format(test_binary), manifest, @@ -104,7 +104,7 @@ def gazelle_python_manifest( # buildifier: disable=provider-params AllSourcesInfo = provider(fields = {"all_srcs": "All sources collected from the target and dependencies."}) -_rules_python_workspace = Label("//:WORKSPACE") +_rules_python_workspace = Label("@rules_python//:WORKSPACE") def _get_all_sources_impl(target, ctx): is_rules_python = target.label.workspace_name == _rules_python_workspace.workspace_name @@ -148,7 +148,7 @@ sources_hash = rule( ), "_hasher": attr.label( cfg = "exec", - default = Label("//gazelle/manifest/hasher"), + default = Label("//manifest/hasher"), executable = True, ), }, diff --git a/gazelle/manifest/generate/BUILD.bazel b/gazelle/manifest/generate/BUILD.bazel index 7a5d27ff24..96248f4e08 100644 --- a/gazelle/manifest/generate/BUILD.bazel +++ b/gazelle/manifest/generate/BUILD.bazel @@ -1,12 +1,12 @@ load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") -load("//gazelle/manifest:defs.bzl", "sources_hash") +load("//manifest:defs.bzl", "sources_hash") go_library( name = "generate_lib", srcs = ["generate.go"], importpath = "github.com/bazelbuild/rules_python/gazelle/manifest/generate", visibility = ["//visibility:public"], - deps = ["//gazelle/manifest"], + deps = ["//manifest"], ) sources_hash( @@ -24,5 +24,5 @@ go_binary( filegroup( name = "distribution", srcs = glob(["**"]), - visibility = ["//gazelle/manifest:__pkg__"], + visibility = ["//manifest:__pkg__"], ) diff --git a/gazelle/manifest/hasher/BUILD.bazel b/gazelle/manifest/hasher/BUILD.bazel index 5e67b2f549..2e7b125cc0 100644 --- a/gazelle/manifest/hasher/BUILD.bazel +++ b/gazelle/manifest/hasher/BUILD.bazel @@ -12,3 +12,9 @@ go_binary( embed = [":hasher_lib"], visibility = ["//visibility:public"], ) + +filegroup( + name = "distribution", + srcs = glob(["**"]), + visibility = ["//manifest:__pkg__"], +) diff --git a/gazelle/manifest/test/BUILD.bazel b/gazelle/manifest/test/BUILD.bazel index 3f4a535957..c8b28286f3 100644 --- a/gazelle/manifest/test/BUILD.bazel +++ b/gazelle/manifest/test/BUILD.bazel @@ -5,7 +5,7 @@ go_library( srcs = ["test.go"], importpath = "github.com/bazelbuild/rules_python/gazelle/manifest/test", visibility = ["//visibility:public"], - deps = ["//gazelle/manifest"], + deps = ["//manifest"], ) go_binary( @@ -19,5 +19,5 @@ exports_files(["run.sh"]) filegroup( name = "distribution", srcs = glob(["**"]), - visibility = ["//gazelle/manifest:__pkg__"], + visibility = ["//manifest:__pkg__"], ) diff --git a/gazelle/modules_mapping/BUILD.bazel b/gazelle/modules_mapping/BUILD.bazel index d4b35c8a45..1855551a80 100644 --- a/gazelle/modules_mapping/BUILD.bazel +++ b/gazelle/modules_mapping/BUILD.bazel @@ -9,5 +9,5 @@ py_binary( filegroup( name = "distribution", srcs = glob(["**"]), - visibility = ["//gazelle:__pkg__"], + visibility = ["//:__pkg__"], ) diff --git a/gazelle/modules_mapping/def.bzl b/gazelle/modules_mapping/def.bzl index 9b1352c5e4..8cffb31cbf 100644 --- a/gazelle/modules_mapping/def.bzl +++ b/gazelle/modules_mapping/def.bzl @@ -44,7 +44,7 @@ modules_mapping = rule( ), "_generator": attr.label( cfg = "exec", - default = "//gazelle/modules_mapping:generator", + default = "//modules_mapping:generator", executable = True, ), }, diff --git a/gazelle/python/BUILD.bazel b/gazelle/python/BUILD.bazel index 659f6eb72b..a2bfb2730f 100644 --- a/gazelle/python/BUILD.bazel +++ b/gazelle/python/BUILD.bazel @@ -22,8 +22,8 @@ go_library( importpath = "github.com/bazelbuild/rules_python/gazelle/python", visibility = ["//visibility:public"], deps = [ - "//gazelle/manifest", - "//gazelle/pythonconfig", + "//manifest", + "//pythonconfig", "@bazel_gazelle//config:go_default_library", "@bazel_gazelle//label:go_default_library", "@bazel_gazelle//language:go_default_library", @@ -77,5 +77,5 @@ gazelle_binary( filegroup( name = "distribution", srcs = glob(["**"]), - visibility = ["//gazelle:__pkg__"], + visibility = ["//:__pkg__"], ) diff --git a/gazelle/python/parser.go b/gazelle/python/parser.go index df4a0fcbbc..fdb34f76c1 100644 --- a/gazelle/python/parser.go +++ b/gazelle/python/parser.go @@ -25,7 +25,7 @@ var ( ) func init() { - parseScriptRunfile, err := bazel.Runfile("gazelle/python/parse") + parseScriptRunfile, err := bazel.Runfile("python/parse") if err != nil { log.Printf("failed to initialize parser: %v\n", err) os.Exit(1) diff --git a/gazelle/python/python_test.go b/gazelle/python/python_test.go index 6622bcbf23..e8edf89275 100644 --- a/gazelle/python/python_test.go +++ b/gazelle/python/python_test.go @@ -38,7 +38,7 @@ import ( ) const ( - extensionDir = "gazelle" + string(os.PathSeparator) + "python" + string(os.PathSeparator) + extensionDir = "python" + string(os.PathSeparator) testDataPath = extensionDir + "testdata" + string(os.PathSeparator) gazelleBinaryName = "gazelle_binary" ) diff --git a/gazelle/python/std_modules.go b/gazelle/python/std_modules.go index 9ef1ecbd94..5f4df63455 100644 --- a/gazelle/python/std_modules.go +++ b/gazelle/python/std_modules.go @@ -26,7 +26,7 @@ var ( func init() { stdModulesSeen = make(map[string]struct{}) - stdModulesScriptRunfile, err := bazel.Runfile("gazelle/python/std_modules") + stdModulesScriptRunfile, err := bazel.Runfile("python/std_modules") if err != nil { log.Printf("failed to initialize std_modules: %v\n", err) os.Exit(1) diff --git a/gazelle/pythonconfig/BUILD.bazel b/gazelle/pythonconfig/BUILD.bazel index 9472fd49f5..79b512163d 100644 --- a/gazelle/pythonconfig/BUILD.bazel +++ b/gazelle/pythonconfig/BUILD.bazel @@ -9,7 +9,7 @@ go_library( importpath = "github.com/bazelbuild/rules_python/gazelle/pythonconfig", visibility = ["//visibility:public"], deps = [ - "//gazelle/manifest", + "//manifest", "@bazel_gazelle//label:go_default_library", "@com_github_emirpasic_gods//lists/singlylinkedlist", ], @@ -18,5 +18,5 @@ go_library( filegroup( name = "distribution", srcs = glob(["**"]), - visibility = ["//gazelle:__pkg__"], + visibility = ["//:__pkg__"], ) diff --git a/internal_deps.bzl b/internal_deps.bzl index 942a8720e2..15a4f625fa 100644 --- a/internal_deps.bzl +++ b/internal_deps.bzl @@ -34,6 +34,8 @@ def rules_python_internal_deps(): strip_prefix = "stardoc-6f274e903009158504a9d9130d7f7d5f3e9421ed", ) + # The below two deps are required for the integration test with bazel + # gazelle. Maybe the test should be moved to the `gazelle` workspace? maybe( http_archive, name = "io_bazel_rules_go", diff --git a/internal_setup.bzl b/internal_setup.bzl index 57eecc2116..c3a7ad452d 100644 --- a/internal_setup.bzl +++ b/internal_setup.bzl @@ -14,14 +14,11 @@ """Setup for rules_python tests and tools.""" -load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies") load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") load("@build_bazel_integration_testing//tools:repositories.bzl", "bazel_binaries") load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") -load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains") load("//:version.bzl", "SUPPORTED_BAZEL_VERSIONS") -load("//gazelle:deps.bzl", _go_repositories = "gazelle_deps") load("//python/pip_install:repositories.bzl", "pip_install_dependencies") def rules_python_internal_setup(): @@ -35,15 +32,6 @@ def rules_python_internal_setup(): bazel_skylib_workspace() - # gazelle:repository_macro gazelle/deps.bzl%gazelle_deps - _go_repositories() - - go_rules_dependencies() - - go_register_toolchains(version = "1.19.2") - - gazelle_dependencies() - rules_proto_dependencies() rules_proto_toolchains() diff --git a/tools/bazel_integration_test/test_runner.py b/tools/bazel_integration_test/test_runner.py index fbc27e4d4b..27abf1fa9e 100644 --- a/tools/bazel_integration_test/test_runner.py +++ b/tools/bazel_integration_test/test_runner.py @@ -52,6 +52,10 @@ def main(conf_file): "--override_repository=rules_python=%s/rules_python" % os.environ["TEST_SRCDIR"] ) + bazel_args.append( + "--override_repository=rules_python_gazelle_plugin=%s/rules_python_gazelle_plugin" + % os.environ["TEST_SRCDIR"] + ) # TODO: --override_module isn't supported in the current BAZEL_VERSION (5.2.0) # This condition and attribute can be removed when bazel is updated for From 996025317896846267c40ef1934b9e71e3445e8b Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Wed, 25 Jan 2023 12:26:48 -0800 Subject: [PATCH 133/234] refactor: py_wheel now a macro (#1014) This gives us the place to insert other targets produced by it, such as a publishing target. Part of #99 --- docs/packaging.md | 121 ++++++++++++++++++++++-------------- python/packaging.bzl | 97 ++++++++++++++++------------- python/private/py_wheel.bzl | 12 ++++ 3 files changed, 140 insertions(+), 90 deletions(-) diff --git a/docs/packaging.md b/docs/packaging.md index 86ba81e477..b750db64f5 100755 --- a/docs/packaging.md +++ b/docs/packaging.md @@ -26,21 +26,84 @@ This rule is intended to be used as data dependency to py_wheel rule. | packages | List of Python packages to include in the distribution. Sub-packages are automatically included. | List of strings | optional | [] | + + +## py_wheel_rule + +
+py_wheel_rule(name, abi, author, author_email, classifiers, console_scripts, deps, description_file,
+              distribution, entry_points, extra_distinfo_files, extra_requires, homepage, license,
+              platform, python_requires, python_tag, requires, stamp, strip_path_prefixes, version)
+
+ +Internal rule used by the [py_wheel macro](/docs/packaging.md#py_wheel). + +These intentionally have the same name to avoid sharp edges with Bazel macros. +For example, a `bazel query` for a user's `py_wheel` macro expands to `py_wheel` targets, +in the way they expect. + + +**ATTRIBUTES** + + +| Name | Description | Type | Mandatory | Default | +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this target. | Name | required | | +| abi | Python ABI tag. 'none' for pure-Python wheels. | String | optional | "none" | +| author | A string specifying the author of the package. | String | optional | "" | +| author_email | A string specifying the email address of the package author. | String | optional | "" | +| classifiers | A list of strings describing the categories for the package. For valid classifiers see https://pypi.org/classifiers | List of strings | optional | [] | +| console_scripts | Deprecated console_script entry points, e.g. {'main': 'examples.wheel.main:main'}.

Deprecated: prefer the entry_points attribute, which supports console_scripts as well as other entry points. | Dictionary: String -> String | optional | {} | +| deps | Targets to be included in the distribution.

The targets to package are usually py_library rules or filesets (for packaging data files).

Note it's usually better to package py_library targets and use entry_points attribute to specify console_scripts than to package py_binary rules. py_binary targets would wrap a executable script that tries to locate .runfiles directory which is not packaged in the wheel. | List of labels | optional | [] | +| description_file | A file containing text describing the package. | Label | optional | None | +| distribution | Name of the distribution.

This should match the project name onm PyPI. It's also the name that is used to refer to the package in other packages' dependencies. | String | required | | +| entry_points | entry_points, e.g. {'console_scripts': ['main = examples.wheel.main:main']}. | Dictionary: String -> List of strings | optional | {} | +| extra_distinfo_files | Extra files to add to distinfo directory in the archive. | Dictionary: Label -> String | optional | {} | +| extra_requires | List of optional requirements for this package | Dictionary: String -> List of strings | optional | {} | +| homepage | A string specifying the URL for the package homepage. | String | optional | "" | +| license | A string specifying the license of the package. | String | optional | "" | +| platform | Supported platform. Use 'any' for pure-Python wheel.

If you have included platform-specific data, such as a .pyd or .so extension module, you will need to specify the platform in standard pip format. If you support multiple platforms, you can define platform constraints, then use a select() to specify the appropriate specifier, eg:

platform = select({ "//platforms:windows_x86_64": "win_amd64", "//platforms:macos_x86_64": "macosx_10_7_x86_64", "//platforms:linux_x86_64": "manylinux2014_x86_64", }) | String | optional | "any" | +| python_requires | Python versions required by this distribution, e.g. '>=3.5,<3.7' | String | optional | "" | +| python_tag | Supported Python version(s), eg py3, cp35.cp36, etc | String | optional | "py3" | +| requires | List of requirements for this package. See the section on [Declaring required dependency](https://setuptools.readthedocs.io/en/latest/userguide/dependency_management.html#declaring-dependencies) for details and examples of the format of this argument. | List of strings | optional | [] | +| stamp | Whether to encode build information into the wheel. Possible values:

- stamp = 1: Always stamp the build information into the wheel, even in [--nostamp](https://docs.bazel.build/versions/main/user-manual.html#flag--stamp) builds. This setting should be avoided, since it potentially kills remote caching for the target and any downstream actions that depend on it.

- stamp = 0: Always replace build information by constant values. This gives good build result caching.

- stamp = -1: Embedding of build information is controlled by the [--[no]stamp](https://docs.bazel.build/versions/main/user-manual.html#flag--stamp) flag.

Stamped targets are not rebuilt unless their dependencies change. | Integer | optional | -1 | +| strip_path_prefixes | path prefixes to strip from files added to the generated package | List of strings | optional | [] | +| version | Version number of the package. Note that this attribute supports stamp format strings (eg. 1.2.3-{BUILD_TIMESTAMP}) as well as 'make variables' (e.g. 1.2.3-$(VERSION)). | String | required | | + + + + +## PyWheelInfo + +
+PyWheelInfo(name_file, wheel)
+
+ +Information about a wheel produced by `py_wheel` + +**FIELDS** + + +| Name | Description | +| :------------- | :------------- | +| name_file | File: A file containing the canonical name of the wheel (after stamping, if enabled). | +| wheel | File: The wheel file itself. | + + ## py_wheel
-py_wheel(name, abi, author, author_email, classifiers, console_scripts, deps, description_file,
-         distribution, entry_points, extra_distinfo_files, extra_requires, homepage, license,
-         platform, python_requires, python_tag, requires, stamp, strip_path_prefixes, version)
+py_wheel(name, kwargs)
 
-A rule for building Python Wheels. +Builds a Python Wheel. Wheels are Python distribution format defined in https://www.python.org/dev/peps/pep-0427/. -This rule packages a set of targets into a single wheel. +This macro packages a set of targets into a single wheel. +It wraps the [py_wheel rule](#py_wheel_rule). Currently only pure-python wheels are supported. @@ -80,50 +143,12 @@ py_wheel( ``` -**ATTRIBUTES** - - -| Name | Description | Type | Mandatory | Default | -| :------------- | :------------- | :------------- | :------------- | :------------- | -| name | A unique name for this target. | Name | required | | -| abi | Python ABI tag. 'none' for pure-Python wheels. | String | optional | "none" | -| author | A string specifying the author of the package. | String | optional | "" | -| author_email | A string specifying the email address of the package author. | String | optional | "" | -| classifiers | A list of strings describing the categories for the package. For valid classifiers see https://pypi.org/classifiers | List of strings | optional | [] | -| console_scripts | Deprecated console_script entry points, e.g. {'main': 'examples.wheel.main:main'}.

Deprecated: prefer the entry_points attribute, which supports console_scripts as well as other entry points. | Dictionary: String -> String | optional | {} | -| deps | Targets to be included in the distribution.

The targets to package are usually py_library rules or filesets (for packaging data files).

Note it's usually better to package py_library targets and use entry_points attribute to specify console_scripts than to package py_binary rules. py_binary targets would wrap a executable script that tries to locate .runfiles directory which is not packaged in the wheel. | List of labels | optional | [] | -| description_file | A file containing text describing the package. | Label | optional | None | -| distribution | Name of the distribution.

This should match the project name onm PyPI. It's also the name that is used to refer to the package in other packages' dependencies. | String | required | | -| entry_points | entry_points, e.g. {'console_scripts': ['main = examples.wheel.main:main']}. | Dictionary: String -> List of strings | optional | {} | -| extra_distinfo_files | Extra files to add to distinfo directory in the archive. | Dictionary: Label -> String | optional | {} | -| extra_requires | List of optional requirements for this package | Dictionary: String -> List of strings | optional | {} | -| homepage | A string specifying the URL for the package homepage. | String | optional | "" | -| license | A string specifying the license of the package. | String | optional | "" | -| platform | Supported platform. Use 'any' for pure-Python wheel.

If you have included platform-specific data, such as a .pyd or .so extension module, you will need to specify the platform in standard pip format. If you support multiple platforms, you can define platform constraints, then use a select() to specify the appropriate specifier, eg:

platform = select({ "//platforms:windows_x86_64": "win_amd64", "//platforms:macos_x86_64": "macosx_10_7_x86_64", "//platforms:linux_x86_64": "manylinux2014_x86_64", }) | String | optional | "any" | -| python_requires | Python versions required by this distribution, e.g. '>=3.5,<3.7' | String | optional | "" | -| python_tag | Supported Python version(s), eg py3, cp35.cp36, etc | String | optional | "py3" | -| requires | List of requirements for this package. See the section on [Declaring required dependency](https://setuptools.readthedocs.io/en/latest/userguide/dependency_management.html#declaring-dependencies) for details and examples of the format of this argument. | List of strings | optional | [] | -| stamp | Whether to encode build information into the wheel. Possible values:

- stamp = 1: Always stamp the build information into the wheel, even in [--nostamp](https://docs.bazel.build/versions/main/user-manual.html#flag--stamp) builds. This setting should be avoided, since it potentially kills remote caching for the target and any downstream actions that depend on it.

- stamp = 0: Always replace build information by constant values. This gives good build result caching.

- stamp = -1: Embedding of build information is controlled by the [--[no]stamp](https://docs.bazel.build/versions/main/user-manual.html#flag--stamp) flag.

Stamped targets are not rebuilt unless their dependencies change. | Integer | optional | -1 | -| strip_path_prefixes | path prefixes to strip from files added to the generated package | List of strings | optional | [] | -| version | Version number of the package. Note that this attribute supports stamp format strings (eg. 1.2.3-{BUILD_TIMESTAMP}) as well as 'make variables' (e.g. 1.2.3-$(VERSION)). | String | required | | - - - - -## PyWheelInfo - -
-PyWheelInfo(name_file, wheel)
-
- -Information about a wheel produced by `py_wheel` - -**FIELDS** +**PARAMETERS** -| Name | Description | -| :------------- | :------------- | -| name_file | File: A file containing the canonical name of the wheel (after stamping, if enabled). | -| wheel | File: The wheel file itself. | +| Name | Description | Default Value | +| :------------- | :------------- | :------------- | +| name | A unique name for this target. | none | +| kwargs | other named parameters passed to the underlying [py_wheel rule](#py_wheel_rule) | none | diff --git a/python/packaging.bzl b/python/packaging.bzl index 763d7c5486..3b0b016321 100644 --- a/python/packaging.bzl +++ b/python/packaging.bzl @@ -15,7 +15,7 @@ """Public API for for building wheels.""" load("//python/private:py_package.bzl", "py_package_lib") -load("//python/private:py_wheel.bzl", "py_wheel_lib", _PyWheelInfo = "PyWheelInfo") +load("//python/private:py_wheel.bzl", _PyWheelInfo = "PyWheelInfo", _py_wheel = "py_wheel") # Re-export as public API PyWheelInfo = _PyWheelInfo @@ -31,51 +31,64 @@ This rule is intended to be used as data dependency to py_wheel rule. attrs = py_package_lib.attrs, ) -py_wheel = rule( - implementation = py_wheel_lib.implementation, - doc = """\ -A rule for building Python Wheels. +def py_wheel(name, **kwargs): + """Builds a Python Wheel. -Wheels are Python distribution format defined in https://www.python.org/dev/peps/pep-0427/. + Wheels are Python distribution format defined in https://www.python.org/dev/peps/pep-0427/. -This rule packages a set of targets into a single wheel. + This macro packages a set of targets into a single wheel. + It wraps the [py_wheel rule](#py_wheel_rule). -Currently only pure-python wheels are supported. + Currently only pure-python wheels are supported. -Examples: + Examples: -```python -# Package some specific py_library targets, without their dependencies -py_wheel( - name = "minimal_with_py_library", - # Package data. We're building "example_minimal_library-0.0.1-py3-none-any.whl" - distribution = "example_minimal_library", - python_tag = "py3", - version = "0.0.1", - deps = [ - "//examples/wheel/lib:module_with_data", - "//examples/wheel/lib:simple_module", - ], -) + ```python + # Package some specific py_library targets, without their dependencies + py_wheel( + name = "minimal_with_py_library", + # Package data. We're building "example_minimal_library-0.0.1-py3-none-any.whl" + distribution = "example_minimal_library", + python_tag = "py3", + version = "0.0.1", + deps = [ + "//examples/wheel/lib:module_with_data", + "//examples/wheel/lib:simple_module", + ], + ) -# Use py_package to collect all transitive dependencies of a target, -# selecting just the files within a specific python package. -py_package( - name = "example_pkg", - # Only include these Python packages. - packages = ["examples.wheel"], - deps = [":main"], -) + # Use py_package to collect all transitive dependencies of a target, + # selecting just the files within a specific python package. + py_package( + name = "example_pkg", + # Only include these Python packages. + packages = ["examples.wheel"], + deps = [":main"], + ) -py_wheel( - name = "minimal_with_py_package", - # Package data. We're building "example_minimal_package-0.0.1-py3-none-any.whl" - distribution = "example_minimal_package", - python_tag = "py3", - version = "0.0.1", - deps = [":example_pkg"], -) -``` -""", - attrs = py_wheel_lib.attrs, -) + py_wheel( + name = "minimal_with_py_package", + # Package data. We're building "example_minimal_package-0.0.1-py3-none-any.whl" + distribution = "example_minimal_package", + python_tag = "py3", + version = "0.0.1", + deps = [":example_pkg"], + ) + ``` + + Args: + name: A unique name for this target. + **kwargs: other named parameters passed to the underlying [py_wheel rule](#py_wheel_rule) + """ + _py_wheel(name = name, **kwargs) + + # TODO(alexeagle): produce an executable target like this: + # py_publish_wheel( + # name = "{}.publish".format(name), + # wheel = name, + # # Optional: override the label for a py_binary that runs twine + # # https://twine.readthedocs.io/en/stable/ + # twine_bin = "//path/to:twine", + # ) + +py_wheel_rule = _py_wheel diff --git a/python/private/py_wheel.bzl b/python/private/py_wheel.bzl index 6d2c9b36bb..b2ecce9e2c 100644 --- a/python/private/py_wheel.bzl +++ b/python/private/py_wheel.bzl @@ -357,3 +357,15 @@ tries to locate `.runfiles` directory which is not packaged in the wheel. _other_attrs, ), ) + +py_wheel = rule( + implementation = py_wheel_lib.implementation, + doc = """\ +Internal rule used by the [py_wheel macro](/docs/packaging.md#py_wheel). + +These intentionally have the same name to avoid sharp edges with Bazel macros. +For example, a `bazel query` for a user's `py_wheel` macro expands to `py_wheel` targets, +in the way they expect. +""", + attrs = py_wheel_lib.attrs, +) From fa3e2d5a6f7821657473e8c6452426242ce6c5ea Mon Sep 17 00:00:00 2001 From: Matt Mackay Date: Thu, 26 Jan 2023 10:51:52 -0500 Subject: [PATCH 134/234] fix: ensure 'patches' attr is included for the canonical representation of the toolchain (#1018) --- python/repositories.bzl | 1 + 1 file changed, 1 insertion(+) diff --git a/python/repositories.bzl b/python/repositories.bzl index d1fba51f83..7589640332 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -323,6 +323,7 @@ py_runtime_pair( "distutils_content": rctx.attr.distutils_content, "ignore_root_user_error": rctx.attr.ignore_root_user_error, "name": rctx.attr.name, + "patches": rctx.attr.patches, "platform": platform, "python_version": python_version, "release_filename": release_filename, From 68b021306f1cb8d1a3a0f54a0187c2b3824d9756 Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Thu, 26 Jan 2023 15:14:05 -0800 Subject: [PATCH 135/234] feat: produce publishable distribution archives (#1019) * feat: produce publishable distribution archives Fixes #741 * fix: give unique names to dist/ folders by default --- .github/workflows/release.yml | 4 +-- docs/packaging.md | 28 ++++++++++++++++++- python/packaging.bzl | 52 +++++++++++++++++++++++++++++------ python/private/py_wheel.bzl | 22 +++++++++++---- python/runfiles/BUILD.bazel | 1 + 5 files changed, 90 insertions(+), 17 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5906289e66..9fb1705009 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,7 +15,7 @@ jobs: - name: Prepare workspace snippet run: .github/workflows/workspace_snippet.sh > release_notes.txt - name: Build wheel dist - run: bazel build --stamp --embed_label=${{ env.GITHUB_REF_NAME }} //python/runfiles:wheel + run: bazel build --stamp --embed_label=${{ env.GITHUB_REF_NAME }} //python/runfiles:wheel.dist - name: Publish runfiles package to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: @@ -23,7 +23,7 @@ jobs: # https://github.com/bazelbuild/rules_python/settings/secrets/actions # and currently uses a token which authenticates as https://pypi.org/user/alexeagle/ password: ${{ secrets.PYPI_API_TOKEN }} - packages_dir: bazel-bin/python/runfiles + packages_dir: bazel-bin/python/runfiles/dist - name: Release uses: softprops/action-gh-release@v1 with: diff --git a/docs/packaging.md b/docs/packaging.md index b750db64f5..a7a65ab7f8 100755 --- a/docs/packaging.md +++ b/docs/packaging.md @@ -26,6 +26,32 @@ This rule is intended to be used as data dependency to py_wheel rule. | packages | List of Python packages to include in the distribution. Sub-packages are automatically included. | List of strings | optional | [] | + + +## py_wheel_dist + +
+py_wheel_dist(name, out, wheel)
+
+ +Prepare a dist/ folder, following Python's packaging standard practice. + +See https://packaging.python.org/en/latest/tutorials/packaging-projects/#generating-distribution-archives +which recommends a dist/ folder containing the wheel file(s), source distributions, etc. + +This also has the advantage that stamping information is included in the wheel's filename. + + +**ATTRIBUTES** + + +| Name | Description | Type | Mandatory | Default | +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this target. | Name | required | | +| out | name of the resulting directory | String | required | | +| wheel | a [py_wheel rule](/docs/packaging.md#py_wheel_rule) | Label | optional | None | + + ## py_wheel_rule @@ -68,7 +94,7 @@ in the way they expect. | requires | List of requirements for this package. See the section on [Declaring required dependency](https://setuptools.readthedocs.io/en/latest/userguide/dependency_management.html#declaring-dependencies) for details and examples of the format of this argument. | List of strings | optional | [] | | stamp | Whether to encode build information into the wheel. Possible values:

- stamp = 1: Always stamp the build information into the wheel, even in [--nostamp](https://docs.bazel.build/versions/main/user-manual.html#flag--stamp) builds. This setting should be avoided, since it potentially kills remote caching for the target and any downstream actions that depend on it.

- stamp = 0: Always replace build information by constant values. This gives good build result caching.

- stamp = -1: Embedding of build information is controlled by the [--[no]stamp](https://docs.bazel.build/versions/main/user-manual.html#flag--stamp) flag.

Stamped targets are not rebuilt unless their dependencies change. | Integer | optional | -1 | | strip_path_prefixes | path prefixes to strip from files added to the generated package | List of strings | optional | [] | -| version | Version number of the package. Note that this attribute supports stamp format strings (eg. 1.2.3-{BUILD_TIMESTAMP}) as well as 'make variables' (e.g. 1.2.3-$(VERSION)). | String | required | | +| version | Version number of the package.

Note that this attribute supports stamp format strings as well as 'make variables'. For example: - version = "1.2.3-{BUILD_TIMESTAMP}" - version = "{BUILD_EMBED_LABEL}" - version = "$(VERSION)"

Note that Bazel's output filename cannot include the stamp information, as outputs must be known during the analysis phase and the stamp data is available only during the action execution.

The [py_wheel](/docs/packaging.md#py_wheel) macro produces a .dist-suffix target which creates a dist/ folder containing the wheel with the stamped name, suitable for publishing.

See [py_wheel_dist](/docs/packaging.md#py_wheel_dist) for more info. | String | required | | diff --git a/python/packaging.bzl b/python/packaging.bzl index 3b0b016321..92745792a5 100644 --- a/python/packaging.bzl +++ b/python/packaging.bzl @@ -31,6 +31,43 @@ This rule is intended to be used as data dependency to py_wheel rule. attrs = py_package_lib.attrs, ) +# Based on https://github.com/aspect-build/bazel-lib/tree/main/lib/private/copy_to_directory.bzl +# Avoiding a bazelbuild -> aspect-build dependency :( +def _py_wheel_dist_impl(ctx): + dir = ctx.actions.declare_directory(ctx.attr.out) + name_file = ctx.attr.wheel[PyWheelInfo].name_file + cmds = [ + "mkdir -p \"%s\"" % dir.path, + """cp "{}" "{}/$(cat "{}")" """.format(ctx.files.wheel[0].path, dir.path, name_file.path), + ] + ctx.actions.run_shell( + inputs = ctx.files.wheel + [name_file], + outputs = [dir], + command = "\n".join(cmds), + mnemonic = "CopyToDirectory", + progress_message = "Copying files to directory", + use_default_shell_env = True, + ) + return [ + DefaultInfo(files = depset([dir])), + ] + +py_wheel_dist = rule( + doc = """\ +Prepare a dist/ folder, following Python's packaging standard practice. + +See https://packaging.python.org/en/latest/tutorials/packaging-projects/#generating-distribution-archives +which recommends a dist/ folder containing the wheel file(s), source distributions, etc. + +This also has the advantage that stamping information is included in the wheel's filename. +""", + implementation = _py_wheel_dist_impl, + attrs = { + "out": attr.string(doc = "name of the resulting directory", mandatory = True), + "wheel": attr.label(doc = "a [py_wheel rule](/docs/packaging.md#py_wheel_rule)", providers = [PyWheelInfo]), + }, +) + def py_wheel(name, **kwargs): """Builds a Python Wheel. @@ -80,15 +117,12 @@ def py_wheel(name, **kwargs): name: A unique name for this target. **kwargs: other named parameters passed to the underlying [py_wheel rule](#py_wheel_rule) """ - _py_wheel(name = name, **kwargs) + py_wheel_dist( + name = "{}.dist".format(name), + wheel = name, + out = kwargs.pop("dist_folder", "{}_dist".format(name)), + ) - # TODO(alexeagle): produce an executable target like this: - # py_publish_wheel( - # name = "{}.publish".format(name), - # wheel = name, - # # Optional: override the label for a py_binary that runs twine - # # https://twine.readthedocs.io/en/stable/ - # twine_bin = "//path/to:twine", - # ) + _py_wheel(name = name, **kwargs) py_wheel_rule = _py_wheel diff --git a/python/private/py_wheel.bzl b/python/private/py_wheel.bzl index b2ecce9e2c..de9f65d808 100644 --- a/python/private/py_wheel.bzl +++ b/python/private/py_wheel.bzl @@ -73,11 +73,23 @@ Stamped targets are not rebuilt unless their dependencies change. ), "version": attr.string( mandatory = True, - doc = ( - "Version number of the package. Note that this attribute " + - "supports stamp format strings (eg. `1.2.3-{BUILD_TIMESTAMP}`) " + - "as well as 'make variables' (e.g. `1.2.3-$(VERSION)`)." - ), + doc = """\ +Version number of the package. + +Note that this attribute supports stamp format strings as well as 'make variables'. +For example: + - `version = "1.2.3-{BUILD_TIMESTAMP}"` + - `version = "{BUILD_EMBED_LABEL}"` + - `version = "$(VERSION)"` + +Note that Bazel's output filename cannot include the stamp information, as outputs must be known +during the analysis phase and the stamp data is available only during the action execution. + +The [`py_wheel`](/docs/packaging.md#py_wheel) macro produces a `.dist`-suffix target which creates a +`dist/` folder containing the wheel with the stamped name, suitable for publishing. + +See [`py_wheel_dist`](/docs/packaging.md#py_wheel_dist) for more info. +""", ), "_stamp_flag": attr.label( doc = "A setting used to determine whether or not the `--stamp` flag is enabled", diff --git a/python/runfiles/BUILD.bazel b/python/runfiles/BUILD.bazel index ea171ccd8e..ea327d7bd4 100644 --- a/python/runfiles/BUILD.bazel +++ b/python/runfiles/BUILD.bazel @@ -41,6 +41,7 @@ py_wheel( "License :: OSI Approved :: Apache Software License", ], description_file = "README.md", + dist_folder = "dist", distribution = "bazel_runfiles", homepage = "https://github.com/bazelbuild/rules_python", strip_path_prefixes = ["python"], From d196451b4f279c4463fcc59f73f858ed32ccd21d Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Thu, 26 Jan 2023 15:31:41 -0800 Subject: [PATCH 136/234] fix(release): use correct GH workflows syntax (#1020) See https://docs.github.com/en/actions/learn-github-actions/contexts#github-context --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9fb1705009..8a05b408c2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,7 +15,7 @@ jobs: - name: Prepare workspace snippet run: .github/workflows/workspace_snippet.sh > release_notes.txt - name: Build wheel dist - run: bazel build --stamp --embed_label=${{ env.GITHUB_REF_NAME }} //python/runfiles:wheel.dist + run: bazel build --stamp --embed_label=${{ github.ref_name }} //python/runfiles:wheel.dist - name: Publish runfiles package to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: From 7761231605d4354e76601d47ffdc771f40737b75 Mon Sep 17 00:00:00 2001 From: Lukas Date: Fri, 27 Jan 2023 01:24:37 +0100 Subject: [PATCH 137/234] feat: allow absolute urls in `tool_versions` (#973) feat: allow absolute urls in `tools_versions` --- python/versions.bzl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python/versions.bzl b/python/versions.bzl index 3c19c1890b..f843e47619 100644 --- a/python/versions.bzl +++ b/python/versions.bzl @@ -275,7 +275,10 @@ def get_release_info(platform, python_version, base_url = DEFAULT_RELEASE_BASE_U python_version = python_version, build = "shared-install_only" if (WINDOWS_NAME in platform) else "install_only", ) - url = "/".join([base_url, release_filename]) + if "://" in release_filename: # is absolute url? + url = release_filename + else: + url = "/".join([base_url, release_filename]) patches = tool_versions[python_version].get("patches", []) if type(patches) == type({}): From 3aefaed8762f6248f7b28ce1217371308ab19725 Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Thu, 26 Jan 2023 17:12:43 -0800 Subject: [PATCH 138/234] chore: revert publish wheel on releases (#1022) our 0.17 release is stuck on this step. Partially reverts #995 --- .github/workflows/release.yml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8a05b408c2..85c865e261 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,16 +14,6 @@ jobs: uses: actions/checkout@v2 - name: Prepare workspace snippet run: .github/workflows/workspace_snippet.sh > release_notes.txt - - name: Build wheel dist - run: bazel build --stamp --embed_label=${{ github.ref_name }} //python/runfiles:wheel.dist - - name: Publish runfiles package to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - # Note, the PYPI_API_TOKEN was added on - # https://github.com/bazelbuild/rules_python/settings/secrets/actions - # and currently uses a token which authenticates as https://pypi.org/user/alexeagle/ - password: ${{ secrets.PYPI_API_TOKEN }} - packages_dir: bazel-bin/python/runfiles/dist - name: Release uses: softprops/action-gh-release@v1 with: From 58c795801eaeb6b02976cfe08e2b542bd1f52ad9 Mon Sep 17 00:00:00 2001 From: Zhongpeng Lin Date: Thu, 26 Jan 2023 22:27:14 -0800 Subject: [PATCH 139/234] Using label as id for py targets (#1023) --- gazelle/go.mod | 1 - gazelle/go.sum | 2 -- gazelle/python/BUILD.bazel | 1 - gazelle/python/generate.go | 8 +++----- 4 files changed, 3 insertions(+), 9 deletions(-) diff --git a/gazelle/go.mod b/gazelle/go.mod index 322cf0db98..6d6f0332a0 100644 --- a/gazelle/go.mod +++ b/gazelle/go.mod @@ -9,7 +9,6 @@ require ( github.com/bmatcuk/doublestar v1.3.4 github.com/emirpasic/gods v1.18.1 github.com/ghodss/yaml v1.0.0 - github.com/google/uuid v1.3.0 gopkg.in/yaml.v2 v2.4.0 ) diff --git a/gazelle/go.sum b/gazelle/go.sum index 1a952616ba..ed8ceae5ec 100644 --- a/gazelle/go.sum +++ b/gazelle/go.sum @@ -38,8 +38,6 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= go.starlark.net v0.0.0-20210223155950-e043a3d3c984/go.mod h1:t3mmBBPzAVvK0L0n1drDmrQsJ8FoIx4INCqVMTr/Zo0= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= diff --git a/gazelle/python/BUILD.bazel b/gazelle/python/BUILD.bazel index a2bfb2730f..3b5ded2139 100644 --- a/gazelle/python/BUILD.bazel +++ b/gazelle/python/BUILD.bazel @@ -35,7 +35,6 @@ go_library( "@com_github_emirpasic_gods//lists/singlylinkedlist", "@com_github_emirpasic_gods//sets/treeset", "@com_github_emirpasic_gods//utils", - "@com_github_google_uuid//:uuid", "@io_bazel_rules_go//go/tools/bazel:go_default_library", ], ) diff --git a/gazelle/python/generate.go b/gazelle/python/generate.go index ac0ba6b8cf..a36b83b754 100644 --- a/gazelle/python/generate.go +++ b/gazelle/python/generate.go @@ -12,13 +12,11 @@ import ( "github.com/bazelbuild/bazel-gazelle/label" "github.com/bazelbuild/bazel-gazelle/language" "github.com/bazelbuild/bazel-gazelle/rule" + "github.com/bazelbuild/rules_python/gazelle/pythonconfig" "github.com/bmatcuk/doublestar" "github.com/emirpasic/gods/lists/singlylinkedlist" "github.com/emirpasic/gods/sets/treeset" godsutils "github.com/emirpasic/gods/utils" - "github.com/google/uuid" - - "github.com/bazelbuild/rules_python/gazelle/pythonconfig" ) const ( @@ -212,7 +210,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } pyLibrary = newTargetBuilder(pyLibraryKind, pyLibraryTargetName, pythonProjectRoot, args.Rel). - setUUID(uuid.Must(uuid.NewUUID()).String()). + setUUID(label.New("", args.Rel, pyLibraryTargetName).String()). addVisibility(visibility). addSrcs(pyLibraryFilenames). addModuleDependencies(deps). @@ -289,7 +287,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } conftestTarget := newTargetBuilder(pyLibraryKind, conftestTargetname, pythonProjectRoot, args.Rel). - setUUID(uuid.Must(uuid.NewUUID()).String()). + setUUID(label.New("", args.Rel, conftestTargetname).String()). addSrc(conftestFilename). addModuleDependencies(deps). addVisibility(visibility). From 82c8f0a084c35dafc381725c195597910cbab218 Mon Sep 17 00:00:00 2001 From: Zhongpeng Lin Date: Fri, 27 Jan 2023 20:45:54 -0800 Subject: [PATCH 140/234] Handling imports from sibling modules (#1027) --- gazelle/python/generate.go | 8 ++++---- gazelle/python/target.go | 10 +++++++--- .../python/testdata/subdir_sources/one/two/README.md | 2 ++ .../python/testdata/subdir_sources/one/two/__init__.py | 1 + .../testdata/with_third_party_requirements/BUILD.out | 5 +---- .../testdata/with_third_party_requirements/README.md | 4 +++- 6 files changed, 18 insertions(+), 12 deletions(-) create mode 100644 gazelle/python/testdata/subdir_sources/one/two/README.md diff --git a/gazelle/python/generate.go b/gazelle/python/generate.go index a36b83b754..a1587991e3 100644 --- a/gazelle/python/generate.go +++ b/gazelle/python/generate.go @@ -209,7 +209,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } } - pyLibrary = newTargetBuilder(pyLibraryKind, pyLibraryTargetName, pythonProjectRoot, args.Rel). + pyLibrary = newTargetBuilder(pyLibraryKind, pyLibraryTargetName, pythonProjectRoot, args.Rel, pyLibraryFilenames.Union(pyTestFilenames)). setUUID(label.New("", args.Rel, pyLibraryTargetName).String()). addVisibility(visibility). addSrcs(pyLibraryFilenames). @@ -246,7 +246,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } } - pyBinaryTarget := newTargetBuilder(pyBinaryKind, pyBinaryTargetName, pythonProjectRoot, args.Rel). + pyBinaryTarget := newTargetBuilder(pyBinaryKind, pyBinaryTargetName, pythonProjectRoot, args.Rel, pyLibraryFilenames.Union(pyTestFilenames)). setMain(pyBinaryEntrypointFilename). addVisibility(visibility). addSrc(pyBinaryEntrypointFilename). @@ -286,7 +286,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } } - conftestTarget := newTargetBuilder(pyLibraryKind, conftestTargetname, pythonProjectRoot, args.Rel). + conftestTarget := newTargetBuilder(pyLibraryKind, conftestTargetname, pythonProjectRoot, args.Rel, pyLibraryFilenames.Union(pyTestFilenames)). setUUID(label.New("", args.Rel, conftestTargetname).String()). addSrc(conftestFilename). addModuleDependencies(deps). @@ -322,7 +322,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } } } - return newTargetBuilder(pyTestKind, pyTestTargetName, pythonProjectRoot, args.Rel). + return newTargetBuilder(pyTestKind, pyTestTargetName, pythonProjectRoot, args.Rel, pyLibraryFilenames.Union(pyTestFilenames)). addSrcs(pyTestFilenames). addModuleDependencies(deps). generateImportsAttribute() diff --git a/gazelle/python/target.go b/gazelle/python/target.go index eef3aedd8d..84bbe29161 100644 --- a/gazelle/python/target.go +++ b/gazelle/python/target.go @@ -17,6 +17,7 @@ type targetBuilder struct { bzlPackage string uuid string srcs *treeset.Set + siblingSrcs *treeset.Set deps *treeset.Set resolvedDeps *treeset.Set visibility *treeset.Set @@ -26,13 +27,14 @@ type targetBuilder struct { } // newTargetBuilder constructs a new targetBuilder. -func newTargetBuilder(kind, name, pythonProjectRoot, bzlPackage string) *targetBuilder { +func newTargetBuilder(kind, name, pythonProjectRoot, bzlPackage string, siblingSrcs *treeset.Set) *targetBuilder { return &targetBuilder{ kind: kind, name: name, pythonProjectRoot: pythonProjectRoot, bzlPackage: bzlPackage, srcs: treeset.NewWith(godsutils.StringComparator), + siblingSrcs: siblingSrcs, deps: treeset.NewWith(moduleComparator), resolvedDeps: treeset.NewWith(godsutils.StringComparator), visibility: treeset.NewWith(godsutils.StringComparator), @@ -65,7 +67,9 @@ func (t *targetBuilder) addSrcs(srcs *treeset.Set) *targetBuilder { // addModuleDependency adds a single module dep to the target. func (t *targetBuilder) addModuleDependency(dep module) *targetBuilder { - t.deps.Add(dep) + if dep.Name+".py" == filepath.Base(dep.Filepath) || !t.siblingSrcs.Contains(dep.Name+".py") { + t.deps.Add(dep) + } return t } @@ -73,7 +77,7 @@ func (t *targetBuilder) addModuleDependency(dep module) *targetBuilder { func (t *targetBuilder) addModuleDependencies(deps *treeset.Set) *targetBuilder { it := deps.Iterator() for it.Next() { - t.deps.Add(it.Value().(module)) + t.addModuleDependency(it.Value().(module)) } return t } diff --git a/gazelle/python/testdata/subdir_sources/one/two/README.md b/gazelle/python/testdata/subdir_sources/one/two/README.md new file mode 100644 index 0000000000..ec4c15ddaa --- /dev/null +++ b/gazelle/python/testdata/subdir_sources/one/two/README.md @@ -0,0 +1,2 @@ +# Same package imports +This test case asserts that no `deps` is needed when a module imports another module in the same package \ No newline at end of file diff --git a/gazelle/python/testdata/subdir_sources/one/two/__init__.py b/gazelle/python/testdata/subdir_sources/one/two/__init__.py index f6c7d2a988..b6074a18d6 100644 --- a/gazelle/python/testdata/subdir_sources/one/two/__init__.py +++ b/gazelle/python/testdata/subdir_sources/one/two/__init__.py @@ -1,3 +1,4 @@ import foo.baz.baz as baz +import three _ = baz diff --git a/gazelle/python/testdata/with_third_party_requirements/BUILD.out b/gazelle/python/testdata/with_third_party_requirements/BUILD.out index a8261a9fae..2da7f2bd86 100644 --- a/gazelle/python/testdata/with_third_party_requirements/BUILD.out +++ b/gazelle/python/testdata/with_third_party_requirements/BUILD.out @@ -20,8 +20,5 @@ py_binary( srcs = ["__main__.py"], main = "__main__.py", visibility = ["//:__subpackages__"], - deps = [ - ":with_third_party_requirements", - "@gazelle_python_test_baz//:pkg", - ], + deps = [":with_third_party_requirements"], ) diff --git a/gazelle/python/testdata/with_third_party_requirements/README.md b/gazelle/python/testdata/with_third_party_requirements/README.md index b47101c8f8..a7ef7a3ca7 100644 --- a/gazelle/python/testdata/with_third_party_requirements/README.md +++ b/gazelle/python/testdata/with_third_party_requirements/README.md @@ -1,5 +1,7 @@ # With third-party requirements -This test case asserts that a `py_library` is generated with dependencies +This test case asserts that +* a `py_library` is generated with dependencies extracted from its sources and a `py_binary` is generated embeding the `py_library` and inherits its dependencies, without specifying the `deps` again. +* when a third-party library and a module in the same package having the same name, the one in the same package takes precedence. From 018e355734bbea1dc4905b997f2a8b45bf050583 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Sun, 29 Jan 2023 19:07:13 -0800 Subject: [PATCH 141/234] Add missing copyright headers (#1030) * Add missing copyright headers Done by running: `addlicense -v -c "The Bazel Authors. All rights reserved." .` With a few changes reverted because they're for generated files or test goldens. Fixes #916 --- .bazelci/presubmit.yml | 14 ++++++++++++++ .bcr/config.yml | 14 ++++++++++++++ .bcr/presubmit.yml | 14 ++++++++++++++ .github/workflows/release.yml | 14 ++++++++++++++ .github/workflows/stale.yml | 14 ++++++++++++++ .github/workflows/workspace_snippet.sh | 14 ++++++++++++++ .pre-commit-config.yaml | 14 ++++++++++++++ .../build_file_generation/gazelle_python.yaml | 14 ++++++++++++++ .../random_number_generator/__init__.py | 14 ++++++++++++++ examples/bzlmod/__init__.py | 14 ++++++++++++++ examples/bzlmod/__main__.py | 14 ++++++++++++++ .../bzlmod/other_module/other_module/pkg/lib.py | 14 ++++++++++++++ examples/bzlmod/runfiles/runfiles_test.py | 14 ++++++++++++++ examples/bzlmod/test.py | 14 ++++++++++++++ .../libs/my_lib/__init__.py | 14 ++++++++++++++ .../tests/cross_version_test.py | 14 ++++++++++++++ .../multi_python_versions/tests/my_lib_test.py | 14 ++++++++++++++ examples/multi_python_versions/tests/version.py | 14 ++++++++++++++ .../multi_python_versions/tests/version_test.py | 14 ++++++++++++++ .../multi_python_versions/tests/version_test.sh | 14 ++++++++++++++ examples/pip_install/main.py | 14 ++++++++++++++ examples/pip_install/pip_install_test.py | 14 ++++++++++++++ examples/pip_install/test.py | 14 ++++++++++++++ examples/pip_parse/main.py | 14 ++++++++++++++ examples/pip_parse/pip_parse_test.py | 14 ++++++++++++++ examples/pip_parse/test.py | 14 ++++++++++++++ .../data/copy_executable.py | 14 ++++++++++++++ .../pip_repository_annotations_test.py | 14 ++++++++++++++ examples/wheel/private/directory_writer.py | 14 ++++++++++++++ examples/wheel/private/wheel_utils.bzl | 14 ++++++++++++++ gazelle/def.bzl | 14 ++++++++++++++ gazelle/deps.bzl | 14 ++++++++++++++ gazelle/manifest/defs.bzl | 14 ++++++++++++++ gazelle/manifest/generate/generate.go | 14 ++++++++++++++ gazelle/manifest/hasher/main.go | 14 ++++++++++++++ gazelle/manifest/manifest.go | 14 ++++++++++++++ gazelle/manifest/manifest_test.go | 14 ++++++++++++++ gazelle/manifest/test/run.sh | 14 ++++++++++++++ gazelle/manifest/test/test.go | 14 ++++++++++++++ gazelle/modules_mapping/def.bzl | 14 ++++++++++++++ gazelle/modules_mapping/generator.py | 14 ++++++++++++++ gazelle/python/configure.go | 14 ++++++++++++++ gazelle/python/fix.go | 14 ++++++++++++++ gazelle/python/generate.go | 14 ++++++++++++++ gazelle/python/kinds.go | 14 ++++++++++++++ gazelle/python/language.go | 14 ++++++++++++++ gazelle/python/parse.py | 14 ++++++++++++++ gazelle/python/parser.go | 14 ++++++++++++++ gazelle/python/resolve.go | 14 ++++++++++++++ gazelle/python/std_modules.go | 14 ++++++++++++++ gazelle/python/std_modules.py | 14 ++++++++++++++ gazelle/python/target.go | 14 ++++++++++++++ .../dependency_resolution_order/__init__.py | 14 ++++++++++++++ .../dependency_resolution_order/bar/__init__.py | 14 ++++++++++++++ .../dependency_resolution_order/baz/__init__.py | 14 ++++++++++++++ .../dependency_resolution_order/foo/__init__.py | 14 ++++++++++++++ .../gazelle_python.yaml | 14 ++++++++++++++ .../somewhere/bar/__init__.py | 14 ++++++++++++++ .../dependency_resolution_order/test.yaml | 14 ++++++++++++++ .../__init__.py | 14 ++++++++++++++ .../test.yaml | 14 ++++++++++++++ .../testdata/dont_rename_target/__init__.py | 14 ++++++++++++++ .../python/testdata/dont_rename_target/test.yaml | 14 ++++++++++++++ .../__init__.py | 14 ++++++++++++++ .../gazelle_python.yaml | 14 ++++++++++++++ .../rest_framework.py | 14 ++++++++++++++ .../file_name_matches_import_statement/test.yaml | 14 ++++++++++++++ .../first_party_dependencies/one/__main__.py | 14 ++++++++++++++ .../first_party_dependencies/one/bar/__init__.py | 14 ++++++++++++++ .../one/bar/baz/__init__.py | 14 ++++++++++++++ .../first_party_dependencies/one/foo/__init__.py | 14 ++++++++++++++ .../testdata/first_party_dependencies/test.yaml | 14 ++++++++++++++ .../first_party_dependencies/three/__init__.py | 14 ++++++++++++++ .../first_party_dependencies/two/__init__.py | 14 ++++++++++++++ .../__main__.py | 14 ++++++++++++++ .../baz.py | 14 ++++++++++++++ .../foo.py | 14 ++++++++++++++ .../foo/__init__.py | 14 ++++++++++++++ .../foo/bar.py | 14 ++++++++++++++ .../one/__init__.py | 14 ++++++++++++++ .../one/two.py | 14 ++++++++++++++ .../test.yaml | 14 ++++++++++++++ .../package1/subpackage1/__init__.py | 14 ++++++++++++++ .../package1/subpackage1/module1.py | 14 ++++++++++++++ .../python/testdata/from_imports/foo/__init__.py | 14 ++++++++++++++ .../testdata/from_imports/foo/bar/__init__.py | 14 ++++++++++++++ .../python/testdata/from_imports/foo/bar/baz.py | 14 ++++++++++++++ .../testdata/from_imports/gazelle_python.yaml | 14 ++++++++++++++ .../from_imports/import_from_init_py/__init__.py | 14 ++++++++++++++ .../import_from_multiple/__init__.py | 14 ++++++++++++++ .../from_imports/import_nested_file/__init__.py | 14 ++++++++++++++ .../import_nested_module/__init__.py | 14 ++++++++++++++ .../from_imports/import_nested_var/__init__.py | 14 ++++++++++++++ .../import_top_level_var/__init__.py | 14 ++++++++++++++ .../testdata/from_imports/std_module/__init__.py | 14 ++++++++++++++ gazelle/python/testdata/from_imports/test.yaml | 14 ++++++++++++++ .../generated_test_entrypoint/__init__.py | 14 ++++++++++++++ .../testdata/generated_test_entrypoint/foo.py | 14 ++++++++++++++ .../testdata/generated_test_entrypoint/test.yaml | 14 ++++++++++++++ .../ignored_invalid_imported_module/__init__.py | 14 ++++++++++++++ .../gazelle_python.yaml | 14 ++++++++++++++ .../ignored_invalid_imported_module/test.yaml | 14 ++++++++++++++ .../testdata/invalid_annotation/__init__.py | 14 ++++++++++++++ .../python/testdata/invalid_annotation/test.yaml | 14 ++++++++++++++ .../testdata/invalid_imported_module/__init__.py | 14 ++++++++++++++ .../testdata/invalid_imported_module/test.yaml | 16 +++++++++++++++- .../testdata/monorepo/coarse_grained/__init__.py | 14 ++++++++++++++ .../coarse_grained/_boundary/__init__.py | 14 ++++++++++++++ .../monorepo/coarse_grained/bar/__init__.py | 14 ++++++++++++++ .../monorepo/coarse_grained/bar/baz/__init__.py | 14 ++++++++++++++ .../coarse_grained/bar/baz/first_excluded.py | 14 ++++++++++++++ .../monorepo/coarse_grained/bar/baz/hue.py | 14 ++++++++++++++ .../coarse_grained/bar/baz/second_excluded.py | 14 ++++++++++++++ .../monorepo/coarse_grained/foo/__init__.py | 14 ++++++++++++++ .../python/testdata/monorepo/gazelle_python.yaml | 14 ++++++++++++++ gazelle/python/testdata/monorepo/one/__main__.py | 14 ++++++++++++++ .../python/testdata/monorepo/one/bar/__init__.py | 14 ++++++++++++++ .../testdata/monorepo/one/bar/baz/__init__.py | 14 ++++++++++++++ .../python/testdata/monorepo/one/foo/__init__.py | 14 ++++++++++++++ .../testdata/monorepo/one/gazelle_python.yaml | 14 ++++++++++++++ gazelle/python/testdata/monorepo/test.yaml | 14 ++++++++++++++ .../python/testdata/monorepo/three/__init__.py | 14 ++++++++++++++ .../testdata/monorepo/three/gazelle_python.yaml | 14 ++++++++++++++ gazelle/python/testdata/monorepo/two/__init__.py | 14 ++++++++++++++ .../testdata/monorepo/two/gazelle_python.yaml | 14 ++++++++++++++ .../testdata/monorepo/wont_generate/__main__.py | 14 ++++++++++++++ .../monorepo/wont_generate/bar/__init__.py | 14 ++++++++++++++ .../monorepo/wont_generate/bar/baz/__init__.py | 14 ++++++++++++++ .../monorepo/wont_generate/foo/__init__.py | 14 ++++++++++++++ .../testdata/naming_convention/__init__.py | 14 ++++++++++++++ .../testdata/naming_convention/__main__.py | 14 ++++++++++++++ .../testdata/naming_convention/__test__.py | 14 ++++++++++++++ .../naming_convention/dont_rename/__init__.py | 14 ++++++++++++++ .../naming_convention/dont_rename/__main__.py | 14 ++++++++++++++ .../naming_convention/dont_rename/__test__.py | 14 ++++++++++++++ .../resolve_conflict/__init__.py | 14 ++++++++++++++ .../resolve_conflict/__main__.py | 14 ++++++++++++++ .../resolve_conflict/__test__.py | 14 ++++++++++++++ .../python/testdata/naming_convention/test.yaml | 14 ++++++++++++++ .../naming_convention_binary_fail/__main__.py | 14 ++++++++++++++ .../naming_convention_binary_fail/test.yaml | 14 ++++++++++++++ .../naming_convention_library_fail/__init__.py | 14 ++++++++++++++ .../naming_convention_library_fail/test.yaml | 14 ++++++++++++++ .../naming_convention_test_fail/__test__.py | 14 ++++++++++++++ .../naming_convention_test_fail/test.yaml | 14 ++++++++++++++ .../__init__.py | 14 ++++++++++++++ .../gazelle_python.yaml | 14 ++++++++++++++ .../test.yaml | 14 ++++++++++++++ .../python_ignore_files_directive/__init__.py | 14 ++++++++++++++ .../python_ignore_files_directive/bar/baz.py | 14 ++++++++++++++ .../bar/some_other.py | 14 ++++++++++++++ .../python_ignore_files_directive/foo/baz.py | 14 ++++++++++++++ .../python_ignore_files_directive/setup.py | 14 ++++++++++++++ .../python_ignore_files_directive/some_other.py | 14 ++++++++++++++ .../python_ignore_files_directive/test.yaml | 14 ++++++++++++++ .../python_target_with_test_in_name/__init__.py | 14 ++++++++++++++ .../gazelle_python.yaml | 14 ++++++++++++++ .../python_target_with_test_in_name/real_test.py | 14 ++++++++++++++ .../python_target_with_test_in_name/test.yaml | 14 ++++++++++++++ .../test_reality.py | 14 ++++++++++++++ .../python/testdata/relative_imports/__main__.py | 14 ++++++++++++++ .../relative_imports/package1/module1.py | 14 ++++++++++++++ .../relative_imports/package1/module2.py | 14 ++++++++++++++ .../relative_imports/package2/__init__.py | 14 ++++++++++++++ .../relative_imports/package2/module3.py | 14 ++++++++++++++ .../relative_imports/package2/module4.py | 14 ++++++++++++++ .../package2/subpackage1/module5.py | 14 ++++++++++++++ .../python/testdata/relative_imports/test.yaml | 14 ++++++++++++++ .../python/testdata/simple_binary/__main__.py | 14 ++++++++++++++ gazelle/python/testdata/simple_binary/test.yaml | 14 ++++++++++++++ .../simple_binary_with_library/__init__.py | 14 ++++++++++++++ .../simple_binary_with_library/__main__.py | 14 ++++++++++++++ .../testdata/simple_binary_with_library/bar.py | 14 ++++++++++++++ .../testdata/simple_binary_with_library/foo.py | 14 ++++++++++++++ .../simple_binary_with_library/test.yaml | 14 ++++++++++++++ .../python/testdata/simple_library/__init__.py | 14 ++++++++++++++ gazelle/python/testdata/simple_library/test.yaml | 14 ++++++++++++++ .../simple_library_without_init/foo/foo.py | 14 ++++++++++++++ .../simple_library_without_init/test.yaml | 14 ++++++++++++++ gazelle/python/testdata/simple_test/__init__.py | 14 ++++++++++++++ gazelle/python/testdata/simple_test/__test__.py | 14 ++++++++++++++ gazelle/python/testdata/simple_test/foo.py | 14 ++++++++++++++ gazelle/python/testdata/simple_test/test.yaml | 14 ++++++++++++++ .../simple_test_with_conftest/__init__.py | 14 ++++++++++++++ .../simple_test_with_conftest/__test__.py | 14 ++++++++++++++ .../simple_test_with_conftest/conftest.py | 14 ++++++++++++++ .../testdata/simple_test_with_conftest/foo.py | 14 ++++++++++++++ .../testdata/simple_test_with_conftest/test.yaml | 14 ++++++++++++++ .../python/testdata/subdir_sources/__main__.py | 14 ++++++++++++++ .../testdata/subdir_sources/foo/__init__.py | 14 ++++++++++++++ .../testdata/subdir_sources/foo/bar/bar.py | 14 ++++++++++++++ .../testdata/subdir_sources/foo/baz/baz.py | 14 ++++++++++++++ .../python/testdata/subdir_sources/foo/foo.py | 14 ++++++++++++++ .../foo/has_build/python/my_module.py | 14 ++++++++++++++ .../foo/has_build_bazel/python/my_module.py | 14 ++++++++++++++ .../subdir_sources/foo/has_init/__init__.py | 14 ++++++++++++++ .../foo/has_init/python/my_module.py | 14 ++++++++++++++ .../subdir_sources/foo/has_main/__main__.py | 14 ++++++++++++++ .../foo/has_main/python/my_module.py | 14 ++++++++++++++ .../subdir_sources/foo/has_test/__test__.py | 14 ++++++++++++++ .../foo/has_test/python/my_module.py | 14 ++++++++++++++ .../testdata/subdir_sources/one/__init__.py | 14 ++++++++++++++ .../testdata/subdir_sources/one/two/__init__.py | 14 ++++++++++++++ .../testdata/subdir_sources/one/two/three.py | 14 ++++++++++++++ gazelle/python/testdata/subdir_sources/test.yaml | 14 ++++++++++++++ .../with_nested_import_statements/__init__.py | 14 ++++++++++++++ .../gazelle_python.yaml | 14 ++++++++++++++ .../with_nested_import_statements/test.yaml | 14 ++++++++++++++ .../testdata/with_std_requirements/__init__.py | 14 ++++++++++++++ .../testdata/with_std_requirements/test.yaml | 14 ++++++++++++++ .../with_third_party_requirements/__init__.py | 14 ++++++++++++++ .../with_third_party_requirements/__main__.py | 14 ++++++++++++++ .../with_third_party_requirements/bar.py | 14 ++++++++++++++ .../with_third_party_requirements/foo.py | 14 ++++++++++++++ .../gazelle_python.yaml | 14 ++++++++++++++ .../with_third_party_requirements/test.yaml | 14 ++++++++++++++ .../__init__.py | 14 ++++++++++++++ .../__main__.py | 14 ++++++++++++++ .../bar.py | 14 ++++++++++++++ .../gazelle_python.yaml | 14 ++++++++++++++ .../test.yaml | 14 ++++++++++++++ gazelle/pythonconfig/pythonconfig.go | 14 ++++++++++++++ gazelle/pythonconfig/types.go | 14 ++++++++++++++ internal_deps.bzl | 14 ++++++++++++++ python/config_settings/config_settings.bzl | 14 ++++++++++++++ python/config_settings/transition.bzl | 14 ++++++++++++++ python/extensions.bzl | 14 ++++++++++++++ python/pip_install/pip_repository.bzl | 14 ++++++++++++++ python/pip_install/private/pip_install_utils.bzl | 14 ++++++++++++++ .../private/test/requirements_parser_tests.bzl | 14 ++++++++++++++ python/pip_install/repositories.bzl | 14 ++++++++++++++ python/pip_install/requirements.bzl | 14 ++++++++++++++ python/pip_install/requirements_parser.bzl | 14 ++++++++++++++ .../tools/dependency_resolver/__init__.py | 14 ++++++++++++++ .../dependency_resolver/dependency_resolver.py | 14 ++++++++++++++ python/pip_install/tools/lib/__init__.py | 14 ++++++++++++++ python/pip_install/tools/lib/annotation.py | 14 ++++++++++++++ python/pip_install/tools/lib/annotations_test.py | 14 ++++++++++++++ .../tools/lib/annotations_test_helpers.bzl | 14 ++++++++++++++ python/pip_install/tools/lib/arguments.py | 14 ++++++++++++++ python/pip_install/tools/lib/arguments_test.py | 14 ++++++++++++++ python/pip_install/tools/lib/bazel.py | 14 ++++++++++++++ .../tools/lock_file_generator/__init__.py | 14 ++++++++++++++ .../lock_file_generator/lock_file_generator.py | 14 ++++++++++++++ .../lock_file_generator_test.py | 14 ++++++++++++++ .../tools/wheel_installer/namespace_pkgs.py | 14 ++++++++++++++ .../tools/wheel_installer/namespace_pkgs_test.py | 14 ++++++++++++++ .../pip_install/tools/wheel_installer/wheel.py | 14 ++++++++++++++ .../tools/wheel_installer/wheel_installer.py | 14 ++++++++++++++ .../wheel_installer/wheel_installer_test.py | 14 ++++++++++++++ python/private/py_package.bzl | 14 ++++++++++++++ python/private/py_wheel.bzl | 14 ++++++++++++++ python/private/stamp.bzl | 14 ++++++++++++++ python/runfiles/__init__.py | 14 ++++++++++++++ .../pip_repository_entry_points_test.py | 14 ++++++++++++++ .../runfiles/runfiles_wheel_integration_test.sh | 14 ++++++++++++++ .../bazel_integration_test.bzl | 14 ++++++++++++++ tools/bazel_integration_test/test_runner.py | 14 ++++++++++++++ .../update_deleted_packages.sh | 14 ++++++++++++++ 259 files changed, 3627 insertions(+), 1 deletion(-) diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 085a873001..95fdea6985 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- buildifier: version: latest diff --git a/.bcr/config.yml b/.bcr/config.yml index ba611eb33b..024e524293 100644 --- a/.bcr/config.yml +++ b/.bcr/config.yml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + fixedReleaser: login: f0rmiga email: thulio@aspect.dev diff --git a/.bcr/presubmit.yml b/.bcr/presubmit.yml index 90e3122aca..252df6b3d4 100644 --- a/.bcr/presubmit.yml +++ b/.bcr/presubmit.yml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + bcr_test_module: module_path: "examples/bzlmod" matrix: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 85c865e261..5b1cde014a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # Cut a release whenever a new tag is pushed to the repo. name: Release diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 816ce1da21..8d388e2f7a 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # See https://github.com/marketplace/actions/close-stale-issues name: Mark stale issues and pull requests diff --git a/.github/workflows/workspace_snippet.sh b/.github/workflows/workspace_snippet.sh index 843be7a2f4..bfc0d8b0e4 100755 --- a/.github/workflows/workspace_snippet.sh +++ b/.github/workflows/workspace_snippet.sh @@ -1,4 +1,18 @@ #!/usr/bin/env bash +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + set -o errexit -o nounset -o pipefail diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9836759a79..e4ae5d3e0a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # See CONTRIBUTING.md for instructions. # See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks diff --git a/examples/build_file_generation/gazelle_python.yaml b/examples/build_file_generation/gazelle_python.yaml index 847d1ecc55..9953ad3936 100644 --- a/examples/build_file_generation/gazelle_python.yaml +++ b/examples/build_file_generation/gazelle_python.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # GENERATED FILE - DO NOT EDIT! # # To update this file, run: diff --git a/examples/build_file_generation/random_number_generator/__init__.py b/examples/build_file_generation/random_number_generator/__init__.py index e69de29bb2..bbdfb4c588 100644 --- a/examples/build_file_generation/random_number_generator/__init__.py +++ b/examples/build_file_generation/random_number_generator/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + diff --git a/examples/bzlmod/__init__.py b/examples/bzlmod/__init__.py index 955eb5af15..646c6e890f 100644 --- a/examples/bzlmod/__init__.py +++ b/examples/bzlmod/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from tabulate import tabulate diff --git a/examples/bzlmod/__main__.py b/examples/bzlmod/__main__.py index 8b4cb130b8..b173bd6f57 100644 --- a/examples/bzlmod/__main__.py +++ b/examples/bzlmod/__main__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from __init__ import main if __name__ == "__main__": diff --git a/examples/bzlmod/other_module/other_module/pkg/lib.py b/examples/bzlmod/other_module/other_module/pkg/lib.py index 48f6b58b36..eaf65fb46a 100644 --- a/examples/bzlmod/other_module/other_module/pkg/lib.py +++ b/examples/bzlmod/other_module/other_module/pkg/lib.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from python.runfiles import runfiles diff --git a/examples/bzlmod/runfiles/runfiles_test.py b/examples/bzlmod/runfiles/runfiles_test.py index 3c3ae75a2c..e1ba14e569 100644 --- a/examples/bzlmod/runfiles/runfiles_test.py +++ b/examples/bzlmod/runfiles/runfiles_test.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os import unittest diff --git a/examples/bzlmod/test.py b/examples/bzlmod/test.py index f9f0a830cd..b6038a7d1b 100644 --- a/examples/bzlmod/test.py +++ b/examples/bzlmod/test.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import unittest from __init__ import main diff --git a/examples/multi_python_versions/libs/my_lib/__init__.py b/examples/multi_python_versions/libs/my_lib/__init__.py index 3f02b96905..33cfb414f5 100644 --- a/examples/multi_python_versions/libs/my_lib/__init__.py +++ b/examples/multi_python_versions/libs/my_lib/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import websockets diff --git a/examples/multi_python_versions/tests/cross_version_test.py b/examples/multi_python_versions/tests/cross_version_test.py index f933ed6ffa..437be2ed5a 100644 --- a/examples/multi_python_versions/tests/cross_version_test.py +++ b/examples/multi_python_versions/tests/cross_version_test.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os import subprocess import sys diff --git a/examples/multi_python_versions/tests/my_lib_test.py b/examples/multi_python_versions/tests/my_lib_test.py index 4fc7095cf1..e0a97dbf2b 100644 --- a/examples/multi_python_versions/tests/my_lib_test.py +++ b/examples/multi_python_versions/tests/my_lib_test.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os import sys diff --git a/examples/multi_python_versions/tests/version.py b/examples/multi_python_versions/tests/version.py index 1007a14d7e..2d293c1571 100644 --- a/examples/multi_python_versions/tests/version.py +++ b/examples/multi_python_versions/tests/version.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import sys print(f"{sys.version_info.major}.{sys.version_info.minor}") diff --git a/examples/multi_python_versions/tests/version_test.py b/examples/multi_python_versions/tests/version_test.py index 305773cf58..444f5e4321 100644 --- a/examples/multi_python_versions/tests/version_test.py +++ b/examples/multi_python_versions/tests/version_test.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os import sys diff --git a/examples/multi_python_versions/tests/version_test.sh b/examples/multi_python_versions/tests/version_test.sh index b8f510df31..3bedb95ef9 100755 --- a/examples/multi_python_versions/tests/version_test.sh +++ b/examples/multi_python_versions/tests/version_test.sh @@ -1,4 +1,18 @@ #!/usr/bin/env bash +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + set -o errexit -o nounset -o pipefail diff --git a/examples/pip_install/main.py b/examples/pip_install/main.py index b65ad0e5ea..1fb7249f76 100644 --- a/examples/pip_install/main.py +++ b/examples/pip_install/main.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import boto3 diff --git a/examples/pip_install/pip_install_test.py b/examples/pip_install/pip_install_test.py index 1746b5da63..3e1b085ed4 100644 --- a/examples/pip_install/pip_install_test.py +++ b/examples/pip_install/pip_install_test.py @@ -1,4 +1,18 @@ #!/usr/bin/env python3 +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os import subprocess diff --git a/examples/pip_install/test.py b/examples/pip_install/test.py index 0859a2831a..0f5b7c905e 100644 --- a/examples/pip_install/test.py +++ b/examples/pip_install/test.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import unittest import main diff --git a/examples/pip_parse/main.py b/examples/pip_parse/main.py index 79e1c1219b..80610f42a1 100644 --- a/examples/pip_parse/main.py +++ b/examples/pip_parse/main.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import requests diff --git a/examples/pip_parse/pip_parse_test.py b/examples/pip_parse/pip_parse_test.py index c623a47567..f319cb898f 100644 --- a/examples/pip_parse/pip_parse_test.py +++ b/examples/pip_parse/pip_parse_test.py @@ -1,4 +1,18 @@ #!/usr/bin/env python3 +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os import subprocess diff --git a/examples/pip_parse/test.py b/examples/pip_parse/test.py index e1f97f167b..2dc3046319 100644 --- a/examples/pip_parse/test.py +++ b/examples/pip_parse/test.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import unittest import main diff --git a/examples/pip_repository_annotations/data/copy_executable.py b/examples/pip_repository_annotations/data/copy_executable.py index 20c6651e5b..5cb1af7fdb 100755 --- a/examples/pip_repository_annotations/data/copy_executable.py +++ b/examples/pip_repository_annotations/data/copy_executable.py @@ -1,4 +1,18 @@ #!/usr/bin/env python +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + if __name__ == "__main__": print("Hello world from copied executable") diff --git a/examples/pip_repository_annotations/pip_repository_annotations_test.py b/examples/pip_repository_annotations/pip_repository_annotations_test.py index b49fd34b33..e41dd4f0f6 100644 --- a/examples/pip_repository_annotations/pip_repository_annotations_test.py +++ b/examples/pip_repository_annotations/pip_repository_annotations_test.py @@ -1,4 +1,18 @@ #!/usr/bin/env python3 +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os import platform diff --git a/examples/wheel/private/directory_writer.py b/examples/wheel/private/directory_writer.py index dd604c671e..7d9a93ed3f 100644 --- a/examples/wheel/private/directory_writer.py +++ b/examples/wheel/private/directory_writer.py @@ -1,4 +1,18 @@ #!/usr/bin/env python3 +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + """The action executable of the `@rules_python//examples/wheel/private:wheel_utils.bzl%directory_writer` rule.""" import argparse diff --git a/examples/wheel/private/wheel_utils.bzl b/examples/wheel/private/wheel_utils.bzl index 25ef9b4d8f..af4fa1958b 100644 --- a/examples/wheel/private/wheel_utils.bzl +++ b/examples/wheel/private/wheel_utils.bzl @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + """Helper rules for demonstrating `py_wheel` examples""" def _directory_writer_impl(ctx): diff --git a/gazelle/def.bzl b/gazelle/def.bzl index bb53c30276..80b11576e6 100644 --- a/gazelle/def.bzl +++ b/gazelle/def.bzl @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + """This module contains the Gazelle runtime dependencies for the Python extension. """ diff --git a/gazelle/deps.bzl b/gazelle/deps.bzl index 15150c9afb..9ecb0c3436 100644 --- a/gazelle/deps.bzl +++ b/gazelle/deps.bzl @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + "This file managed by `bazel run //:update_go_deps`" load("@bazel_gazelle//:deps.bzl", _go_repository = "go_repository") diff --git a/gazelle/manifest/defs.bzl b/gazelle/manifest/defs.bzl index 3bbcf99701..8540c0e310 100644 --- a/gazelle/manifest/defs.bzl +++ b/gazelle/manifest/defs.bzl @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + """This module provides the gazelle_python_manifest macro that contains targets for updating and testing the Gazelle manifest file. """ diff --git a/gazelle/manifest/generate/generate.go b/gazelle/manifest/generate/generate.go index 7c2e064d93..0f429f8345 100644 --- a/gazelle/manifest/generate/generate.go +++ b/gazelle/manifest/generate/generate.go @@ -1,3 +1,17 @@ +// Copyright 2023 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + /* generate.go is a program that generates the Gazelle YAML manifest. diff --git a/gazelle/manifest/hasher/main.go b/gazelle/manifest/hasher/main.go index 6e8833572b..61f8952904 100644 --- a/gazelle/manifest/hasher/main.go +++ b/gazelle/manifest/hasher/main.go @@ -1,3 +1,17 @@ +// Copyright 2023 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package main import ( diff --git a/gazelle/manifest/manifest.go b/gazelle/manifest/manifest.go index 5668d9ce88..bb4826435f 100644 --- a/gazelle/manifest/manifest.go +++ b/gazelle/manifest/manifest.go @@ -1,3 +1,17 @@ +// Copyright 2023 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package manifest import ( diff --git a/gazelle/manifest/manifest_test.go b/gazelle/manifest/manifest_test.go index d3873e3881..43c4099aa1 100644 --- a/gazelle/manifest/manifest_test.go +++ b/gazelle/manifest/manifest_test.go @@ -1,3 +1,17 @@ +// Copyright 2023 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package manifest_test import ( diff --git a/gazelle/manifest/test/run.sh b/gazelle/manifest/test/run.sh index 524e9b5dd5..95efef009d 100755 --- a/gazelle/manifest/test/run.sh +++ b/gazelle/manifest/test/run.sh @@ -1,4 +1,18 @@ #!/usr/bin/env bash +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # This file exists to allow passing the runfile paths to the Go program via # environment variables. diff --git a/gazelle/manifest/test/test.go b/gazelle/manifest/test/test.go index 207923c3ff..ae9fdfe0d6 100644 --- a/gazelle/manifest/test/test.go +++ b/gazelle/manifest/test/test.go @@ -1,3 +1,17 @@ +// Copyright 2023 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + /* test.go is a program that asserts the Gazelle YAML manifest is up-to-date in regards to the requirements.txt. diff --git a/gazelle/modules_mapping/def.bzl b/gazelle/modules_mapping/def.bzl index 8cffb31cbf..54fc8add80 100644 --- a/gazelle/modules_mapping/def.bzl +++ b/gazelle/modules_mapping/def.bzl @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + """Definitions for the modules_mapping.json generation. The modules_mapping.json file is a mapping from Python modules to the wheel diff --git a/gazelle/modules_mapping/generator.py b/gazelle/modules_mapping/generator.py index 51b81e7487..be57eac3bc 100644 --- a/gazelle/modules_mapping/generator.py +++ b/gazelle/modules_mapping/generator.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import argparse import json import pathlib diff --git a/gazelle/python/configure.go b/gazelle/python/configure.go index 8e71110d0a..901c226782 100644 --- a/gazelle/python/configure.go +++ b/gazelle/python/configure.go @@ -1,3 +1,17 @@ +// Copyright 2023 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package python import ( diff --git a/gazelle/python/fix.go b/gazelle/python/fix.go index c669f21d27..1ca42571ab 100644 --- a/gazelle/python/fix.go +++ b/gazelle/python/fix.go @@ -1,3 +1,17 @@ +// Copyright 2023 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package python import ( diff --git a/gazelle/python/generate.go b/gazelle/python/generate.go index a1587991e3..4ebb40f6bb 100644 --- a/gazelle/python/generate.go +++ b/gazelle/python/generate.go @@ -1,3 +1,17 @@ +// Copyright 2023 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package python import ( diff --git a/gazelle/python/kinds.go b/gazelle/python/kinds.go index fa0f4ed98a..0fdc6bc3e9 100644 --- a/gazelle/python/kinds.go +++ b/gazelle/python/kinds.go @@ -1,3 +1,17 @@ +// Copyright 2023 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package python import ( diff --git a/gazelle/python/language.go b/gazelle/python/language.go index 877ac6d065..56eb97b043 100644 --- a/gazelle/python/language.go +++ b/gazelle/python/language.go @@ -1,3 +1,17 @@ +// Copyright 2023 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package python import ( diff --git a/gazelle/python/parse.py b/gazelle/python/parse.py index b892229386..5cf0b89868 100644 --- a/gazelle/python/parse.py +++ b/gazelle/python/parse.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # parse.py is a long-living program that communicates over STDIN and STDOUT. # STDIN receives parse requests, one per line. It outputs the parsed modules and # comments from all the files from each request. diff --git a/gazelle/python/parser.go b/gazelle/python/parser.go index fdb34f76c1..3809a461cd 100644 --- a/gazelle/python/parser.go +++ b/gazelle/python/parser.go @@ -1,3 +1,17 @@ +// Copyright 2023 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package python import ( diff --git a/gazelle/python/resolve.go b/gazelle/python/resolve.go index 220876da60..607776aee3 100644 --- a/gazelle/python/resolve.go +++ b/gazelle/python/resolve.go @@ -1,3 +1,17 @@ +// Copyright 2023 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package python import ( diff --git a/gazelle/python/std_modules.go b/gazelle/python/std_modules.go index 5f4df63455..17bc5263ae 100644 --- a/gazelle/python/std_modules.go +++ b/gazelle/python/std_modules.go @@ -1,3 +1,17 @@ +// Copyright 2023 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package python import ( diff --git a/gazelle/python/std_modules.py b/gazelle/python/std_modules.py index 86a20774f0..779a325508 100644 --- a/gazelle/python/std_modules.py +++ b/gazelle/python/std_modules.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # std_modules.py is a long-living program that communicates over STDIN and # STDOUT. STDIN receives module names, one per line. For each module statement # it evaluates, it outputs true/false for whether the module is part of the diff --git a/gazelle/python/target.go b/gazelle/python/target.go index 84bbe29161..69711ce643 100644 --- a/gazelle/python/target.go +++ b/gazelle/python/target.go @@ -1,3 +1,17 @@ +// Copyright 2023 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package python import ( diff --git a/gazelle/python/testdata/dependency_resolution_order/__init__.py b/gazelle/python/testdata/dependency_resolution_order/__init__.py index f2a1c081ad..d9c6504deb 100644 --- a/gazelle/python/testdata/dependency_resolution_order/__init__.py +++ b/gazelle/python/testdata/dependency_resolution_order/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import sys import bar diff --git a/gazelle/python/testdata/dependency_resolution_order/bar/__init__.py b/gazelle/python/testdata/dependency_resolution_order/bar/__init__.py index 76c3313f0e..1c0275c070 100644 --- a/gazelle/python/testdata/dependency_resolution_order/bar/__init__.py +++ b/gazelle/python/testdata/dependency_resolution_order/bar/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os _ = os diff --git a/gazelle/python/testdata/dependency_resolution_order/baz/__init__.py b/gazelle/python/testdata/dependency_resolution_order/baz/__init__.py index 76c3313f0e..1c0275c070 100644 --- a/gazelle/python/testdata/dependency_resolution_order/baz/__init__.py +++ b/gazelle/python/testdata/dependency_resolution_order/baz/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os _ = os diff --git a/gazelle/python/testdata/dependency_resolution_order/foo/__init__.py b/gazelle/python/testdata/dependency_resolution_order/foo/__init__.py index 76c3313f0e..1c0275c070 100644 --- a/gazelle/python/testdata/dependency_resolution_order/foo/__init__.py +++ b/gazelle/python/testdata/dependency_resolution_order/foo/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os _ = os diff --git a/gazelle/python/testdata/dependency_resolution_order/gazelle_python.yaml b/gazelle/python/testdata/dependency_resolution_order/gazelle_python.yaml index 7e911bf29b..8615181c91 100644 --- a/gazelle/python/testdata/dependency_resolution_order/gazelle_python.yaml +++ b/gazelle/python/testdata/dependency_resolution_order/gazelle_python.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + manifest: modules_mapping: foo: some_foo diff --git a/gazelle/python/testdata/dependency_resolution_order/somewhere/bar/__init__.py b/gazelle/python/testdata/dependency_resolution_order/somewhere/bar/__init__.py index 76c3313f0e..1c0275c070 100644 --- a/gazelle/python/testdata/dependency_resolution_order/somewhere/bar/__init__.py +++ b/gazelle/python/testdata/dependency_resolution_order/somewhere/bar/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os _ = os diff --git a/gazelle/python/testdata/dependency_resolution_order/test.yaml b/gazelle/python/testdata/dependency_resolution_order/test.yaml index ed97d539c0..fcea77710f 100644 --- a/gazelle/python/testdata/dependency_resolution_order/test.yaml +++ b/gazelle/python/testdata/dependency_resolution_order/test.yaml @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- diff --git a/gazelle/python/testdata/disable_import_statements_validation/__init__.py b/gazelle/python/testdata/disable_import_statements_validation/__init__.py index 88eba74539..fde6e50c27 100644 --- a/gazelle/python/testdata/disable_import_statements_validation/__init__.py +++ b/gazelle/python/testdata/disable_import_statements_validation/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import abcdefg _ = abcdefg diff --git a/gazelle/python/testdata/disable_import_statements_validation/test.yaml b/gazelle/python/testdata/disable_import_statements_validation/test.yaml index 36dd656b39..2410223e59 100644 --- a/gazelle/python/testdata/disable_import_statements_validation/test.yaml +++ b/gazelle/python/testdata/disable_import_statements_validation/test.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- expect: exit_code: 0 diff --git a/gazelle/python/testdata/dont_rename_target/__init__.py b/gazelle/python/testdata/dont_rename_target/__init__.py index e69de29bb2..bbdfb4c588 100644 --- a/gazelle/python/testdata/dont_rename_target/__init__.py +++ b/gazelle/python/testdata/dont_rename_target/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + diff --git a/gazelle/python/testdata/dont_rename_target/test.yaml b/gazelle/python/testdata/dont_rename_target/test.yaml index ed97d539c0..fcea77710f 100644 --- a/gazelle/python/testdata/dont_rename_target/test.yaml +++ b/gazelle/python/testdata/dont_rename_target/test.yaml @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- diff --git a/gazelle/python/testdata/file_name_matches_import_statement/__init__.py b/gazelle/python/testdata/file_name_matches_import_statement/__init__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/file_name_matches_import_statement/__init__.py +++ b/gazelle/python/testdata/file_name_matches_import_statement/__init__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/file_name_matches_import_statement/gazelle_python.yaml b/gazelle/python/testdata/file_name_matches_import_statement/gazelle_python.yaml index 63e6966941..f50d3ae397 100644 --- a/gazelle/python/testdata/file_name_matches_import_statement/gazelle_python.yaml +++ b/gazelle/python/testdata/file_name_matches_import_statement/gazelle_python.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + manifest: modules_mapping: rest_framework: djangorestframework diff --git a/gazelle/python/testdata/file_name_matches_import_statement/rest_framework.py b/gazelle/python/testdata/file_name_matches_import_statement/rest_framework.py index 9bede69c55..43098d29e2 100644 --- a/gazelle/python/testdata/file_name_matches_import_statement/rest_framework.py +++ b/gazelle/python/testdata/file_name_matches_import_statement/rest_framework.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import rest_framework _ = rest_framework diff --git a/gazelle/python/testdata/file_name_matches_import_statement/test.yaml b/gazelle/python/testdata/file_name_matches_import_statement/test.yaml index ed97d539c0..fcea77710f 100644 --- a/gazelle/python/testdata/file_name_matches_import_statement/test.yaml +++ b/gazelle/python/testdata/file_name_matches_import_statement/test.yaml @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- diff --git a/gazelle/python/testdata/first_party_dependencies/one/__main__.py b/gazelle/python/testdata/first_party_dependencies/one/__main__.py index 2d241cc41e..efc7900d53 100644 --- a/gazelle/python/testdata/first_party_dependencies/one/__main__.py +++ b/gazelle/python/testdata/first_party_dependencies/one/__main__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os from bar import bar diff --git a/gazelle/python/testdata/first_party_dependencies/one/bar/__init__.py b/gazelle/python/testdata/first_party_dependencies/one/bar/__init__.py index e311ff122a..d4b5fb84f1 100644 --- a/gazelle/python/testdata/first_party_dependencies/one/bar/__init__.py +++ b/gazelle/python/testdata/first_party_dependencies/one/bar/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os diff --git a/gazelle/python/testdata/first_party_dependencies/one/bar/baz/__init__.py b/gazelle/python/testdata/first_party_dependencies/one/bar/baz/__init__.py index e74f519643..5be74a7d3e 100644 --- a/gazelle/python/testdata/first_party_dependencies/one/bar/baz/__init__.py +++ b/gazelle/python/testdata/first_party_dependencies/one/bar/baz/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os diff --git a/gazelle/python/testdata/first_party_dependencies/one/foo/__init__.py b/gazelle/python/testdata/first_party_dependencies/one/foo/__init__.py index 8aeca3de74..978fb74567 100644 --- a/gazelle/python/testdata/first_party_dependencies/one/foo/__init__.py +++ b/gazelle/python/testdata/first_party_dependencies/one/foo/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os diff --git a/gazelle/python/testdata/first_party_dependencies/test.yaml b/gazelle/python/testdata/first_party_dependencies/test.yaml index ed97d539c0..fcea77710f 100644 --- a/gazelle/python/testdata/first_party_dependencies/test.yaml +++ b/gazelle/python/testdata/first_party_dependencies/test.yaml @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- diff --git a/gazelle/python/testdata/first_party_dependencies/three/__init__.py b/gazelle/python/testdata/first_party_dependencies/three/__init__.py index 41bec88fd3..9f7d123649 100644 --- a/gazelle/python/testdata/first_party_dependencies/three/__init__.py +++ b/gazelle/python/testdata/first_party_dependencies/three/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os from bar import bar diff --git a/gazelle/python/testdata/first_party_dependencies/two/__init__.py b/gazelle/python/testdata/first_party_dependencies/two/__init__.py index a0bb5c8715..88ff57bf1b 100644 --- a/gazelle/python/testdata/first_party_dependencies/two/__init__.py +++ b/gazelle/python/testdata/first_party_dependencies/two/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os from foo import foo diff --git a/gazelle/python/testdata/first_party_file_and_directory_modules/__main__.py b/gazelle/python/testdata/first_party_file_and_directory_modules/__main__.py index acf5f10a71..242448d348 100644 --- a/gazelle/python/testdata/first_party_file_and_directory_modules/__main__.py +++ b/gazelle/python/testdata/first_party_file_and_directory_modules/__main__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import foo from baz import baz as another_baz from foo.bar import baz diff --git a/gazelle/python/testdata/first_party_file_and_directory_modules/baz.py b/gazelle/python/testdata/first_party_file_and_directory_modules/baz.py index b161d6ab5e..e03a9ecb9d 100644 --- a/gazelle/python/testdata/first_party_file_and_directory_modules/baz.py +++ b/gazelle/python/testdata/first_party_file_and_directory_modules/baz.py @@ -1,2 +1,16 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + def baz(): return "baz from baz.py" diff --git a/gazelle/python/testdata/first_party_file_and_directory_modules/foo.py b/gazelle/python/testdata/first_party_file_and_directory_modules/foo.py index af3cbda705..04474d83a8 100644 --- a/gazelle/python/testdata/first_party_file_and_directory_modules/foo.py +++ b/gazelle/python/testdata/first_party_file_and_directory_modules/foo.py @@ -1,2 +1,16 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + def foo(): print("foo") diff --git a/gazelle/python/testdata/first_party_file_and_directory_modules/foo/__init__.py b/gazelle/python/testdata/first_party_file_and_directory_modules/foo/__init__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/first_party_file_and_directory_modules/foo/__init__.py +++ b/gazelle/python/testdata/first_party_file_and_directory_modules/foo/__init__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/first_party_file_and_directory_modules/foo/bar.py b/gazelle/python/testdata/first_party_file_and_directory_modules/foo/bar.py index d6524cca2a..dacf2d42b2 100644 --- a/gazelle/python/testdata/first_party_file_and_directory_modules/foo/bar.py +++ b/gazelle/python/testdata/first_party_file_and_directory_modules/foo/bar.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import one.two as two _ = two diff --git a/gazelle/python/testdata/first_party_file_and_directory_modules/one/__init__.py b/gazelle/python/testdata/first_party_file_and_directory_modules/one/__init__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/first_party_file_and_directory_modules/one/__init__.py +++ b/gazelle/python/testdata/first_party_file_and_directory_modules/one/__init__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/first_party_file_and_directory_modules/one/two.py b/gazelle/python/testdata/first_party_file_and_directory_modules/one/two.py index 0020c44f2f..94cca3d002 100644 --- a/gazelle/python/testdata/first_party_file_and_directory_modules/one/two.py +++ b/gazelle/python/testdata/first_party_file_and_directory_modules/one/two.py @@ -1,2 +1,16 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + def two(): return "two" diff --git a/gazelle/python/testdata/first_party_file_and_directory_modules/test.yaml b/gazelle/python/testdata/first_party_file_and_directory_modules/test.yaml index ed97d539c0..fcea77710f 100644 --- a/gazelle/python/testdata/first_party_file_and_directory_modules/test.yaml +++ b/gazelle/python/testdata/first_party_file_and_directory_modules/test.yaml @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- diff --git a/gazelle/python/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/__init__.py b/gazelle/python/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/__init__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/__init__.py +++ b/gazelle/python/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/__init__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/module1.py b/gazelle/python/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/module1.py index 0ff1c4256c..76c72273fa 100644 --- a/gazelle/python/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/module1.py +++ b/gazelle/python/testdata/first_party_file_and_directory_modules/undiscoverable/package1/subpackage1/module1.py @@ -1,2 +1,16 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + def find_me(): return "found" diff --git a/gazelle/python/testdata/from_imports/foo/__init__.py b/gazelle/python/testdata/from_imports/foo/__init__.py index 8c4ff6a255..d0f74a859a 100644 --- a/gazelle/python/testdata/from_imports/foo/__init__.py +++ b/gazelle/python/testdata/from_imports/foo/__init__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + foo = "foo" diff --git a/gazelle/python/testdata/from_imports/foo/bar/__init__.py b/gazelle/python/testdata/from_imports/foo/bar/__init__.py index 2e96e096cc..240f382ac6 100644 --- a/gazelle/python/testdata/from_imports/foo/bar/__init__.py +++ b/gazelle/python/testdata/from_imports/foo/bar/__init__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + bar = "bar" diff --git a/gazelle/python/testdata/from_imports/foo/bar/baz.py b/gazelle/python/testdata/from_imports/foo/bar/baz.py index a15f053fe4..9aeae611db 100644 --- a/gazelle/python/testdata/from_imports/foo/bar/baz.py +++ b/gazelle/python/testdata/from_imports/foo/bar/baz.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + baz = "baz" diff --git a/gazelle/python/testdata/from_imports/gazelle_python.yaml b/gazelle/python/testdata/from_imports/gazelle_python.yaml index 5f7922f40f..132854e842 100644 --- a/gazelle/python/testdata/from_imports/gazelle_python.yaml +++ b/gazelle/python/testdata/from_imports/gazelle_python.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + manifest: modules_mapping: boto3: rootboto3 diff --git a/gazelle/python/testdata/from_imports/import_from_init_py/__init__.py b/gazelle/python/testdata/from_imports/import_from_init_py/__init__.py index 350a327d20..bd6d8a550f 100644 --- a/gazelle/python/testdata/from_imports/import_from_init_py/__init__.py +++ b/gazelle/python/testdata/from_imports/import_from_init_py/__init__.py @@ -1,2 +1,16 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # bar is a variable inside foo/bar/__init__.py from foo.bar import bar diff --git a/gazelle/python/testdata/from_imports/import_from_multiple/__init__.py b/gazelle/python/testdata/from_imports/import_from_multiple/__init__.py index 864059b428..05cd10460a 100644 --- a/gazelle/python/testdata/from_imports/import_from_multiple/__init__.py +++ b/gazelle/python/testdata/from_imports/import_from_multiple/__init__.py @@ -1,2 +1,16 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # Import multiple values from the same import. from foo.bar import bar, baz diff --git a/gazelle/python/testdata/from_imports/import_nested_file/__init__.py b/gazelle/python/testdata/from_imports/import_nested_file/__init__.py index d5e6b2592b..55a1621628 100644 --- a/gazelle/python/testdata/from_imports/import_nested_file/__init__.py +++ b/gazelle/python/testdata/from_imports/import_nested_file/__init__.py @@ -1,2 +1,16 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # baz.py is a file at foo/bar/baz.py from foo.bar import baz diff --git a/gazelle/python/testdata/from_imports/import_nested_module/__init__.py b/gazelle/python/testdata/from_imports/import_nested_module/__init__.py index 3b04f00fed..96fa0e5ecb 100644 --- a/gazelle/python/testdata/from_imports/import_nested_module/__init__.py +++ b/gazelle/python/testdata/from_imports/import_nested_module/__init__.py @@ -1,2 +1,16 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # bar is a module at foo/bar/__init__.py from foo import bar diff --git a/gazelle/python/testdata/from_imports/import_nested_var/__init__.py b/gazelle/python/testdata/from_imports/import_nested_var/__init__.py index de5069d540..d0f51c443c 100644 --- a/gazelle/python/testdata/from_imports/import_nested_var/__init__.py +++ b/gazelle/python/testdata/from_imports/import_nested_var/__init__.py @@ -1,2 +1,16 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # baz is a variable in foo/bar/baz.py from foo.bar.baz import baz diff --git a/gazelle/python/testdata/from_imports/import_top_level_var/__init__.py b/gazelle/python/testdata/from_imports/import_top_level_var/__init__.py index 532f11a889..71dd7c482f 100644 --- a/gazelle/python/testdata/from_imports/import_top_level_var/__init__.py +++ b/gazelle/python/testdata/from_imports/import_top_level_var/__init__.py @@ -1,2 +1,16 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # foo is a variable in foo/__init__.py from foo import foo diff --git a/gazelle/python/testdata/from_imports/std_module/__init__.py b/gazelle/python/testdata/from_imports/std_module/__init__.py index 7e6bc9dc02..5518cc0239 100644 --- a/gazelle/python/testdata/from_imports/std_module/__init__.py +++ b/gazelle/python/testdata/from_imports/std_module/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # Gazelle should recognize this from import # as the standard module __future__. from __future__ import print_function diff --git a/gazelle/python/testdata/from_imports/test.yaml b/gazelle/python/testdata/from_imports/test.yaml index ed97d539c0..fcea77710f 100644 --- a/gazelle/python/testdata/from_imports/test.yaml +++ b/gazelle/python/testdata/from_imports/test.yaml @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- diff --git a/gazelle/python/testdata/generated_test_entrypoint/__init__.py b/gazelle/python/testdata/generated_test_entrypoint/__init__.py index 6a49193fe4..b274b0d921 100644 --- a/gazelle/python/testdata/generated_test_entrypoint/__init__.py +++ b/gazelle/python/testdata/generated_test_entrypoint/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from foo import foo _ = foo diff --git a/gazelle/python/testdata/generated_test_entrypoint/foo.py b/gazelle/python/testdata/generated_test_entrypoint/foo.py index cf68624419..932de45b74 100644 --- a/gazelle/python/testdata/generated_test_entrypoint/foo.py +++ b/gazelle/python/testdata/generated_test_entrypoint/foo.py @@ -1,2 +1,16 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + def foo(): return "foo" diff --git a/gazelle/python/testdata/generated_test_entrypoint/test.yaml b/gazelle/python/testdata/generated_test_entrypoint/test.yaml index ed97d539c0..fcea77710f 100644 --- a/gazelle/python/testdata/generated_test_entrypoint/test.yaml +++ b/gazelle/python/testdata/generated_test_entrypoint/test.yaml @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- diff --git a/gazelle/python/testdata/ignored_invalid_imported_module/__init__.py b/gazelle/python/testdata/ignored_invalid_imported_module/__init__.py index 4301453aec..a094ed0332 100644 --- a/gazelle/python/testdata/ignored_invalid_imported_module/__init__.py +++ b/gazelle/python/testdata/ignored_invalid_imported_module/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # gazelle:ignore abcdefg1,abcdefg2 # gazelle:ignore abcdefg3 diff --git a/gazelle/python/testdata/ignored_invalid_imported_module/gazelle_python.yaml b/gazelle/python/testdata/ignored_invalid_imported_module/gazelle_python.yaml index 54b3148810..4b12372b4e 100644 --- a/gazelle/python/testdata/ignored_invalid_imported_module/gazelle_python.yaml +++ b/gazelle/python/testdata/ignored_invalid_imported_module/gazelle_python.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + manifest: modules_mapping: foo: foo diff --git a/gazelle/python/testdata/ignored_invalid_imported_module/test.yaml b/gazelle/python/testdata/ignored_invalid_imported_module/test.yaml index 36dd656b39..2410223e59 100644 --- a/gazelle/python/testdata/ignored_invalid_imported_module/test.yaml +++ b/gazelle/python/testdata/ignored_invalid_imported_module/test.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- expect: exit_code: 0 diff --git a/gazelle/python/testdata/invalid_annotation/__init__.py b/gazelle/python/testdata/invalid_annotation/__init__.py index 9968c4af55..7aee8768ad 100644 --- a/gazelle/python/testdata/invalid_annotation/__init__.py +++ b/gazelle/python/testdata/invalid_annotation/__init__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # gazelle:ignore diff --git a/gazelle/python/testdata/invalid_annotation/test.yaml b/gazelle/python/testdata/invalid_annotation/test.yaml index 5e6170b626..19924b1288 100644 --- a/gazelle/python/testdata/invalid_annotation/test.yaml +++ b/gazelle/python/testdata/invalid_annotation/test.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- expect: exit_code: 1 diff --git a/gazelle/python/testdata/invalid_imported_module/__init__.py b/gazelle/python/testdata/invalid_imported_module/__init__.py index c100931cc4..dc6fb8519e 100644 --- a/gazelle/python/testdata/invalid_imported_module/__init__.py +++ b/gazelle/python/testdata/invalid_imported_module/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + try: import grpc diff --git a/gazelle/python/testdata/invalid_imported_module/test.yaml b/gazelle/python/testdata/invalid_imported_module/test.yaml index f12c36b505..6bcea39d2e 100644 --- a/gazelle/python/testdata/invalid_imported_module/test.yaml +++ b/gazelle/python/testdata/invalid_imported_module/test.yaml @@ -1,8 +1,22 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- expect: exit_code: 1 stderr: | - gazelle: ERROR: failed to validate dependencies for target "//:invalid_imported_module": "grpc" at line 2 from "__init__.py" is an invalid dependency: possible solutions: + gazelle: ERROR: failed to validate dependencies for target "//:invalid_imported_module": "grpc" at line 16 from "__init__.py" is an invalid dependency: possible solutions: 1. Add it as a dependency in the requirements.txt file. 2. Instruct Gazelle to resolve to a known dependency using the gazelle:resolve directive. 3. Ignore it with a comment '# gazelle:ignore grpc' in the Python file. diff --git a/gazelle/python/testdata/monorepo/coarse_grained/__init__.py b/gazelle/python/testdata/monorepo/coarse_grained/__init__.py index 2b5b044257..6e77327a42 100644 --- a/gazelle/python/testdata/monorepo/coarse_grained/__init__.py +++ b/gazelle/python/testdata/monorepo/coarse_grained/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os import boto3 diff --git a/gazelle/python/testdata/monorepo/coarse_grained/_boundary/__init__.py b/gazelle/python/testdata/monorepo/coarse_grained/_boundary/__init__.py index e69de29bb2..bbdfb4c588 100644 --- a/gazelle/python/testdata/monorepo/coarse_grained/_boundary/__init__.py +++ b/gazelle/python/testdata/monorepo/coarse_grained/_boundary/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + diff --git a/gazelle/python/testdata/monorepo/coarse_grained/bar/__init__.py b/gazelle/python/testdata/monorepo/coarse_grained/bar/__init__.py index f6ec21462a..499a0903cc 100644 --- a/gazelle/python/testdata/monorepo/coarse_grained/bar/__init__.py +++ b/gazelle/python/testdata/monorepo/coarse_grained/bar/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os import boto3 diff --git a/gazelle/python/testdata/monorepo/coarse_grained/bar/baz/__init__.py b/gazelle/python/testdata/monorepo/coarse_grained/bar/baz/__init__.py index e74f519643..5be74a7d3e 100644 --- a/gazelle/python/testdata/monorepo/coarse_grained/bar/baz/__init__.py +++ b/gazelle/python/testdata/monorepo/coarse_grained/bar/baz/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os diff --git a/gazelle/python/testdata/monorepo/coarse_grained/bar/baz/first_excluded.py b/gazelle/python/testdata/monorepo/coarse_grained/bar/baz/first_excluded.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/monorepo/coarse_grained/bar/baz/first_excluded.py +++ b/gazelle/python/testdata/monorepo/coarse_grained/bar/baz/first_excluded.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/monorepo/coarse_grained/bar/baz/hue.py b/gazelle/python/testdata/monorepo/coarse_grained/bar/baz/hue.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/monorepo/coarse_grained/bar/baz/hue.py +++ b/gazelle/python/testdata/monorepo/coarse_grained/bar/baz/hue.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/monorepo/coarse_grained/bar/baz/second_excluded.py b/gazelle/python/testdata/monorepo/coarse_grained/bar/baz/second_excluded.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/monorepo/coarse_grained/bar/baz/second_excluded.py +++ b/gazelle/python/testdata/monorepo/coarse_grained/bar/baz/second_excluded.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/monorepo/coarse_grained/foo/__init__.py b/gazelle/python/testdata/monorepo/coarse_grained/foo/__init__.py index 8aeca3de74..978fb74567 100644 --- a/gazelle/python/testdata/monorepo/coarse_grained/foo/__init__.py +++ b/gazelle/python/testdata/monorepo/coarse_grained/foo/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os diff --git a/gazelle/python/testdata/monorepo/gazelle_python.yaml b/gazelle/python/testdata/monorepo/gazelle_python.yaml index 5f7922f40f..132854e842 100644 --- a/gazelle/python/testdata/monorepo/gazelle_python.yaml +++ b/gazelle/python/testdata/monorepo/gazelle_python.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + manifest: modules_mapping: boto3: rootboto3 diff --git a/gazelle/python/testdata/monorepo/one/__main__.py b/gazelle/python/testdata/monorepo/one/__main__.py index f08f5e8009..7ef50cc97b 100644 --- a/gazelle/python/testdata/monorepo/one/__main__.py +++ b/gazelle/python/testdata/monorepo/one/__main__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os import boto3 diff --git a/gazelle/python/testdata/monorepo/one/bar/__init__.py b/gazelle/python/testdata/monorepo/one/bar/__init__.py index f6ec21462a..499a0903cc 100644 --- a/gazelle/python/testdata/monorepo/one/bar/__init__.py +++ b/gazelle/python/testdata/monorepo/one/bar/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os import boto3 diff --git a/gazelle/python/testdata/monorepo/one/bar/baz/__init__.py b/gazelle/python/testdata/monorepo/one/bar/baz/__init__.py index e74f519643..5be74a7d3e 100644 --- a/gazelle/python/testdata/monorepo/one/bar/baz/__init__.py +++ b/gazelle/python/testdata/monorepo/one/bar/baz/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os diff --git a/gazelle/python/testdata/monorepo/one/foo/__init__.py b/gazelle/python/testdata/monorepo/one/foo/__init__.py index 8aeca3de74..978fb74567 100644 --- a/gazelle/python/testdata/monorepo/one/foo/__init__.py +++ b/gazelle/python/testdata/monorepo/one/foo/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os diff --git a/gazelle/python/testdata/monorepo/one/gazelle_python.yaml b/gazelle/python/testdata/monorepo/one/gazelle_python.yaml index 67c53451b4..6b323b73d2 100644 --- a/gazelle/python/testdata/monorepo/one/gazelle_python.yaml +++ b/gazelle/python/testdata/monorepo/one/gazelle_python.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + manifest: modules_mapping: boto3: oneboto3 diff --git a/gazelle/python/testdata/monorepo/test.yaml b/gazelle/python/testdata/monorepo/test.yaml index ed97d539c0..fcea77710f 100644 --- a/gazelle/python/testdata/monorepo/test.yaml +++ b/gazelle/python/testdata/monorepo/test.yaml @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- diff --git a/gazelle/python/testdata/monorepo/three/__init__.py b/gazelle/python/testdata/monorepo/three/__init__.py index 6f12bd8033..b324b0c416 100644 --- a/gazelle/python/testdata/monorepo/three/__init__.py +++ b/gazelle/python/testdata/monorepo/three/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os import bar.baz.hue as hue diff --git a/gazelle/python/testdata/monorepo/three/gazelle_python.yaml b/gazelle/python/testdata/monorepo/three/gazelle_python.yaml index 860416933e..8280b38d16 100644 --- a/gazelle/python/testdata/monorepo/three/gazelle_python.yaml +++ b/gazelle/python/testdata/monorepo/three/gazelle_python.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + manifest: modules_mapping: boto3: threeboto3 diff --git a/gazelle/python/testdata/monorepo/two/__init__.py b/gazelle/python/testdata/monorepo/two/__init__.py index fb3e877fe5..d080c27de3 100644 --- a/gazelle/python/testdata/monorepo/two/__init__.py +++ b/gazelle/python/testdata/monorepo/two/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os import boto3 diff --git a/gazelle/python/testdata/monorepo/two/gazelle_python.yaml b/gazelle/python/testdata/monorepo/two/gazelle_python.yaml index 3bc5939e58..88c24d0147 100644 --- a/gazelle/python/testdata/monorepo/two/gazelle_python.yaml +++ b/gazelle/python/testdata/monorepo/two/gazelle_python.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + manifest: modules_mapping: boto3: twoboto3 diff --git a/gazelle/python/testdata/monorepo/wont_generate/__main__.py b/gazelle/python/testdata/monorepo/wont_generate/__main__.py index 2d241cc41e..efc7900d53 100644 --- a/gazelle/python/testdata/monorepo/wont_generate/__main__.py +++ b/gazelle/python/testdata/monorepo/wont_generate/__main__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os from bar import bar diff --git a/gazelle/python/testdata/monorepo/wont_generate/bar/__init__.py b/gazelle/python/testdata/monorepo/wont_generate/bar/__init__.py index e311ff122a..d4b5fb84f1 100644 --- a/gazelle/python/testdata/monorepo/wont_generate/bar/__init__.py +++ b/gazelle/python/testdata/monorepo/wont_generate/bar/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os diff --git a/gazelle/python/testdata/monorepo/wont_generate/bar/baz/__init__.py b/gazelle/python/testdata/monorepo/wont_generate/bar/baz/__init__.py index e74f519643..5be74a7d3e 100644 --- a/gazelle/python/testdata/monorepo/wont_generate/bar/baz/__init__.py +++ b/gazelle/python/testdata/monorepo/wont_generate/bar/baz/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os diff --git a/gazelle/python/testdata/monorepo/wont_generate/foo/__init__.py b/gazelle/python/testdata/monorepo/wont_generate/foo/__init__.py index 8aeca3de74..978fb74567 100644 --- a/gazelle/python/testdata/monorepo/wont_generate/foo/__init__.py +++ b/gazelle/python/testdata/monorepo/wont_generate/foo/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os diff --git a/gazelle/python/testdata/naming_convention/__init__.py b/gazelle/python/testdata/naming_convention/__init__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/naming_convention/__init__.py +++ b/gazelle/python/testdata/naming_convention/__init__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/naming_convention/__main__.py b/gazelle/python/testdata/naming_convention/__main__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/naming_convention/__main__.py +++ b/gazelle/python/testdata/naming_convention/__main__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/naming_convention/__test__.py b/gazelle/python/testdata/naming_convention/__test__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/naming_convention/__test__.py +++ b/gazelle/python/testdata/naming_convention/__test__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/naming_convention/dont_rename/__init__.py b/gazelle/python/testdata/naming_convention/dont_rename/__init__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/naming_convention/dont_rename/__init__.py +++ b/gazelle/python/testdata/naming_convention/dont_rename/__init__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/naming_convention/dont_rename/__main__.py b/gazelle/python/testdata/naming_convention/dont_rename/__main__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/naming_convention/dont_rename/__main__.py +++ b/gazelle/python/testdata/naming_convention/dont_rename/__main__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/naming_convention/dont_rename/__test__.py b/gazelle/python/testdata/naming_convention/dont_rename/__test__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/naming_convention/dont_rename/__test__.py +++ b/gazelle/python/testdata/naming_convention/dont_rename/__test__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/naming_convention/resolve_conflict/__init__.py b/gazelle/python/testdata/naming_convention/resolve_conflict/__init__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/naming_convention/resolve_conflict/__init__.py +++ b/gazelle/python/testdata/naming_convention/resolve_conflict/__init__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py b/gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py +++ b/gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py b/gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py +++ b/gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/naming_convention/test.yaml b/gazelle/python/testdata/naming_convention/test.yaml index ed97d539c0..fcea77710f 100644 --- a/gazelle/python/testdata/naming_convention/test.yaml +++ b/gazelle/python/testdata/naming_convention/test.yaml @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- diff --git a/gazelle/python/testdata/naming_convention_binary_fail/__main__.py b/gazelle/python/testdata/naming_convention_binary_fail/__main__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/naming_convention_binary_fail/__main__.py +++ b/gazelle/python/testdata/naming_convention_binary_fail/__main__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/naming_convention_binary_fail/test.yaml b/gazelle/python/testdata/naming_convention_binary_fail/test.yaml index bc30dd0858..41eabbfb11 100644 --- a/gazelle/python/testdata/naming_convention_binary_fail/test.yaml +++ b/gazelle/python/testdata/naming_convention_binary_fail/test.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- expect: exit_code: 1 diff --git a/gazelle/python/testdata/naming_convention_library_fail/__init__.py b/gazelle/python/testdata/naming_convention_library_fail/__init__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/naming_convention_library_fail/__init__.py +++ b/gazelle/python/testdata/naming_convention_library_fail/__init__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/naming_convention_library_fail/test.yaml b/gazelle/python/testdata/naming_convention_library_fail/test.yaml index 3743c324df..f48aa397f1 100644 --- a/gazelle/python/testdata/naming_convention_library_fail/test.yaml +++ b/gazelle/python/testdata/naming_convention_library_fail/test.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- expect: exit_code: 1 diff --git a/gazelle/python/testdata/naming_convention_test_fail/__test__.py b/gazelle/python/testdata/naming_convention_test_fail/__test__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/naming_convention_test_fail/__test__.py +++ b/gazelle/python/testdata/naming_convention_test_fail/__test__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/naming_convention_test_fail/test.yaml b/gazelle/python/testdata/naming_convention_test_fail/test.yaml index fc4e24e830..a8867e567e 100644 --- a/gazelle/python/testdata/naming_convention_test_fail/test.yaml +++ b/gazelle/python/testdata/naming_convention_test_fail/test.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- expect: exit_code: 1 diff --git a/gazelle/python/testdata/python_ignore_dependencies_directive/__init__.py b/gazelle/python/testdata/python_ignore_dependencies_directive/__init__.py index 79935a70c4..9e6e25a891 100644 --- a/gazelle/python/testdata/python_ignore_dependencies_directive/__init__.py +++ b/gazelle/python/testdata/python_ignore_dependencies_directive/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import bar import boto3 import foo diff --git a/gazelle/python/testdata/python_ignore_dependencies_directive/gazelle_python.yaml b/gazelle/python/testdata/python_ignore_dependencies_directive/gazelle_python.yaml index 7288b798e1..1bf594f9b4 100644 --- a/gazelle/python/testdata/python_ignore_dependencies_directive/gazelle_python.yaml +++ b/gazelle/python/testdata/python_ignore_dependencies_directive/gazelle_python.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + manifest: modules_mapping: boto3: boto3 diff --git a/gazelle/python/testdata/python_ignore_dependencies_directive/test.yaml b/gazelle/python/testdata/python_ignore_dependencies_directive/test.yaml index ed97d539c0..fcea77710f 100644 --- a/gazelle/python/testdata/python_ignore_dependencies_directive/test.yaml +++ b/gazelle/python/testdata/python_ignore_dependencies_directive/test.yaml @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- diff --git a/gazelle/python/testdata/python_ignore_files_directive/__init__.py b/gazelle/python/testdata/python_ignore_files_directive/__init__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/python_ignore_files_directive/__init__.py +++ b/gazelle/python/testdata/python_ignore_files_directive/__init__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/python_ignore_files_directive/bar/baz.py b/gazelle/python/testdata/python_ignore_files_directive/bar/baz.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/python_ignore_files_directive/bar/baz.py +++ b/gazelle/python/testdata/python_ignore_files_directive/bar/baz.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/python_ignore_files_directive/bar/some_other.py b/gazelle/python/testdata/python_ignore_files_directive/bar/some_other.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/python_ignore_files_directive/bar/some_other.py +++ b/gazelle/python/testdata/python_ignore_files_directive/bar/some_other.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/python_ignore_files_directive/foo/baz.py b/gazelle/python/testdata/python_ignore_files_directive/foo/baz.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/python_ignore_files_directive/foo/baz.py +++ b/gazelle/python/testdata/python_ignore_files_directive/foo/baz.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/python_ignore_files_directive/setup.py b/gazelle/python/testdata/python_ignore_files_directive/setup.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/python_ignore_files_directive/setup.py +++ b/gazelle/python/testdata/python_ignore_files_directive/setup.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/python_ignore_files_directive/some_other.py b/gazelle/python/testdata/python_ignore_files_directive/some_other.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/python_ignore_files_directive/some_other.py +++ b/gazelle/python/testdata/python_ignore_files_directive/some_other.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/python_ignore_files_directive/test.yaml b/gazelle/python/testdata/python_ignore_files_directive/test.yaml index ed97d539c0..fcea77710f 100644 --- a/gazelle/python/testdata/python_ignore_files_directive/test.yaml +++ b/gazelle/python/testdata/python_ignore_files_directive/test.yaml @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- diff --git a/gazelle/python/testdata/python_target_with_test_in_name/__init__.py b/gazelle/python/testdata/python_target_with_test_in_name/__init__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/python_target_with_test_in_name/__init__.py +++ b/gazelle/python/testdata/python_target_with_test_in_name/__init__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/python_target_with_test_in_name/gazelle_python.yaml b/gazelle/python/testdata/python_target_with_test_in_name/gazelle_python.yaml index 7288b798e1..1bf594f9b4 100644 --- a/gazelle/python/testdata/python_target_with_test_in_name/gazelle_python.yaml +++ b/gazelle/python/testdata/python_target_with_test_in_name/gazelle_python.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + manifest: modules_mapping: boto3: boto3 diff --git a/gazelle/python/testdata/python_target_with_test_in_name/real_test.py b/gazelle/python/testdata/python_target_with_test_in_name/real_test.py index 57c019daab..2f032112ef 100644 --- a/gazelle/python/testdata/python_target_with_test_in_name/real_test.py +++ b/gazelle/python/testdata/python_target_with_test_in_name/real_test.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import boto3 _ = boto3 diff --git a/gazelle/python/testdata/python_target_with_test_in_name/test.yaml b/gazelle/python/testdata/python_target_with_test_in_name/test.yaml index ed97d539c0..fcea77710f 100644 --- a/gazelle/python/testdata/python_target_with_test_in_name/test.yaml +++ b/gazelle/python/testdata/python_target_with_test_in_name/test.yaml @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- diff --git a/gazelle/python/testdata/python_target_with_test_in_name/test_reality.py b/gazelle/python/testdata/python_target_with_test_in_name/test_reality.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/python_target_with_test_in_name/test_reality.py +++ b/gazelle/python/testdata/python_target_with_test_in_name/test_reality.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/relative_imports/__main__.py b/gazelle/python/testdata/relative_imports/__main__.py index 4fb887a803..8d468bd643 100644 --- a/gazelle/python/testdata/relative_imports/__main__.py +++ b/gazelle/python/testdata/relative_imports/__main__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from package1.module1 import function1 from package2.module3 import function3 diff --git a/gazelle/python/testdata/relative_imports/package1/module1.py b/gazelle/python/testdata/relative_imports/package1/module1.py index 69cdde2633..28502f1f84 100644 --- a/gazelle/python/testdata/relative_imports/package1/module1.py +++ b/gazelle/python/testdata/relative_imports/package1/module1.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from .module2 import function2 diff --git a/gazelle/python/testdata/relative_imports/package1/module2.py b/gazelle/python/testdata/relative_imports/package1/module2.py index 1e731b4ec1..f8893b24e6 100644 --- a/gazelle/python/testdata/relative_imports/package1/module2.py +++ b/gazelle/python/testdata/relative_imports/package1/module2.py @@ -1,2 +1,16 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + def function2(): return "function2" diff --git a/gazelle/python/testdata/relative_imports/package2/__init__.py b/gazelle/python/testdata/relative_imports/package2/__init__.py index fd0384ba7e..0f5956835b 100644 --- a/gazelle/python/testdata/relative_imports/package2/__init__.py +++ b/gazelle/python/testdata/relative_imports/package2/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + class Class1: def method1(self): return "method1" diff --git a/gazelle/python/testdata/relative_imports/package2/module3.py b/gazelle/python/testdata/relative_imports/package2/module3.py index a5102dd8bd..74978a08d9 100644 --- a/gazelle/python/testdata/relative_imports/package2/module3.py +++ b/gazelle/python/testdata/relative_imports/package2/module3.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from . import Class1 from .subpackage1.module5 import function5 diff --git a/gazelle/python/testdata/relative_imports/package2/module4.py b/gazelle/python/testdata/relative_imports/package2/module4.py index 6e69699985..b7509dc7cf 100644 --- a/gazelle/python/testdata/relative_imports/package2/module4.py +++ b/gazelle/python/testdata/relative_imports/package2/module4.py @@ -1,2 +1,16 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + def function4(): return "function4" diff --git a/gazelle/python/testdata/relative_imports/package2/subpackage1/module5.py b/gazelle/python/testdata/relative_imports/package2/subpackage1/module5.py index ac1f7257df..ea0b981fd0 100644 --- a/gazelle/python/testdata/relative_imports/package2/subpackage1/module5.py +++ b/gazelle/python/testdata/relative_imports/package2/subpackage1/module5.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from ..module4 import function4 diff --git a/gazelle/python/testdata/relative_imports/test.yaml b/gazelle/python/testdata/relative_imports/test.yaml index ed97d539c0..fcea77710f 100644 --- a/gazelle/python/testdata/relative_imports/test.yaml +++ b/gazelle/python/testdata/relative_imports/test.yaml @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- diff --git a/gazelle/python/testdata/simple_binary/__main__.py b/gazelle/python/testdata/simple_binary/__main__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/simple_binary/__main__.py +++ b/gazelle/python/testdata/simple_binary/__main__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/simple_binary/test.yaml b/gazelle/python/testdata/simple_binary/test.yaml index ed97d539c0..fcea77710f 100644 --- a/gazelle/python/testdata/simple_binary/test.yaml +++ b/gazelle/python/testdata/simple_binary/test.yaml @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- diff --git a/gazelle/python/testdata/simple_binary_with_library/__init__.py b/gazelle/python/testdata/simple_binary_with_library/__init__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/simple_binary_with_library/__init__.py +++ b/gazelle/python/testdata/simple_binary_with_library/__init__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/simple_binary_with_library/__main__.py b/gazelle/python/testdata/simple_binary_with_library/__main__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/simple_binary_with_library/__main__.py +++ b/gazelle/python/testdata/simple_binary_with_library/__main__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/simple_binary_with_library/bar.py b/gazelle/python/testdata/simple_binary_with_library/bar.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/simple_binary_with_library/bar.py +++ b/gazelle/python/testdata/simple_binary_with_library/bar.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/simple_binary_with_library/foo.py b/gazelle/python/testdata/simple_binary_with_library/foo.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/simple_binary_with_library/foo.py +++ b/gazelle/python/testdata/simple_binary_with_library/foo.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/simple_binary_with_library/test.yaml b/gazelle/python/testdata/simple_binary_with_library/test.yaml index ed97d539c0..fcea77710f 100644 --- a/gazelle/python/testdata/simple_binary_with_library/test.yaml +++ b/gazelle/python/testdata/simple_binary_with_library/test.yaml @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- diff --git a/gazelle/python/testdata/simple_library/__init__.py b/gazelle/python/testdata/simple_library/__init__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/simple_library/__init__.py +++ b/gazelle/python/testdata/simple_library/__init__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/simple_library/test.yaml b/gazelle/python/testdata/simple_library/test.yaml index ed97d539c0..fcea77710f 100644 --- a/gazelle/python/testdata/simple_library/test.yaml +++ b/gazelle/python/testdata/simple_library/test.yaml @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- diff --git a/gazelle/python/testdata/simple_library_without_init/foo/foo.py b/gazelle/python/testdata/simple_library_without_init/foo/foo.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/simple_library_without_init/foo/foo.py +++ b/gazelle/python/testdata/simple_library_without_init/foo/foo.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/simple_library_without_init/test.yaml b/gazelle/python/testdata/simple_library_without_init/test.yaml index ed97d539c0..fcea77710f 100644 --- a/gazelle/python/testdata/simple_library_without_init/test.yaml +++ b/gazelle/python/testdata/simple_library_without_init/test.yaml @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- diff --git a/gazelle/python/testdata/simple_test/__init__.py b/gazelle/python/testdata/simple_test/__init__.py index 6a49193fe4..b274b0d921 100644 --- a/gazelle/python/testdata/simple_test/__init__.py +++ b/gazelle/python/testdata/simple_test/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from foo import foo _ = foo diff --git a/gazelle/python/testdata/simple_test/__test__.py b/gazelle/python/testdata/simple_test/__test__.py index d6085a41b4..2b180a5f53 100644 --- a/gazelle/python/testdata/simple_test/__test__.py +++ b/gazelle/python/testdata/simple_test/__test__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import unittest from __init__ import foo diff --git a/gazelle/python/testdata/simple_test/foo.py b/gazelle/python/testdata/simple_test/foo.py index cf68624419..932de45b74 100644 --- a/gazelle/python/testdata/simple_test/foo.py +++ b/gazelle/python/testdata/simple_test/foo.py @@ -1,2 +1,16 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + def foo(): return "foo" diff --git a/gazelle/python/testdata/simple_test/test.yaml b/gazelle/python/testdata/simple_test/test.yaml index 36dd656b39..2410223e59 100644 --- a/gazelle/python/testdata/simple_test/test.yaml +++ b/gazelle/python/testdata/simple_test/test.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- expect: exit_code: 0 diff --git a/gazelle/python/testdata/simple_test_with_conftest/__init__.py b/gazelle/python/testdata/simple_test_with_conftest/__init__.py index 6a49193fe4..b274b0d921 100644 --- a/gazelle/python/testdata/simple_test_with_conftest/__init__.py +++ b/gazelle/python/testdata/simple_test_with_conftest/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from foo import foo _ = foo diff --git a/gazelle/python/testdata/simple_test_with_conftest/__test__.py b/gazelle/python/testdata/simple_test_with_conftest/__test__.py index d6085a41b4..2b180a5f53 100644 --- a/gazelle/python/testdata/simple_test_with_conftest/__test__.py +++ b/gazelle/python/testdata/simple_test_with_conftest/__test__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import unittest from __init__ import foo diff --git a/gazelle/python/testdata/simple_test_with_conftest/conftest.py b/gazelle/python/testdata/simple_test_with_conftest/conftest.py index e69de29bb2..bbdfb4c588 100644 --- a/gazelle/python/testdata/simple_test_with_conftest/conftest.py +++ b/gazelle/python/testdata/simple_test_with_conftest/conftest.py @@ -0,0 +1,14 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + diff --git a/gazelle/python/testdata/simple_test_with_conftest/foo.py b/gazelle/python/testdata/simple_test_with_conftest/foo.py index cf68624419..932de45b74 100644 --- a/gazelle/python/testdata/simple_test_with_conftest/foo.py +++ b/gazelle/python/testdata/simple_test_with_conftest/foo.py @@ -1,2 +1,16 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + def foo(): return "foo" diff --git a/gazelle/python/testdata/simple_test_with_conftest/test.yaml b/gazelle/python/testdata/simple_test_with_conftest/test.yaml index 36dd656b39..2410223e59 100644 --- a/gazelle/python/testdata/simple_test_with_conftest/test.yaml +++ b/gazelle/python/testdata/simple_test_with_conftest/test.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- expect: exit_code: 0 diff --git a/gazelle/python/testdata/subdir_sources/__main__.py b/gazelle/python/testdata/subdir_sources/__main__.py index 3cc8834990..aacfc67bc5 100644 --- a/gazelle/python/testdata/subdir_sources/__main__.py +++ b/gazelle/python/testdata/subdir_sources/__main__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import foo.bar.bar as bar import foo.baz.baz as baz import one.two.three as three diff --git a/gazelle/python/testdata/subdir_sources/foo/__init__.py b/gazelle/python/testdata/subdir_sources/foo/__init__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/subdir_sources/foo/__init__.py +++ b/gazelle/python/testdata/subdir_sources/foo/__init__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/subdir_sources/foo/bar/bar.py b/gazelle/python/testdata/subdir_sources/foo/bar/bar.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/subdir_sources/foo/bar/bar.py +++ b/gazelle/python/testdata/subdir_sources/foo/bar/bar.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/subdir_sources/foo/baz/baz.py b/gazelle/python/testdata/subdir_sources/foo/baz/baz.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/subdir_sources/foo/baz/baz.py +++ b/gazelle/python/testdata/subdir_sources/foo/baz/baz.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/subdir_sources/foo/foo.py b/gazelle/python/testdata/subdir_sources/foo/foo.py index 6752f22f90..a98c73d4eb 100644 --- a/gazelle/python/testdata/subdir_sources/foo/foo.py +++ b/gazelle/python/testdata/subdir_sources/foo/foo.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import foo.bar.bar as bar _ = bar diff --git a/gazelle/python/testdata/subdir_sources/foo/has_build/python/my_module.py b/gazelle/python/testdata/subdir_sources/foo/has_build/python/my_module.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/subdir_sources/foo/has_build/python/my_module.py +++ b/gazelle/python/testdata/subdir_sources/foo/has_build/python/my_module.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/subdir_sources/foo/has_build_bazel/python/my_module.py b/gazelle/python/testdata/subdir_sources/foo/has_build_bazel/python/my_module.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/subdir_sources/foo/has_build_bazel/python/my_module.py +++ b/gazelle/python/testdata/subdir_sources/foo/has_build_bazel/python/my_module.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/subdir_sources/foo/has_init/__init__.py b/gazelle/python/testdata/subdir_sources/foo/has_init/__init__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/subdir_sources/foo/has_init/__init__.py +++ b/gazelle/python/testdata/subdir_sources/foo/has_init/__init__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/subdir_sources/foo/has_init/python/my_module.py b/gazelle/python/testdata/subdir_sources/foo/has_init/python/my_module.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/subdir_sources/foo/has_init/python/my_module.py +++ b/gazelle/python/testdata/subdir_sources/foo/has_init/python/my_module.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py b/gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py +++ b/gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/subdir_sources/foo/has_main/python/my_module.py b/gazelle/python/testdata/subdir_sources/foo/has_main/python/my_module.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/subdir_sources/foo/has_main/python/my_module.py +++ b/gazelle/python/testdata/subdir_sources/foo/has_main/python/my_module.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py b/gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py +++ b/gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/subdir_sources/foo/has_test/python/my_module.py b/gazelle/python/testdata/subdir_sources/foo/has_test/python/my_module.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/subdir_sources/foo/has_test/python/my_module.py +++ b/gazelle/python/testdata/subdir_sources/foo/has_test/python/my_module.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/subdir_sources/one/__init__.py b/gazelle/python/testdata/subdir_sources/one/__init__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/subdir_sources/one/__init__.py +++ b/gazelle/python/testdata/subdir_sources/one/__init__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/subdir_sources/one/two/__init__.py b/gazelle/python/testdata/subdir_sources/one/two/__init__.py index b6074a18d6..72357b3c46 100644 --- a/gazelle/python/testdata/subdir_sources/one/two/__init__.py +++ b/gazelle/python/testdata/subdir_sources/one/two/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import foo.baz.baz as baz import three diff --git a/gazelle/python/testdata/subdir_sources/one/two/three.py b/gazelle/python/testdata/subdir_sources/one/two/three.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/subdir_sources/one/two/three.py +++ b/gazelle/python/testdata/subdir_sources/one/two/three.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/subdir_sources/test.yaml b/gazelle/python/testdata/subdir_sources/test.yaml index ed97d539c0..fcea77710f 100644 --- a/gazelle/python/testdata/subdir_sources/test.yaml +++ b/gazelle/python/testdata/subdir_sources/test.yaml @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- diff --git a/gazelle/python/testdata/with_nested_import_statements/__init__.py b/gazelle/python/testdata/with_nested_import_statements/__init__.py index 6871953f88..733b51f974 100644 --- a/gazelle/python/testdata/with_nested_import_statements/__init__.py +++ b/gazelle/python/testdata/with_nested_import_statements/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os import sys diff --git a/gazelle/python/testdata/with_nested_import_statements/gazelle_python.yaml b/gazelle/python/testdata/with_nested_import_statements/gazelle_python.yaml index 7288b798e1..1bf594f9b4 100644 --- a/gazelle/python/testdata/with_nested_import_statements/gazelle_python.yaml +++ b/gazelle/python/testdata/with_nested_import_statements/gazelle_python.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + manifest: modules_mapping: boto3: boto3 diff --git a/gazelle/python/testdata/with_nested_import_statements/test.yaml b/gazelle/python/testdata/with_nested_import_statements/test.yaml index ed97d539c0..fcea77710f 100644 --- a/gazelle/python/testdata/with_nested_import_statements/test.yaml +++ b/gazelle/python/testdata/with_nested_import_statements/test.yaml @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- diff --git a/gazelle/python/testdata/with_std_requirements/__init__.py b/gazelle/python/testdata/with_std_requirements/__init__.py index 154689a5f4..e51d320213 100644 --- a/gazelle/python/testdata/with_std_requirements/__init__.py +++ b/gazelle/python/testdata/with_std_requirements/__init__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os import sys diff --git a/gazelle/python/testdata/with_std_requirements/test.yaml b/gazelle/python/testdata/with_std_requirements/test.yaml index ed97d539c0..fcea77710f 100644 --- a/gazelle/python/testdata/with_std_requirements/test.yaml +++ b/gazelle/python/testdata/with_std_requirements/test.yaml @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- diff --git a/gazelle/python/testdata/with_third_party_requirements/__init__.py b/gazelle/python/testdata/with_third_party_requirements/__init__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/with_third_party_requirements/__init__.py +++ b/gazelle/python/testdata/with_third_party_requirements/__init__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/with_third_party_requirements/__main__.py b/gazelle/python/testdata/with_third_party_requirements/__main__.py index fe551aa423..38e9a55fb5 100644 --- a/gazelle/python/testdata/with_third_party_requirements/__main__.py +++ b/gazelle/python/testdata/with_third_party_requirements/__main__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import bar import foo diff --git a/gazelle/python/testdata/with_third_party_requirements/bar.py b/gazelle/python/testdata/with_third_party_requirements/bar.py index 19ddd97a87..08f2e7c289 100644 --- a/gazelle/python/testdata/with_third_party_requirements/bar.py +++ b/gazelle/python/testdata/with_third_party_requirements/bar.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os import bar diff --git a/gazelle/python/testdata/with_third_party_requirements/foo.py b/gazelle/python/testdata/with_third_party_requirements/foo.py index 29a1f3b612..9bebbfcfc6 100644 --- a/gazelle/python/testdata/with_third_party_requirements/foo.py +++ b/gazelle/python/testdata/with_third_party_requirements/foo.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import sys import boto3 diff --git a/gazelle/python/testdata/with_third_party_requirements/gazelle_python.yaml b/gazelle/python/testdata/with_third_party_requirements/gazelle_python.yaml index 76bb8bfa7b..7753cfff2c 100644 --- a/gazelle/python/testdata/with_third_party_requirements/gazelle_python.yaml +++ b/gazelle/python/testdata/with_third_party_requirements/gazelle_python.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + manifest: modules_mapping: boto3: boto3 diff --git a/gazelle/python/testdata/with_third_party_requirements/test.yaml b/gazelle/python/testdata/with_third_party_requirements/test.yaml index ed97d539c0..fcea77710f 100644 --- a/gazelle/python/testdata/with_third_party_requirements/test.yaml +++ b/gazelle/python/testdata/with_third_party_requirements/test.yaml @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- diff --git a/gazelle/python/testdata/with_third_party_requirements_from_imports/__init__.py b/gazelle/python/testdata/with_third_party_requirements_from_imports/__init__.py index 6b58ff30a8..730755995d 100644 --- a/gazelle/python/testdata/with_third_party_requirements_from_imports/__init__.py +++ b/gazelle/python/testdata/with_third_party_requirements_from_imports/__init__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For test purposes only. diff --git a/gazelle/python/testdata/with_third_party_requirements_from_imports/__main__.py b/gazelle/python/testdata/with_third_party_requirements_from_imports/__main__.py index 9f529cb0df..2062a9b04a 100644 --- a/gazelle/python/testdata/with_third_party_requirements_from_imports/__main__.py +++ b/gazelle/python/testdata/with_third_party_requirements_from_imports/__main__.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from bar import main from google.cloud import aiplatform diff --git a/gazelle/python/testdata/with_third_party_requirements_from_imports/bar.py b/gazelle/python/testdata/with_third_party_requirements_from_imports/bar.py index 99a4b1ce95..6886b2b4e9 100644 --- a/gazelle/python/testdata/with_third_party_requirements_from_imports/bar.py +++ b/gazelle/python/testdata/with_third_party_requirements_from_imports/bar.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from google.cloud import aiplatform, storage diff --git a/gazelle/python/testdata/with_third_party_requirements_from_imports/gazelle_python.yaml b/gazelle/python/testdata/with_third_party_requirements_from_imports/gazelle_python.yaml index 0e4a6d2316..8b5694b2d7 100644 --- a/gazelle/python/testdata/with_third_party_requirements_from_imports/gazelle_python.yaml +++ b/gazelle/python/testdata/with_third_party_requirements_from_imports/gazelle_python.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + manifest: modules_mapping: cachetools: cachetools diff --git a/gazelle/python/testdata/with_third_party_requirements_from_imports/test.yaml b/gazelle/python/testdata/with_third_party_requirements_from_imports/test.yaml index ed97d539c0..fcea77710f 100644 --- a/gazelle/python/testdata/with_third_party_requirements_from_imports/test.yaml +++ b/gazelle/python/testdata/with_third_party_requirements_from_imports/test.yaml @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + --- diff --git a/gazelle/pythonconfig/pythonconfig.go b/gazelle/pythonconfig/pythonconfig.go index 64f6264323..a2fe7d51b2 100644 --- a/gazelle/pythonconfig/pythonconfig.go +++ b/gazelle/pythonconfig/pythonconfig.go @@ -1,3 +1,17 @@ +// Copyright 2023 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package pythonconfig import ( diff --git a/gazelle/pythonconfig/types.go b/gazelle/pythonconfig/types.go index bdb535bf6e..d83d35f015 100644 --- a/gazelle/pythonconfig/types.go +++ b/gazelle/pythonconfig/types.go @@ -1,3 +1,17 @@ +// Copyright 2023 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package pythonconfig import ( diff --git a/internal_deps.bzl b/internal_deps.bzl index 15a4f625fa..11c652a50d 100644 --- a/internal_deps.bzl +++ b/internal_deps.bzl @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + """Dependencies that are needed for rules_python tests and tools.""" load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file") diff --git a/python/config_settings/config_settings.bzl b/python/config_settings/config_settings.bzl index 977d023918..21e477e644 100644 --- a/python/config_settings/config_settings.bzl +++ b/python/config_settings/config_settings.bzl @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + """This module is used to construct the config settings in the BUILD file in this same package. """ diff --git a/python/config_settings/transition.bzl b/python/config_settings/transition.bzl index 35ba9a8ede..0a3d51c480 100644 --- a/python/config_settings/transition.bzl +++ b/python/config_settings/transition.bzl @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + """The transition module contains the rule definitions to wrap py_binary and py_test and transition them to the desired target platform. """ diff --git a/python/extensions.bzl b/python/extensions.bzl index 8b4fc0b7b4..0c9ad07c1a 100644 --- a/python/extensions.bzl +++ b/python/extensions.bzl @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + "Module extensions for use with bzlmod" load("@rules_python//python:pip.bzl", "pip_parse") diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl index 0685a88366..511da349c8 100644 --- a/python/pip_install/pip_repository.bzl +++ b/python/pip_install/pip_repository.bzl @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + "" load("//python:repositories.bzl", "get_interpreter_dirname", "is_standalone_interpreter") diff --git a/python/pip_install/private/pip_install_utils.bzl b/python/pip_install/private/pip_install_utils.bzl index aaf1600d6d..488583dcb8 100644 --- a/python/pip_install/private/pip_install_utils.bzl +++ b/python/pip_install/private/pip_install_utils.bzl @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + """Utilities for `rules_python` pip rules""" _SRCS_TEMPLATE = """\ diff --git a/python/pip_install/private/test/requirements_parser_tests.bzl b/python/pip_install/private/test/requirements_parser_tests.bzl index 23b67456ab..13c40c2956 100644 --- a/python/pip_install/private/test/requirements_parser_tests.bzl +++ b/python/pip_install/private/test/requirements_parser_tests.bzl @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + "Unit tests for yaml.bzl" load("@bazel_skylib//lib:unittest.bzl", "asserts", "unittest") diff --git a/python/pip_install/repositories.bzl b/python/pip_install/repositories.bzl index 12fe9403a6..e5567c8c58 100644 --- a/python/pip_install/repositories.bzl +++ b/python/pip_install/repositories.bzl @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + "" load("@bazel_skylib//lib:versions.bzl", "versions") diff --git a/python/pip_install/requirements.bzl b/python/pip_install/requirements.bzl index 043edd49c3..32ee063931 100644 --- a/python/pip_install/requirements.bzl +++ b/python/pip_install/requirements.bzl @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + """Rules to verify and update pip-compile locked requirements.txt""" load("//python:defs.bzl", _py_binary = "py_binary", _py_test = "py_test") diff --git a/python/pip_install/requirements_parser.bzl b/python/pip_install/requirements_parser.bzl index 6200382f4f..ac90b95328 100644 --- a/python/pip_install/requirements_parser.bzl +++ b/python/pip_install/requirements_parser.bzl @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + "Pip requirements parser for Starlark" _STATE = struct( diff --git a/python/pip_install/tools/dependency_resolver/__init__.py b/python/pip_install/tools/dependency_resolver/__init__.py index e69de29bb2..bbdfb4c588 100644 --- a/python/pip_install/tools/dependency_resolver/__init__.py +++ b/python/pip_install/tools/dependency_resolver/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + diff --git a/python/pip_install/tools/dependency_resolver/dependency_resolver.py b/python/pip_install/tools/dependency_resolver/dependency_resolver.py index 8d6cf1bd47..db84977a0d 100644 --- a/python/pip_install/tools/dependency_resolver/dependency_resolver.py +++ b/python/pip_install/tools/dependency_resolver/dependency_resolver.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + "Set defaults for the pip-compile command to run it under Bazel" import os diff --git a/python/pip_install/tools/lib/__init__.py b/python/pip_install/tools/lib/__init__.py index e69de29bb2..bbdfb4c588 100644 --- a/python/pip_install/tools/lib/__init__.py +++ b/python/pip_install/tools/lib/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + diff --git a/python/pip_install/tools/lib/annotation.py b/python/pip_install/tools/lib/annotation.py index 48aaa8026a..c98008005e 100644 --- a/python/pip_install/tools/lib/annotation.py +++ b/python/pip_install/tools/lib/annotation.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import json import logging from collections import OrderedDict diff --git a/python/pip_install/tools/lib/annotations_test.py b/python/pip_install/tools/lib/annotations_test.py index e181c6d93e..f7c360fbc9 100644 --- a/python/pip_install/tools/lib/annotations_test.py +++ b/python/pip_install/tools/lib/annotations_test.py @@ -1,4 +1,18 @@ #!/usr/bin/env python3 +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os import textwrap diff --git a/python/pip_install/tools/lib/annotations_test_helpers.bzl b/python/pip_install/tools/lib/annotations_test_helpers.bzl index cef9aebaed..4f56bb7022 100644 --- a/python/pip_install/tools/lib/annotations_test_helpers.bzl +++ b/python/pip_install/tools/lib/annotations_test_helpers.bzl @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + """Helper macros and rules for testing the `annotations` module of `tools`""" load("//python:pip.bzl", _package_annotation = "package_annotation") diff --git a/python/pip_install/tools/lib/arguments.py b/python/pip_install/tools/lib/arguments.py index 0612a94f50..974f03cbdd 100644 --- a/python/pip_install/tools/lib/arguments.py +++ b/python/pip_install/tools/lib/arguments.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import json from argparse import ArgumentParser diff --git a/python/pip_install/tools/lib/arguments_test.py b/python/pip_install/tools/lib/arguments_test.py index 8c546baee5..dfa96a890e 100644 --- a/python/pip_install/tools/lib/arguments_test.py +++ b/python/pip_install/tools/lib/arguments_test.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import argparse import json import unittest diff --git a/python/pip_install/tools/lib/bazel.py b/python/pip_install/tools/lib/bazel.py index c0a4aec422..5ee221f1bf 100644 --- a/python/pip_install/tools/lib/bazel.py +++ b/python/pip_install/tools/lib/bazel.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + WHEEL_FILE_LABEL = "whl" PY_LIBRARY_LABEL = "pkg" DATA_LABEL = "data" diff --git a/python/pip_install/tools/lock_file_generator/__init__.py b/python/pip_install/tools/lock_file_generator/__init__.py index e69de29bb2..bbdfb4c588 100644 --- a/python/pip_install/tools/lock_file_generator/__init__.py +++ b/python/pip_install/tools/lock_file_generator/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + diff --git a/python/pip_install/tools/lock_file_generator/lock_file_generator.py b/python/pip_install/tools/lock_file_generator/lock_file_generator.py index 18136bfbe5..4a64b3b8a7 100644 --- a/python/pip_install/tools/lock_file_generator/lock_file_generator.py +++ b/python/pip_install/tools/lock_file_generator/lock_file_generator.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import argparse import json import shlex diff --git a/python/pip_install/tools/lock_file_generator/lock_file_generator_test.py b/python/pip_install/tools/lock_file_generator/lock_file_generator_test.py index 0e36f6b0db..be244b1c07 100644 --- a/python/pip_install/tools/lock_file_generator/lock_file_generator_test.py +++ b/python/pip_install/tools/lock_file_generator/lock_file_generator_test.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import argparse import json import tempfile diff --git a/python/pip_install/tools/wheel_installer/namespace_pkgs.py b/python/pip_install/tools/wheel_installer/namespace_pkgs.py index 5ddd4e1f85..7d23c0e34b 100644 --- a/python/pip_install/tools/wheel_installer/namespace_pkgs.py +++ b/python/pip_install/tools/wheel_installer/namespace_pkgs.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + """Utility functions to discover python package types""" import os import textwrap diff --git a/python/pip_install/tools/wheel_installer/namespace_pkgs_test.py b/python/pip_install/tools/wheel_installer/namespace_pkgs_test.py index 5ac3390338..4aa0fea978 100644 --- a/python/pip_install/tools/wheel_installer/namespace_pkgs_test.py +++ b/python/pip_install/tools/wheel_installer/namespace_pkgs_test.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os import pathlib import shutil diff --git a/python/pip_install/tools/wheel_installer/wheel.py b/python/pip_install/tools/wheel_installer/wheel.py index f3d5f21200..84af04ca59 100644 --- a/python/pip_install/tools/wheel_installer/wheel.py +++ b/python/pip_install/tools/wheel_installer/wheel.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + """Utility class to inspect an extracted wheel directory""" import email from typing import Dict, Optional, Set, Tuple diff --git a/python/pip_install/tools/wheel_installer/wheel_installer.py b/python/pip_install/tools/wheel_installer/wheel_installer.py index 1f6eaf2450..77aa3a406c 100644 --- a/python/pip_install/tools/wheel_installer/wheel_installer.py +++ b/python/pip_install/tools/wheel_installer/wheel_installer.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import argparse import errno import glob diff --git a/python/pip_install/tools/wheel_installer/wheel_installer_test.py b/python/pip_install/tools/wheel_installer/wheel_installer_test.py index 2a6c29314a..8758b67a1c 100644 --- a/python/pip_install/tools/wheel_installer/wheel_installer_test.py +++ b/python/pip_install/tools/wheel_installer/wheel_installer_test.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os import shutil import tempfile diff --git a/python/private/py_package.bzl b/python/private/py_package.bzl index 25e5bb6389..08f4b0b318 100644 --- a/python/private/py_package.bzl +++ b/python/private/py_package.bzl @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + "Implementation of py_package rule" def _path_inside_wheel(input_file): diff --git a/python/private/py_wheel.bzl b/python/private/py_wheel.bzl index de9f65d808..77690edc65 100644 --- a/python/private/py_wheel.bzl +++ b/python/private/py_wheel.bzl @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + "Implementation of py_wheel rule" load("//python/private:stamp.bzl", "is_stamping_enabled") diff --git a/python/private/stamp.bzl b/python/private/stamp.bzl index 6d0e54977c..6bc0cd9d23 100644 --- a/python/private/stamp.bzl +++ b/python/private/stamp.bzl @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + """A small utility module dedicated to detecting whether or not the `--stamp` flag is enabled This module can be removed likely after the following PRs ar addressed: diff --git a/python/runfiles/__init__.py b/python/runfiles/__init__.py index eb42f79c8d..3dc4141749 100644 --- a/python/runfiles/__init__.py +++ b/python/runfiles/__init__.py @@ -1 +1,15 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from .runfiles import * diff --git a/tests/pip_repository_entry_points/pip_repository_entry_points_test.py b/tests/pip_repository_entry_points/pip_repository_entry_points_test.py index 9e49ce927d..0375153615 100644 --- a/tests/pip_repository_entry_points/pip_repository_entry_points_test.py +++ b/tests/pip_repository_entry_points/pip_repository_entry_points_test.py @@ -1,4 +1,18 @@ #!/usr/bin/env python3 +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import os import subprocess diff --git a/tests/runfiles/runfiles_wheel_integration_test.sh b/tests/runfiles/runfiles_wheel_integration_test.sh index 7faa027909..8e9c6082a5 100755 --- a/tests/runfiles/runfiles_wheel_integration_test.sh +++ b/tests/runfiles/runfiles_wheel_integration_test.sh @@ -1,4 +1,18 @@ #!/usr/bin/env bash +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # Manual test, run outside of Bazel, to check that our runfiles wheel should be functional # for users who install it from pypi. set -o errexit diff --git a/tools/bazel_integration_test/bazel_integration_test.bzl b/tools/bazel_integration_test/bazel_integration_test.bzl index 93059fb8da..66e0cbded1 100644 --- a/tools/bazel_integration_test/bazel_integration_test.bzl +++ b/tools/bazel_integration_test/bazel_integration_test.bzl @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + "Define a rule for running bazel test under Bazel" load("//:version.bzl", "SUPPORTED_BAZEL_VERSIONS", "bazel_version_to_binary_label") diff --git a/tools/bazel_integration_test/test_runner.py b/tools/bazel_integration_test/test_runner.py index 27abf1fa9e..03599fbd0e 100644 --- a/tools/bazel_integration_test/test_runner.py +++ b/tools/bazel_integration_test/test_runner.py @@ -1,3 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import json import os import platform diff --git a/tools/bazel_integration_test/update_deleted_packages.sh b/tools/bazel_integration_test/update_deleted_packages.sh index 8a215c6d4a..ce7b05ada7 100755 --- a/tools/bazel_integration_test/update_deleted_packages.sh +++ b/tools/bazel_integration_test/update_deleted_packages.sh @@ -1,4 +1,18 @@ #!/usr/bin/env bash +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + # For integration tests, we want to be able to glob() up the sources inside a nested package # See explanation in .bazelrc From 3fe06a18ff084613ce0fb70b58437f00fcb760a3 Mon Sep 17 00:00:00 2001 From: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Date: Mon, 30 Jan 2023 06:32:02 -0800 Subject: [PATCH 142/234] feat: allow extra dependencies to be passed to pip-compile (#1026) * feat: allow extra dependencies to be passed to pip-compile Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: update docs Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --------- Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- docs/pip.md | 7 ++++--- python/pip_install/requirements.bzl | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/pip.md b/docs/pip.md index 93bc7f0c15..2f5b92ebf1 100644 --- a/docs/pip.md +++ b/docs/pip.md @@ -29,9 +29,9 @@ whl_library_alias(name, name, extra_args, py_binary, py_test, requirements_in, requirements_txt, - requirements_darwin, requirements_linux, requirements_windows, visibility, - tags, kwargs) +compile_pip_requirements(name, extra_args, extra_deps, py_binary, py_test, requirements_in, + requirements_txt, requirements_darwin, requirements_linux, + requirements_windows, visibility, tags, kwargs) Generates targets for managing pip dependencies with pip-compile. @@ -53,6 +53,7 @@ It also generates two targets for running pip-compile: | :------------- | :------------- | :------------- | | name | base name for generated targets, typically "requirements". | none | | extra_args | passed to pip-compile. | [] | +| extra_deps | extra dependencies passed to pip-compile. | [] | | py_binary | the py_binary rule to be used. | <function py_binary> | | py_test | the py_test rule to be used. | <function py_test> | | requirements_in | file expressing desired dependencies. | None | diff --git a/python/pip_install/requirements.bzl b/python/pip_install/requirements.bzl index 32ee063931..35399da4ff 100644 --- a/python/pip_install/requirements.bzl +++ b/python/pip_install/requirements.bzl @@ -20,6 +20,7 @@ load("//python/pip_install:repositories.bzl", "requirement") def compile_pip_requirements( name, extra_args = [], + extra_deps = [], py_binary = _py_binary, py_test = _py_test, requirements_in = None, @@ -44,6 +45,7 @@ def compile_pip_requirements( Args: name: base name for generated targets, typically "requirements". extra_args: passed to pip-compile. + extra_deps: extra dependencies passed to pip-compile. py_binary: the py_binary rule to be used. py_test: the py_test rule to be used. requirements_in: file expressing desired dependencies. @@ -97,7 +99,7 @@ def compile_pip_requirements( requirement("importlib_metadata"), requirement("zipp"), requirement("more_itertools"), - ] + ] + extra_deps attrs = { "args": args, From 488a0372a4242140cb2e4bfa28e4a8e652866670 Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius Date: Tue, 31 Jan 2023 10:20:24 +0900 Subject: [PATCH 143/234] feat(coverage): Register coverage.py to hermetic toolchains (#977) This allows including the coverage package as part of the toolchain dependencies, which is mixed into a test's dependencies when `bazel coverage` is run (if coverage is not enabled, no extra dependency is added) For now, it's disabled by default because enabling it poses the risk of having two versions of coverage installed (one from the toolchain, one from the user's dependencies). The user can turn the coverage_tool setting by passing `register_coverage_tool=(True|False)` to `python_register_toolchains` or `python_register_multi_toolchains` call or specifying the `coverage_tool` label as described in the `versions.bzl` file. Use coverage.py v6.5.0 because the latest has `types.py` in the package directory, which imports from Python's stdlib `types` [1]. Somehow the Python interpreter is thinking that the `from types import FrameType` is referring to the currently interpreted file and everything breaks. I would have expected the package to use absolute imports and only attempt to import from `coverage.types` if we use `coverage.types` and not just a plain `types` import. NOTE: Coverage is only for non-windows platforms. Update tests to: - ensure that we can still use the toolchain as previously. - ensure that we are not downloading extra deps if they are not needed. * Also changes the projects bazelrc to use a remotejdk, which makes it easier for contributors because they don't have to locally install a jdk to get going. [1]: https://github.com/nedbat/coveragepy/blob/master/coverage/types.py [3]: https://github.com/bazelbuild/bazel/issues/15835 --- .bazelci/presubmit.yml | 22 ++ MODULE.bazel | 16 ++ examples/bzlmod/.bazelrc | 2 + examples/bzlmod/BUILD.bazel | 2 +- examples/bzlmod/MODULE.bazel | 1 + examples/bzlmod/__main__.py | 2 +- examples/bzlmod/{__init__.py => lib.py} | 0 examples/bzlmod/test.py | 2 +- examples/multi_python_versions/.bazelrc | 2 + examples/multi_python_versions/WORKSPACE | 5 + .../requirements/BUILD.bazel | 8 + .../requirements/requirements_lock_3_11.txt | 56 ++++ .../multi_python_versions/tests/BUILD.bazel | 21 ++ python/extensions.bzl | 15 +- python/private/coverage_deps.bzl | 179 ++++++++++++ python/repositories.bzl | 62 ++++- python/versions.bzl | 15 + tools/update_coverage_deps.py | 258 ++++++++++++++++++ 18 files changed, 663 insertions(+), 5 deletions(-) rename examples/bzlmod/{__init__.py => lib.py} (100%) create mode 100644 examples/multi_python_versions/requirements/requirements_lock_3_11.txt create mode 100644 python/private/coverage_deps.bzl create mode 100755 tools/update_coverage_deps.py diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 95fdea6985..a4003604d0 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -34,6 +34,20 @@ buildifier: .reusable_build_test_all: &reusable_build_test_all build_targets: ["..."] test_targets: ["..."] +.coverage_targets_example_bzlmod: &coverage_targets_example_bzlmod + coverage_targets: ["//:test"] +.coverage_targets_example_multi_python: &coverage_targets_example_multi_python + coverage_targets: + - //tests:my_lib_3_10_test + - //tests:my_lib_3_11_test + - //tests:my_lib_3_8_test + - //tests:my_lib_3_9_test + - //tests:my_lib_default_test + - //tests:version_3_10_test + - //tests:version_3_11_test + - //tests:version_3_8_test + - //tests:version_3_9_test + - //tests:version_default_test tasks: gazelle_extension: name: Test the Gazelle extension @@ -89,42 +103,50 @@ tasks: integration_test_bzlmod_ubuntu: <<: *reusable_build_test_all + <<: *coverage_targets_example_bzlmod name: bzlmod integration tests on Ubuntu working_directory: examples/bzlmod platform: ubuntu2004 integration_test_bzlmod_debian: <<: *reusable_build_test_all + <<: *coverage_targets_example_bzlmod name: bzlmod integration tests on Debian working_directory: examples/bzlmod platform: debian11 integration_test_bzlmod_macos: <<: *reusable_build_test_all + <<: *coverage_targets_example_bzlmod name: bzlmod integration tests on macOS working_directory: examples/bzlmod platform: macos integration_test_bzlmod_windows: <<: *reusable_build_test_all + # coverage is not supported on Windows name: bzlmod integration tests on Windows working_directory: examples/bzlmod platform: windows integration_test_multi_python_versions_ubuntu: <<: *reusable_build_test_all + <<: *coverage_targets_example_multi_python name: multi_python_versions integration tests on Ubuntu working_directory: examples/multi_python_versions platform: ubuntu2004 integration_test_multi_python_versions_debian: <<: *reusable_build_test_all + <<: *coverage_targets_example_multi_python name: multi_python_versions integration tests on Debian working_directory: examples/multi_python_versions platform: debian11 integration_test_multi_python_versions_macos: <<: *reusable_build_test_all + <<: *coverage_targets_example_multi_python name: multi_python_versions integration tests on macOS working_directory: examples/multi_python_versions platform: macos integration_test_multi_python_versions_windows: <<: *reusable_build_test_all + # coverage is not supported on Windows name: multi_python_versions integration tests on Windows working_directory: examples/multi_python_versions platform: windows diff --git a/MODULE.bazel b/MODULE.bazel index af5d2e079f..92da4020b9 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -29,4 +29,20 @@ use_repo( "pypi__tomli", "pypi__wheel", "pypi__zipp", + # coverage_deps managed by running ./tools/update_coverage_deps.py + "pypi__coverage_cp310_aarch64-apple-darwin", + "pypi__coverage_cp310_aarch64-unknown-linux-gnu", + "pypi__coverage_cp310_x86_64-apple-darwin", + "pypi__coverage_cp310_x86_64-unknown-linux-gnu", + "pypi__coverage_cp311_aarch64-unknown-linux-gnu", + "pypi__coverage_cp311_x86_64-apple-darwin", + "pypi__coverage_cp311_x86_64-unknown-linux-gnu", + "pypi__coverage_cp38_aarch64-apple-darwin", + "pypi__coverage_cp38_aarch64-unknown-linux-gnu", + "pypi__coverage_cp38_x86_64-apple-darwin", + "pypi__coverage_cp38_x86_64-unknown-linux-gnu", + "pypi__coverage_cp39_aarch64-apple-darwin", + "pypi__coverage_cp39_aarch64-unknown-linux-gnu", + "pypi__coverage_cp39_x86_64-apple-darwin", + "pypi__coverage_cp39_x86_64-unknown-linux-gnu", ) diff --git a/examples/bzlmod/.bazelrc b/examples/bzlmod/.bazelrc index b3a24e8605..b8c233f98c 100644 --- a/examples/bzlmod/.bazelrc +++ b/examples/bzlmod/.bazelrc @@ -1 +1,3 @@ common --experimental_enable_bzlmod + +coverage --java_runtime_version=remotejdk_11 diff --git a/examples/bzlmod/BUILD.bazel b/examples/bzlmod/BUILD.bazel index 2094567362..7b7566bd5a 100644 --- a/examples/bzlmod/BUILD.bazel +++ b/examples/bzlmod/BUILD.bazel @@ -12,7 +12,7 @@ compile_pip_requirements( py_library( name = "lib", - srcs = ["__init__.py"], + srcs = ["lib.py"], deps = [ requirement("pylint"), requirement("tabulate"), diff --git a/examples/bzlmod/MODULE.bazel b/examples/bzlmod/MODULE.bazel index 48fb4cb3fc..5f984c39df 100644 --- a/examples/bzlmod/MODULE.bazel +++ b/examples/bzlmod/MODULE.bazel @@ -13,6 +13,7 @@ local_path_override( python = use_extension("@rules_python//python:extensions.bzl", "python") python.toolchain( name = "python3_9", + configure_coverage_tool = True, python_version = "3.9", ) use_repo(python, "python3_9_toolchains") diff --git a/examples/bzlmod/__main__.py b/examples/bzlmod/__main__.py index b173bd6f57..099493b3c8 100644 --- a/examples/bzlmod/__main__.py +++ b/examples/bzlmod/__main__.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from __init__ import main +from lib import main if __name__ == "__main__": print(main([["A", 1], ["B", 2]])) diff --git a/examples/bzlmod/__init__.py b/examples/bzlmod/lib.py similarity index 100% rename from examples/bzlmod/__init__.py rename to examples/bzlmod/lib.py diff --git a/examples/bzlmod/test.py b/examples/bzlmod/test.py index b6038a7d1b..cdc1c89680 100644 --- a/examples/bzlmod/test.py +++ b/examples/bzlmod/test.py @@ -14,7 +14,7 @@ import unittest -from __init__ import main +from lib import main class ExampleTest(unittest.TestCase): diff --git a/examples/multi_python_versions/.bazelrc b/examples/multi_python_versions/.bazelrc index f23315a7a1..3fd6365ba9 100644 --- a/examples/multi_python_versions/.bazelrc +++ b/examples/multi_python_versions/.bazelrc @@ -3,3 +3,5 @@ test --test_output=errors # Windows requires these for multi-python support: build --enable_runfiles startup --windows_enable_symlinks + +coverage --java_runtime_version=remotejdk_11 diff --git a/examples/multi_python_versions/WORKSPACE b/examples/multi_python_versions/WORKSPACE index 41c8880221..35855ca1e1 100644 --- a/examples/multi_python_versions/WORKSPACE +++ b/examples/multi_python_versions/WORKSPACE @@ -22,11 +22,14 @@ python_register_multi_toolchains( "3.8", "3.9", "3.10", + "3.11", ], + register_coverage_tool = True, ) load("@python//:pip.bzl", "multi_pip_parse") load("@python//3.10:defs.bzl", interpreter_3_10 = "interpreter") +load("@python//3.11:defs.bzl", interpreter_3_11 = "interpreter") load("@python//3.8:defs.bzl", interpreter_3_8 = "interpreter") load("@python//3.9:defs.bzl", interpreter_3_9 = "interpreter") @@ -35,11 +38,13 @@ multi_pip_parse( default_version = default_python_version, python_interpreter_target = { "3.10": interpreter_3_10, + "3.11": interpreter_3_11, "3.8": interpreter_3_8, "3.9": interpreter_3_9, }, requirements_lock = { "3.10": "//requirements:requirements_lock_3_10.txt", + "3.11": "//requirements:requirements_lock_3_11.txt", "3.8": "//requirements:requirements_lock_3_8.txt", "3.9": "//requirements:requirements_lock_3_9.txt", }, diff --git a/examples/multi_python_versions/requirements/BUILD.bazel b/examples/multi_python_versions/requirements/BUILD.bazel index 4848fabe10..e3184c8ac5 100644 --- a/examples/multi_python_versions/requirements/BUILD.bazel +++ b/examples/multi_python_versions/requirements/BUILD.bazel @@ -1,4 +1,5 @@ load("@python//3.10:defs.bzl", compile_pip_requirements_3_10 = "compile_pip_requirements") +load("@python//3.11:defs.bzl", compile_pip_requirements_3_11 = "compile_pip_requirements") load("@python//3.8:defs.bzl", compile_pip_requirements_3_8 = "compile_pip_requirements") load("@python//3.9:defs.bzl", compile_pip_requirements_3_9 = "compile_pip_requirements") @@ -22,3 +23,10 @@ compile_pip_requirements_3_10( requirements_in = "requirements.in", requirements_txt = "requirements_lock_3_10.txt", ) + +compile_pip_requirements_3_11( + name = "requirements_3_11", + extra_args = ["--allow-unsafe"], + requirements_in = "requirements.in", + requirements_txt = "requirements_lock_3_11.txt", +) diff --git a/examples/multi_python_versions/requirements/requirements_lock_3_11.txt b/examples/multi_python_versions/requirements/requirements_lock_3_11.txt new file mode 100644 index 0000000000..a437a397d0 --- /dev/null +++ b/examples/multi_python_versions/requirements/requirements_lock_3_11.txt @@ -0,0 +1,56 @@ +# +# This file is autogenerated by pip-compile with Python 3.11 +# by the following command: +# +# bazel run //requirements:requirements_3_11.update +# +websockets==10.3 \ + --hash=sha256:07cdc0a5b2549bcfbadb585ad8471ebdc7bdf91e32e34ae3889001c1c106a6af \ + --hash=sha256:210aad7fdd381c52e58777560860c7e6110b6174488ef1d4b681c08b68bf7f8c \ + --hash=sha256:28dd20b938a57c3124028680dc1600c197294da5db4292c76a0b48efb3ed7f76 \ + --hash=sha256:2f94fa3ae454a63ea3a19f73b95deeebc9f02ba2d5617ca16f0bbdae375cda47 \ + --hash=sha256:31564a67c3e4005f27815634343df688b25705cccb22bc1db621c781ddc64c69 \ + --hash=sha256:347974105bbd4ea068106ec65e8e8ebd86f28c19e529d115d89bd8cc5cda3079 \ + --hash=sha256:379e03422178436af4f3abe0aa8f401aa77ae2487843738542a75faf44a31f0c \ + --hash=sha256:3eda1cb7e9da1b22588cefff09f0951771d6ee9fa8dbe66f5ae04cc5f26b2b55 \ + --hash=sha256:51695d3b199cd03098ae5b42833006a0f43dc5418d3102972addc593a783bc02 \ + --hash=sha256:54c000abeaff6d8771a4e2cef40900919908ea7b6b6a30eae72752607c6db559 \ + --hash=sha256:5b936bf552e4f6357f5727579072ff1e1324717902127ffe60c92d29b67b7be3 \ + --hash=sha256:6075fd24df23133c1b078e08a9b04a3bc40b31a8def4ee0b9f2c8865acce913e \ + --hash=sha256:661f641b44ed315556a2fa630239adfd77bd1b11cb0b9d96ed8ad90b0b1e4978 \ + --hash=sha256:6ea6b300a6bdd782e49922d690e11c3669828fe36fc2471408c58b93b5535a98 \ + --hash=sha256:6ed1d6f791eabfd9808afea1e068f5e59418e55721db8b7f3bfc39dc831c42ae \ + --hash=sha256:7934e055fd5cd9dee60f11d16c8d79c4567315824bacb1246d0208a47eca9755 \ + --hash=sha256:7ab36e17af592eec5747c68ef2722a74c1a4a70f3772bc661079baf4ae30e40d \ + --hash=sha256:7f6d96fdb0975044fdd7953b35d003b03f9e2bcf85f2d2cf86285ece53e9f991 \ + --hash=sha256:83e5ca0d5b743cde3d29fda74ccab37bdd0911f25bd4cdf09ff8b51b7b4f2fa1 \ + --hash=sha256:85506b3328a9e083cc0a0fb3ba27e33c8db78341b3eb12eb72e8afd166c36680 \ + --hash=sha256:8af75085b4bc0b5c40c4a3c0e113fa95e84c60f4ed6786cbb675aeb1ee128247 \ + --hash=sha256:8b1359aba0ff810d5830d5ab8e2c4a02bebf98a60aa0124fb29aa78cfdb8031f \ + --hash=sha256:8fbd7d77f8aba46d43245e86dd91a8970eac4fb74c473f8e30e9c07581f852b2 \ + --hash=sha256:907e8247480f287aa9bbc9391bd6de23c906d48af54c8c421df84655eef66af7 \ + --hash=sha256:93d5ea0b5da8d66d868b32c614d2b52d14304444e39e13a59566d4acb8d6e2e4 \ + --hash=sha256:97bc9d41e69a7521a358f9b8e44871f6cdeb42af31815c17aed36372d4eec667 \ + --hash=sha256:994cdb1942a7a4c2e10098d9162948c9e7b235df755de91ca33f6e0481366fdb \ + --hash=sha256:a141de3d5a92188234afa61653ed0bbd2dde46ad47b15c3042ffb89548e77094 \ + --hash=sha256:a1e15b230c3613e8ea82c9fc6941b2093e8eb939dd794c02754d33980ba81e36 \ + --hash=sha256:aad5e300ab32036eb3fdc350ad30877210e2f51bceaca83fb7fef4d2b6c72b79 \ + --hash=sha256:b529fdfa881b69fe563dbd98acce84f3e5a67df13de415e143ef053ff006d500 \ + --hash=sha256:b9c77f0d1436ea4b4dc089ed8335fa141e6a251a92f75f675056dac4ab47a71e \ + --hash=sha256:bb621ec2dbbbe8df78a27dbd9dd7919f9b7d32a73fafcb4d9252fc4637343582 \ + --hash=sha256:c7250848ce69559756ad0086a37b82c986cd33c2d344ab87fea596c5ac6d9442 \ + --hash=sha256:c8d1d14aa0f600b5be363077b621b1b4d1eb3fbf90af83f9281cda668e6ff7fd \ + --hash=sha256:d1655a6fc7aecd333b079d00fb3c8132d18988e47f19740c69303bf02e9883c6 \ + --hash=sha256:d6353ba89cfc657a3f5beabb3b69be226adbb5c6c7a66398e17809b0ce3c4731 \ + --hash=sha256:da4377904a3379f0c1b75a965fff23b28315bcd516d27f99a803720dfebd94d4 \ + --hash=sha256:e49ea4c1a9543d2bd8a747ff24411509c29e4bdcde05b5b0895e2120cb1a761d \ + --hash=sha256:e4e08305bfd76ba8edab08dcc6496f40674f44eb9d5e23153efa0a35750337e8 \ + --hash=sha256:e6fa05a680e35d0fcc1470cb070b10e6fe247af54768f488ed93542e71339d6f \ + --hash=sha256:e7e6f2d6fd48422071cc8a6f8542016f350b79cc782752de531577d35e9bd677 \ + --hash=sha256:e904c0381c014b914136c492c8fa711ca4cced4e9b3d110e5e7d436d0fc289e8 \ + --hash=sha256:ec2b0ab7edc8cd4b0eb428b38ed89079bdc20c6bdb5f889d353011038caac2f9 \ + --hash=sha256:ef5ce841e102278c1c2e98f043db99d6755b1c58bde475516aef3a008ed7f28e \ + --hash=sha256:f351c7d7d92f67c0609329ab2735eee0426a03022771b00102816a72715bb00b \ + --hash=sha256:fab7c640815812ed5f10fbee7abbf58788d602046b7bb3af9b1ac753a6d5e916 \ + --hash=sha256:fc06cc8073c8e87072138ba1e431300e2d408f054b27047d047b549455066ff4 + # via -r requirements/requirements.in diff --git a/examples/multi_python_versions/tests/BUILD.bazel b/examples/multi_python_versions/tests/BUILD.bazel index 7219ca5c27..2292d53e40 100644 --- a/examples/multi_python_versions/tests/BUILD.bazel +++ b/examples/multi_python_versions/tests/BUILD.bazel @@ -1,4 +1,5 @@ load("@python//3.10:defs.bzl", py_binary_3_10 = "py_binary", py_test_3_10 = "py_test") +load("@python//3.11:defs.bzl", py_binary_3_11 = "py_binary", py_test_3_11 = "py_test") load("@python//3.8:defs.bzl", py_binary_3_8 = "py_binary", py_test_3_8 = "py_test") load("@python//3.9:defs.bzl", py_binary_3_9 = "py_binary", py_test_3_9 = "py_test") load("@rules_python//python:defs.bzl", "py_binary", "py_test") @@ -27,6 +28,12 @@ py_binary_3_10( main = "version.py", ) +py_binary_3_11( + name = "version_3_11", + srcs = ["version.py"], + main = "version.py", +) + py_test( name = "my_lib_default_test", srcs = ["my_lib_test.py"], @@ -55,6 +62,13 @@ py_test_3_10( deps = ["//libs/my_lib"], ) +py_test_3_11( + name = "my_lib_3_11_test", + srcs = ["my_lib_test.py"], + main = "my_lib_test.py", + deps = ["//libs/my_lib"], +) + py_test( name = "version_default_test", srcs = ["version_test.py"], @@ -83,6 +97,13 @@ py_test_3_10( main = "version_test.py", ) +py_test_3_11( + name = "version_3_11_test", + srcs = ["version_test.py"], + env = {"VERSION_CHECK": "3.11"}, + main = "version_test.py", +) + py_test( name = "version_default_takes_3_10_subprocess_test", srcs = ["cross_version_test.py"], diff --git a/python/extensions.bzl b/python/extensions.bzl index 0c9ad07c1a..bc0d570c52 100644 --- a/python/extensions.bzl +++ b/python/extensions.bzl @@ -19,6 +19,7 @@ load("@rules_python//python:repositories.bzl", "python_register_toolchains") load("@rules_python//python/pip_install:pip_repository.bzl", "locked_requirements_label", "pip_repository_attrs", "use_isolated", "whl_library") load("@rules_python//python/pip_install:repositories.bzl", "pip_install_dependencies") load("@rules_python//python/pip_install:requirements_parser.bzl", parse_requirements = "parse") +load("@rules_python//python/private:coverage_deps.bzl", "install_coverage_deps") def _python_impl(module_ctx): for mod in module_ctx.modules: @@ -26,20 +27,32 @@ def _python_impl(module_ctx): python_register_toolchains( name = attr.name, python_version = attr.python_version, + bzlmod = True, # Toolchain registration in bzlmod is done in MODULE file register_toolchains = False, + register_coverage_tool = attr.configure_coverage_tool, ) python = module_extension( implementation = _python_impl, tag_classes = { - "toolchain": tag_class(attrs = dict({"name": attr.string(mandatory = True), "python_version": attr.string(mandatory = True)})), + "toolchain": tag_class( + attrs = { + "configure_coverage_tool": attr.bool( + mandatory = False, + doc = "Whether or not to configure the default coverage tool for the toolchains.", + ), + "name": attr.string(mandatory = True), + "python_version": attr.string(mandatory = True), + }, + ), }, ) # buildifier: disable=unused-variable def _internal_deps_impl(module_ctx): pip_install_dependencies() + install_coverage_deps() internal_deps = module_extension( implementation = _internal_deps_impl, diff --git a/python/private/coverage_deps.bzl b/python/private/coverage_deps.bzl new file mode 100644 index 0000000000..d6092e675b --- /dev/null +++ b/python/private/coverage_deps.bzl @@ -0,0 +1,179 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Dependencies for coverage.py used by the hermetic toolchain. +""" + +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") +load( + "//python:versions.bzl", + "MINOR_MAPPING", + "PLATFORMS", +) + +# Update with './tools/update_coverage_deps.py ' +#START: managed by update_coverage_deps.py script +_coverage_deps = { + "cp310": { + "aarch64-apple-darwin": ( + "https://files.pythonhosted.org/packages/89/a2/cbf599e50bb4be416e0408c4cf523c354c51d7da39935461a9687e039481/coverage-6.5.0-cp310-cp310-macosx_11_0_arm64.whl", + "784f53ebc9f3fd0e2a3f6a78b2be1bd1f5575d7863e10c6e12504f240fd06660", + ), + "aarch64-unknown-linux-gnu": ( + "https://files.pythonhosted.org/packages/15/b0/3639d84ee8a900da0cf6450ab46e22517e4688b6cec0ba8ab6f8166103a2/coverage-6.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", + "b4a5be1748d538a710f87542f22c2cad22f80545a847ad91ce45e77417293eb4", + ), + "x86_64-apple-darwin": ( + "https://files.pythonhosted.org/packages/c4/8d/5ec7d08f4601d2d792563fe31db5e9322c306848fec1e65ec8885927f739/coverage-6.5.0-cp310-cp310-macosx_10_9_x86_64.whl", + "ef8674b0ee8cc11e2d574e3e2998aea5df5ab242e012286824ea3c6970580e53", + ), + "x86_64-unknown-linux-gnu": ( + "https://files.pythonhosted.org/packages/3c/7d/d5211ea782b193ab8064b06dc0cc042cf1a4ca9c93a530071459172c550f/coverage-6.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", + "af4fffaffc4067232253715065e30c5a7ec6faac36f8fc8d6f64263b15f74db0", + ), + }, + "cp311": { + "aarch64-unknown-linux-gnu": ( + "https://files.pythonhosted.org/packages/36/f3/5cbd79cf4cd059c80b59104aca33b8d05af4ad5bf5b1547645ecee716378/coverage-6.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", + "c4ed2820d919351f4167e52425e096af41bfabacb1857186c1ea32ff9983ed75", + ), + "x86_64-apple-darwin": ( + "https://files.pythonhosted.org/packages/50/cf/455930004231fa87efe8be06d13512f34e070ddfee8b8bf5a050cdc47ab3/coverage-6.5.0-cp311-cp311-macosx_10_9_x86_64.whl", + "4a5375e28c5191ac38cca59b38edd33ef4cc914732c916f2929029b4bfb50795", + ), + "x86_64-unknown-linux-gnu": ( + "https://files.pythonhosted.org/packages/6a/63/8e82513b7e4a1b8d887b4e85c1c2b6c9b754a581b187c0b084f3330ac479/coverage-6.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", + "a8fb6cf131ac4070c9c5a3e21de0f7dc5a0fbe8bc77c9456ced896c12fcdad91", + ), + }, + "cp38": { + "aarch64-apple-darwin": ( + "https://files.pythonhosted.org/packages/07/82/79fa21ceca9a9b091eb3c67e27eb648dade27b2c9e1eb23af47232a2a365/coverage-6.5.0-cp38-cp38-macosx_11_0_arm64.whl", + "2198ea6fc548de52adc826f62cb18554caedfb1d26548c1b7c88d8f7faa8f6ba", + ), + "aarch64-unknown-linux-gnu": ( + "https://files.pythonhosted.org/packages/40/3b/cd68cb278c4966df00158811ec1e357b9a7d132790c240fc65da57e10013/coverage-6.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", + "6c4459b3de97b75e3bd6b7d4b7f0db13f17f504f3d13e2a7c623786289dd670e", + ), + "x86_64-apple-darwin": ( + "https://files.pythonhosted.org/packages/05/63/a789b462075395d34f8152229dccf92b25ca73eac05b3f6cd75fa5017095/coverage-6.5.0-cp38-cp38-macosx_10_9_x86_64.whl", + "d900bb429fdfd7f511f868cedd03a6bbb142f3f9118c09b99ef8dc9bf9643c3c", + ), + "x86_64-unknown-linux-gnu": ( + "https://files.pythonhosted.org/packages/bd/a0/e263b115808226fdb2658f1887808c06ac3f1b579ef5dda02309e0d54459/coverage-6.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", + "6b07130585d54fe8dff3d97b93b0e20290de974dc8177c320aeaf23459219c0b", + ), + }, + "cp39": { + "aarch64-apple-darwin": ( + "https://files.pythonhosted.org/packages/63/e9/f23e8664ec4032d7802a1cf920853196bcbdce7b56408e3efe1b2da08f3c/coverage-6.5.0-cp39-cp39-macosx_11_0_arm64.whl", + "95203854f974e07af96358c0b261f1048d8e1083f2de9b1c565e1be4a3a48cfc", + ), + "aarch64-unknown-linux-gnu": ( + "https://files.pythonhosted.org/packages/18/95/27f80dcd8273171b781a19d109aeaed7f13d78ef6d1e2f7134a5826fd1b4/coverage-6.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", + "b9023e237f4c02ff739581ef35969c3739445fb059b060ca51771e69101efffe", + ), + "x86_64-apple-darwin": ( + "https://files.pythonhosted.org/packages/ea/52/c08080405329326a7ff16c0dfdb4feefaa8edd7446413df67386fe1bbfe0/coverage-6.5.0-cp39-cp39-macosx_10_9_x86_64.whl", + "633713d70ad6bfc49b34ead4060531658dc6dfc9b3eb7d8a716d5873377ab745", + ), + "x86_64-unknown-linux-gnu": ( + "https://files.pythonhosted.org/packages/6b/f2/919f0fdc93d3991ca074894402074d847be8ac1e1d78e7e9e1c371b69a6f/coverage-6.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", + "8f830ed581b45b82451a40faabb89c84e1a998124ee4212d440e9c6cf70083e5", + ), + }, +} +#END: managed by update_coverage_deps.py script + +def coverage_dep(name, python_version, platform, visibility, install = True): + """Register a singe coverage dependency based on the python version and platform. + + Args: + name: The name of the registered repository. + python_version: The full python version. + platform: The platform, which can be found in //python:versions.bzl PLATFORMS dict. + visibility: The visibility of the coverage tool. + install: should we install the dependency with a given name or generate the label + of the bzlmod dependency fallback, which is hard-coded in MODULE.bazel? + + Returns: + The label of the coverage tool if the platform is supported, otherwise - None. + """ + if "windows" in platform: + # NOTE @aignas 2023-01-19: currently we do not support windows as the + # upstream coverage wrapper is written in shell. Do not log any warning + # for now as it is not actionable. + return None + + python_short_version = python_version.rpartition(".")[0] + abi = python_short_version.replace("3.", "cp3") + url, sha256 = _coverage_deps.get(abi, {}).get(platform, (None, "")) + + if url == None: + # Some wheels are not present for some builds, so let's silently ignore those. + return None + + if not install: + # FIXME @aignas 2023-01-19: right now we use globally installed coverage + # which has visibility set to public, but is hidden due to repo remapping. + # + # The name of the toolchain is not known when registering the coverage tooling, + # so we use this as a workaround for now. + return Label("@pypi__coverage_{abi}_{platform}//:coverage".format( + abi = abi, + platform = platform, + )) + + maybe( + http_archive, + name = name, + build_file_content = """ +filegroup( + name = "coverage", + srcs = ["coverage/__main__.py"], + data = glob(["coverage/*.py", "coverage/**/*.py", "coverage/*.so"]), + visibility = {visibility}, +) + """.format( + visibility = visibility, + ), + sha256 = sha256, + type = "zip", + urls = [url], + ) + + return Label("@@{name}//:coverage".format(name = name)) + +def install_coverage_deps(): + """Register the dependency for the coverage dep. + + This is only used under bzlmod. + """ + + for python_version in MINOR_MAPPING.values(): + for platform in PLATFORMS.keys(): + if "windows" in platform: + continue + + coverage_dep( + name = "pypi__coverage_cp{version_no_dot}_{platform}".format( + version_no_dot = python_version.rpartition(".")[0].replace(".", ""), + platform = platform, + ), + python_version = python_version, + platform = platform, + visibility = ["//visibility:public"], + install = True, + ) diff --git a/python/repositories.bzl b/python/repositories.bzl index 7589640332..faaec64d95 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -19,6 +19,7 @@ For historic reasons, pip_repositories() is defined in //python:pip.bzl. load("@bazel_tools//tools/build_defs/repo:http.bzl", _http_archive = "http_archive") load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") +load("//python/private:coverage_deps.bzl", "coverage_dep") load( "//python/private:toolchains_repo.bzl", "multi_toolchain_aliases", @@ -295,9 +296,21 @@ cc_library( exports_files(["python", "{python_path}"]) +# Used to only download coverage toolchain when the coverage is collected by +# bazel. +config_setting( + name = "coverage_enabled", + values = {{"collect_code_coverage": "true"}}, + visibility = ["//visibility:private"], +) + py_runtime( name = "py3_runtime", files = [":files"], + coverage_tool = select({{ + ":coverage_enabled": {coverage_tool}, + "//conditions:default": None, + }}), interpreter = "{python_path}", python_version = "PY3", ) @@ -312,6 +325,7 @@ py_runtime_pair( python_path = python_bin, python_version = python_short_version, python_version_nodot = python_short_version.replace(".", ""), + coverage_tool = rctx.attr.coverage_tool if rctx.attr.coverage_tool == None or "windows" in rctx.os.name else "\"{}\"".format(rctx.attr.coverage_tool), ) rctx.delete("python") rctx.symlink(python_bin, "python") @@ -319,6 +333,7 @@ py_runtime_pair( rctx.file("BUILD.bazel", build_content) return { + "coverage_tool": rctx.attr.coverage_tool, "distutils": rctx.attr.distutils, "distutils_content": rctx.attr.distutils_content, "ignore_root_user_error": rctx.attr.ignore_root_user_error, @@ -336,6 +351,28 @@ python_repository = repository_rule( _python_repository_impl, doc = "Fetches the external tools needed for the Python toolchain.", attrs = { + "coverage_tool": attr.label( + # Mirrors the definition at + # https://github.com/bazelbuild/bazel/blob/master/src/main/starlark/builtins_bzl/common/python/py_runtime_rule.bzl + allow_files = False, + doc = """ +This is a target to use for collecting code coverage information from `py_binary` +and `py_test` targets. + +If set, the target must either produce a single file or be an executable target. +The path to the single file, or the executable if the target is executable, +determines the entry point for the python coverage tool. The target and its +runfiles will be added to the runfiles when coverage is enabled. + +The entry point for the tool must be loadable by a Python interpreter (e.g. a +`.py` or `.pyc` file). It must accept the command line arguments +of coverage.py (https://coverage.readthedocs.io), at least including +the `run` and `lcov` subcommands. + +For more information see the official bazel docs +(https://bazel.build/reference/be/python#py_runtime.coverage_tool). +""", + ), "distutils": attr.label( allow_single_file = True, doc = "A distutils.cfg file to be included in the Python installation. " + @@ -399,8 +436,10 @@ def python_register_toolchains( distutils = None, distutils_content = None, register_toolchains = True, + register_coverage_tool = False, set_python_version_constraint = False, tool_versions = TOOL_VERSIONS, + bzlmod = False, **kwargs): """Convenience macro for users which does typical setup. @@ -417,9 +456,11 @@ def python_register_toolchains( distutils: see the distutils attribute in the python_repository repository rule. distutils_content: see the distutils_content attribute in the python_repository repository rule. register_toolchains: Whether or not to register the downloaded toolchains. + register_coverage_tool: Whether or not to register the downloaded coverage tool to the toolchains. set_python_version_constraint: When set to true, target_compatible_with for the toolchains will include a version constraint. tool_versions: a dict containing a mapping of version with SHASUM and platform info. If not supplied, the defaults - in python/versions.bzl will be used + in python/versions.bzl will be used. + bzlmod: Whether this rule is being run under a bzlmod module extension. **kwargs: passed to each python_repositories call. """ base_url = kwargs.pop("base_url", DEFAULT_RELEASE_BASE_URL) @@ -436,6 +477,24 @@ def python_register_toolchains( (release_filename, url, strip_prefix, patches) = get_release_info(platform, python_version, base_url, tool_versions) + # allow passing in a tool version + coverage_tool = None + coverage_tool = tool_versions[python_version].get("coverage_tool", {}).get(platform, None) + if register_coverage_tool and coverage_tool == None: + coverage_tool = coverage_dep( + name = "{name}_{platform}_coverage".format( + name = name, + platform = platform, + ), + python_version = python_version, + platform = platform, + visibility = ["@@{name}_{platform}//:__subpackages__".format( + name = name, + platform = platform, + )], + install = not bzlmod, + ) + python_repository( name = "{name}_{platform}".format( name = name, @@ -450,6 +509,7 @@ def python_register_toolchains( distutils = distutils, distutils_content = distutils_content, strip_prefix = strip_prefix, + coverage_tool = coverage_tool, **kwargs ) if register_toolchains: diff --git a/python/versions.bzl b/python/versions.bzl index f843e47619..4feeeae58c 100644 --- a/python/versions.bzl +++ b/python/versions.bzl @@ -26,6 +26,21 @@ DEFAULT_RELEASE_BASE_URL = "https://github.com/indygreg/python-build-standalone/ # the hashes: # bazel run //python/private:print_toolchains_checksums # +# Note, to users looking at how to specify their tool versions, coverage_tool version for each +# interpreter can be specified by: +# "3.8.10": { +# "url": "20210506/cpython-{python_version}-{platform}-pgo+lto-20210506T0943.tar.zst", +# "sha256": { +# "x86_64-apple-darwin": "8d06bec08db8cdd0f64f4f05ee892cf2fcbc58cfb1dd69da2caab78fac420238", +# "x86_64-unknown-linux-gnu": "aec8c4c53373b90be7e2131093caa26063be6d9d826f599c935c0e1042af3355", +# }, +# "coverage_tool": { +# "x86_64-apple-darwin": """, +# "x86_64-unknown-linux-gnu": """, +# }, +# "strip_prefix": "python", +# }, +# # buildifier: disable=unsorted-dict-items TOOL_VERSIONS = { "3.8.10": { diff --git a/tools/update_coverage_deps.py b/tools/update_coverage_deps.py new file mode 100755 index 0000000000..4cf1e94232 --- /dev/null +++ b/tools/update_coverage_deps.py @@ -0,0 +1,258 @@ +#!/usr/bin/python3 -B +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""A small script to update bazel files within the repo. + +We are not running this with 'bazel run' to keep the dependencies minimal +""" + +# NOTE @aignas 2023-01-09: We should only depend on core Python 3 packages. +import argparse +import difflib +import json +import pathlib +import sys +import textwrap +from collections import defaultdict +from dataclasses import dataclass +from typing import Any +from urllib import request + +# This should be kept in sync with //python:versions.bzl +_supported_platforms = { + # Windows is unsupported right now + # "win_amd64": "x86_64-pc-windows-msvc", + "manylinux2014_x86_64": "x86_64-unknown-linux-gnu", + "manylinux2014_aarch64": "aarch64-unknown-linux-gnu", + "macosx_11_0_arm64": "aarch64-apple-darwin", + "macosx_10_9_x86_64": "x86_64-apple-darwin", +} + + +@dataclass +class Dep: + name: str + platform: str + python: str + url: str + sha256: str + + @property + def repo_name(self): + return f"pypi__{self.name}_{self.python}_{self.platform}" + + def __repr__(self): + return "\n".join( + [ + "(", + f' "{self.url}",', + f' "{self.sha256}",', + ")", + ] + ) + + +@dataclass +class Deps: + deps: list[Dep] + + def __repr__(self): + deps = defaultdict(dict) + for d in self.deps: + deps[d.python][d.platform] = d + + parts = [] + for python, contents in deps.items(): + inner = textwrap.indent( + "\n".join([f'"{platform}": {d},' for platform, d in contents.items()]), + prefix=" ", + ) + parts.append('"{}": {{\n{}\n}},'.format(python, inner)) + return "{{\n{}\n}}".format(textwrap.indent("\n".join(parts), prefix=" ")) + + +def _get_platforms(filename: str, name: str, version: str, python_version: str): + return filename[ + len(f"{name}-{version}-{python_version}-{python_version}-") : -len(".whl") + ].split(".") + + +def _map( + name: str, + filename: str, + python_version: str, + url: str, + digests: list, + platform: str, + **kwargs: Any, +): + if platform not in _supported_platforms: + return None + + return Dep( + name=name, + platform=_supported_platforms[platform], + python=python_version, + url=url, + sha256=digests["sha256"], + ) + + +def _writelines(path: pathlib.Path, lines: list[str]): + with open(path, "w") as f: + f.writelines(lines) + + +def _difflines(path: pathlib.Path, lines: list[str]): + with open(path) as f: + input = f.readlines() + + rules_python = pathlib.Path(__file__).parent.parent + p = path.relative_to(rules_python) + + print(f"Diff of the changes that would be made to '{p}':") + for line in difflib.unified_diff( + input, + lines, + fromfile=f"a/{p}", + tofile=f"b/{p}", + ): + print(line, end="") + + # Add an empty line at the end of the diff + print() + + +def _update_file( + path: pathlib.Path, + snippet: str, + start_marker: str, + end_marker: str, + dry_run: bool = True, +): + with open(path) as f: + input = f.readlines() + + out = [] + skip = False + for line in input: + if skip: + if not line.startswith(end_marker): + continue + + skip = False + + out.append(line) + + if not line.startswith(start_marker): + continue + + skip = True + out.extend([f"{line}\n" for line in snippet.splitlines()]) + + if dry_run: + _difflines(path, out) + else: + _writelines(path, out) + + +def _parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(__doc__) + parser.add_argument( + "--name", + default="coverage", + type=str, + help="The name of the package", + ) + parser.add_argument( + "version", + type=str, + help="The version of the package to download", + ) + parser.add_argument( + "--py", + nargs="+", + type=str, + default=["cp38", "cp39", "cp310", "cp311"], + help="Supported python versions", + ) + parser.add_argument( + "--dry-run", + action="store_true", + help="Wether to write to files", + ) + return parser.parse_args() + + +def main(): + args = _parse_args() + + api_url = f"https://pypi.python.org/pypi/{args.name}/{args.version}/json" + req = request.Request(api_url) + with request.urlopen(req) as response: + data = json.loads(response.read().decode("utf-8")) + + urls = [] + for u in data["urls"]: + if u["yanked"]: + continue + + if not u["filename"].endswith(".whl"): + continue + + if u["python_version"] not in args.py: + continue + + if f'_{u["python_version"]}m_' in u["filename"]: + continue + + platforms = _get_platforms( + u["filename"], + args.name, + args.version, + u["python_version"], + ) + + result = [_map(name=args.name, platform=p, **u) for p in platforms] + urls.extend(filter(None, result)) + + urls.sort(key=lambda x: f"{x.python}_{x.platform}") + + rules_python = pathlib.Path(__file__).parent.parent + + # Update the coverage_deps, which are used to register deps + _update_file( + path=rules_python / "python" / "private" / "coverage_deps.bzl", + snippet=f"_coverage_deps = {repr(Deps(urls))}\n", + start_marker="#START: managed by update_coverage_deps.py script", + end_marker="#END: managed by update_coverage_deps.py script", + dry_run=args.dry_run, + ) + + # Update the MODULE.bazel, which needs to expose the dependencies to the toolchain + # repositories + _update_file( + path=rules_python / "MODULE.bazel", + snippet="".join(sorted([f' "{u.repo_name}",\n' for u in urls])), + start_marker=" # coverage_deps managed by running", + end_marker=")", + dry_run=args.dry_run, + ) + + return + + +if __name__ == "__main__": + main() From e0f2f5626aadc15be312f1cd2b41d9fab64456ff Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Tue, 31 Jan 2023 09:10:20 -0800 Subject: [PATCH 144/234] Manually generate distribution archives (#1032) Github has a habit of changing how the automatic source archives are generated (e.g. compression), which changes their checksums, which then breaks users. Instead of risking that happening again, generate the distribution archive as part of the release workflow and upload it to the release. The same mechanism, `git export` is used, so the format and structure is the same as before. --- ...kspace_snippet.sh => create_archive_and_notes.sh} | 12 +++++++----- .github/workflows/release.yml | 6 ++++-- 2 files changed, 11 insertions(+), 7 deletions(-) rename .github/workflows/{workspace_snippet.sh => create_archive_and_notes.sh} (82%) diff --git a/.github/workflows/workspace_snippet.sh b/.github/workflows/create_archive_and_notes.sh similarity index 82% rename from .github/workflows/workspace_snippet.sh rename to .github/workflows/create_archive_and_notes.sh index bfc0d8b0e4..549af074eb 100755 --- a/.github/workflows/workspace_snippet.sh +++ b/.github/workflows/create_archive_and_notes.sh @@ -13,16 +13,18 @@ # See the License for the specific language governing permissions and # limitations under the License. - set -o errexit -o nounset -o pipefail # Set by GH actions, see # https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables TAG=${GITHUB_REF_NAME} +# A prefix is added to better match the GitHub generated archives. PREFIX="rules_python-${TAG}" -SHA=$(git archive --format=tar --prefix=${PREFIX}/ ${TAG} | gzip | shasum -a 256 | awk '{print $1}') +ARCHIVE="rules_python-$TAG.tar.gz" +git archive --format=tar --prefix=${PREFIX}/ ${TAG} | gzip > $ARCHIVE +SHA=$(shasum -a 256 $ARCHIVE | awk '{print $1}') -cat << EOF +cat > release_notes.txt << EOF ## Using Bzlmod with Bazel 6 Add to your \`MODULE.bazel\` file: @@ -65,7 +67,7 @@ http_archive( name = "rules_python", sha256 = "${SHA}", strip_prefix = "${PREFIX}", - url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/${TAG}.tar.gz", + url = "https://github.com/bazelbuild/rules_python/releases/download/${TAG}/rules_python-${TAG}.tar.gz", ) load("@rules_python//python:repositories.bzl", "py_repositories") @@ -83,7 +85,7 @@ http_archive( name = "rules_python_gazelle_plugin", sha256 = "${SHA}", strip_prefix = "${PREFIX}/gazelle", - url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/${TAG}.tar.gz", + url = "https://github.com/bazelbuild/rules_python/releases/download/${TAG}/rules_python-${TAG}.tar.gz", ) \`\`\` EOF diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5b1cde014a..1e89fa85a2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,11 +26,13 @@ jobs: steps: - name: Checkout uses: actions/checkout@v2 - - name: Prepare workspace snippet - run: .github/workflows/workspace_snippet.sh > release_notes.txt + - name: Create release archive and notes + run: .github/workflows/create_archive_and_notes.sh - name: Release uses: softprops/action-gh-release@v1 with: # Use GH feature to populate the changelog automatically generate_release_notes: true body_path: release_notes.txt + fail_on_unmatched_files: true + files: rules_python-*.tar.gz From b122f3a227ee4daa64e05b2e8a8ff6c68afcdd72 Mon Sep 17 00:00:00 2001 From: Matt Mackay Date: Tue, 31 Jan 2023 17:02:18 -0500 Subject: [PATCH 145/234] fix: use 'repo' as prefix when constructing annotations label (#1033) --- .../tools/lock_file_generator/lock_file_generator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/pip_install/tools/lock_file_generator/lock_file_generator.py b/python/pip_install/tools/lock_file_generator/lock_file_generator.py index 4a64b3b8a7..ed1488dd45 100644 --- a/python/pip_install/tools/lock_file_generator/lock_file_generator.py +++ b/python/pip_install/tools/lock_file_generator/lock_file_generator.py @@ -300,7 +300,7 @@ def main(output: TextIO) -> None: annotated_requirements.update( { name: "@{}//:{}.annotation.json".format( - args.repo_prefix.rstrip("_"), name + args.repo, name ) } ) From 9fc7cfa82ac834f0dcc5ba321a46b93e9b728f87 Mon Sep 17 00:00:00 2001 From: Zhongpeng Lin Date: Tue, 31 Jan 2023 15:44:23 -0800 Subject: [PATCH 146/234] Resolving sibling modules with absolute imports (#1029) * Resolving sibling modules with absolute imports * unconditionally importing conftest * handle from statements * adding tests * adding readme for the new test case --- gazelle/python/generate.go | 19 +++--------- gazelle/python/resolve.go | 11 ------- gazelle/python/target.go | 27 +++++++---------- .../generated_test_entrypoint/BUILD.out | 5 +--- .../testdata/naming_convention/__main__.py | 1 + .../testdata/naming_convention/__test__.py | 1 + .../naming_convention/dont_rename/__main__.py | 1 + .../naming_convention/dont_rename/__test__.py | 1 + .../resolve_conflict/__main__.py | 1 + .../resolve_conflict/__test__.py | 1 + .../real_test.py | 1 + .../test_reality.py | 1 + .../python/testdata/sibling_imports/README.md | 3 ++ .../python/testdata/sibling_imports/WORKSPACE | 1 + .../testdata/sibling_imports/pkg/BUILD.in | 0 .../testdata/sibling_imports/pkg/BUILD.out | 29 +++++++++++++++++++ .../testdata/sibling_imports/pkg/__init__.py | 0 .../python/testdata/sibling_imports/pkg/a.py | 0 .../python/testdata/sibling_imports/pkg/b.py | 2 ++ .../testdata/sibling_imports/pkg/test_util.py | 0 .../testdata/sibling_imports/pkg/unit_test.py | 3 ++ .../python/testdata/sibling_imports/test.yaml | 1 + .../simple_binary_with_library/__main__.py | 1 + .../subdir_sources/foo/has_main/__main__.py | 1 + .../subdir_sources/foo/has_test/__test__.py | 1 + .../with_third_party_requirements/BUILD.out | 2 +- 26 files changed, 66 insertions(+), 48 deletions(-) create mode 100644 gazelle/python/testdata/sibling_imports/README.md create mode 100644 gazelle/python/testdata/sibling_imports/WORKSPACE create mode 100644 gazelle/python/testdata/sibling_imports/pkg/BUILD.in create mode 100644 gazelle/python/testdata/sibling_imports/pkg/BUILD.out create mode 100644 gazelle/python/testdata/sibling_imports/pkg/__init__.py create mode 100644 gazelle/python/testdata/sibling_imports/pkg/a.py create mode 100644 gazelle/python/testdata/sibling_imports/pkg/b.py create mode 100644 gazelle/python/testdata/sibling_imports/pkg/test_util.py create mode 100644 gazelle/python/testdata/sibling_imports/pkg/unit_test.py create mode 100644 gazelle/python/testdata/sibling_imports/test.yaml diff --git a/gazelle/python/generate.go b/gazelle/python/generate.go index 4ebb40f6bb..74e5f66509 100644 --- a/gazelle/python/generate.go +++ b/gazelle/python/generate.go @@ -224,7 +224,6 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } pyLibrary = newTargetBuilder(pyLibraryKind, pyLibraryTargetName, pythonProjectRoot, args.Rel, pyLibraryFilenames.Union(pyTestFilenames)). - setUUID(label.New("", args.Rel, pyLibraryTargetName).String()). addVisibility(visibility). addSrcs(pyLibraryFilenames). addModuleDependencies(deps). @@ -267,10 +266,6 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes addModuleDependencies(deps). generateImportsAttribute() - if pyLibrary != nil { - pyBinaryTarget.addModuleDependency(module{Name: pyLibrary.PrivateAttr(uuidKey).(string)}) - } - pyBinary := pyBinaryTarget.build() result.Gen = append(result.Gen, pyBinary) @@ -301,7 +296,6 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } conftestTarget := newTargetBuilder(pyLibraryKind, conftestTargetname, pythonProjectRoot, args.Rel, pyLibraryFilenames.Union(pyTestFilenames)). - setUUID(label.New("", args.Rel, conftestTargetname).String()). addSrc(conftestFilename). addModuleDependencies(deps). addVisibility(visibility). @@ -315,8 +309,8 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } var pyTestTargets []*targetBuilder - newPyTestTargetBuilder := func(pyTestFilenames *treeset.Set, pyTestTargetName string) *targetBuilder { - deps, err := parser.parse(pyTestFilenames) + newPyTestTargetBuilder := func(srcs *treeset.Set, pyTestTargetName string) *targetBuilder { + deps, err := parser.parse(srcs) if err != nil { log.Fatalf("ERROR: %v\n", err) } @@ -337,7 +331,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } } return newTargetBuilder(pyTestKind, pyTestTargetName, pythonProjectRoot, args.Rel, pyLibraryFilenames.Union(pyTestFilenames)). - addSrcs(pyTestFilenames). + addSrcs(srcs). addModuleDependencies(deps). generateImportsAttribute() } @@ -371,14 +365,9 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } for _, pyTestTarget := range pyTestTargets { - if pyLibrary != nil { - pyTestTarget.addModuleDependency(module{Name: pyLibrary.PrivateAttr(uuidKey).(string)}) - } - if conftest != nil { - pyTestTarget.addModuleDependency(module{Name: conftest.PrivateAttr(uuidKey).(string)}) + pyTestTarget.addModuleDependency(module{Name: strings.TrimSuffix(conftestFilename, ".py")}) } - pyTest := pyTestTarget.build() result.Gen = append(result.Gen, pyTest) diff --git a/gazelle/python/resolve.go b/gazelle/python/resolve.go index 607776aee3..46014e50ec 100644 --- a/gazelle/python/resolve.go +++ b/gazelle/python/resolve.go @@ -39,10 +39,6 @@ const ( // resolvedDepsKey is the attribute key used to pass dependencies that don't // need to be resolved by the dependency resolver in the Resolver step. resolvedDepsKey = "_gazelle_python_resolved_deps" - // uuidKey is the attribute key used to uniquely identify a py_library - // target that should be imported by a py_test or py_binary in the same - // Bazel package. - uuidKey = "_gazelle_python_library_uuid" ) // Resolver satisfies the resolve.Resolver interface. It resolves dependencies @@ -71,13 +67,6 @@ func (py *Resolver) Imports(c *config.Config, r *rule.Rule, f *rule.File) []reso provides = append(provides, provide) } } - if r.PrivateAttr(uuidKey) != nil { - provide := resolve.ImportSpec{ - Lang: languageName, - Imp: r.PrivateAttr(uuidKey).(string), - } - provides = append(provides, provide) - } if len(provides) == 0 { return nil } diff --git a/gazelle/python/target.go b/gazelle/python/target.go index 69711ce643..fdc99fc68c 100644 --- a/gazelle/python/target.go +++ b/gazelle/python/target.go @@ -15,12 +15,11 @@ package python import ( - "path/filepath" - "github.com/bazelbuild/bazel-gazelle/config" "github.com/bazelbuild/bazel-gazelle/rule" "github.com/emirpasic/gods/sets/treeset" godsutils "github.com/emirpasic/gods/utils" + "path/filepath" ) // targetBuilder builds targets to be generated by Gazelle. @@ -29,7 +28,6 @@ type targetBuilder struct { name string pythonProjectRoot string bzlPackage string - uuid string srcs *treeset.Set siblingSrcs *treeset.Set deps *treeset.Set @@ -55,15 +53,6 @@ func newTargetBuilder(kind, name, pythonProjectRoot, bzlPackage string, siblingS } } -// setUUID sets the given UUID for the target. It's used to index the generated -// target based on this value in addition to the other ways the targets can be -// imported. py_{binary,test} targets in the same Bazel package can add a -// virtual dependency to this UUID that gets resolved in the Resolver interface. -func (t *targetBuilder) setUUID(uuid string) *targetBuilder { - t.uuid = uuid - return t -} - // addSrc adds a single src to the target. func (t *targetBuilder) addSrc(src string) *targetBuilder { t.srcs.Add(src) @@ -81,9 +70,16 @@ func (t *targetBuilder) addSrcs(srcs *treeset.Set) *targetBuilder { // addModuleDependency adds a single module dep to the target. func (t *targetBuilder) addModuleDependency(dep module) *targetBuilder { - if dep.Name+".py" == filepath.Base(dep.Filepath) || !t.siblingSrcs.Contains(dep.Name+".py") { - t.deps.Add(dep) + fileName := dep.Name + ".py" + if dep.From != "" { + fileName = dep.From + ".py" } + if t.siblingSrcs.Contains(fileName) && fileName != filepath.Base(dep.Filepath) { + // importing another module from the same package, converting to absolute imports to make + // dependency resolution easier + dep.Name = importSpecFromSrc(t.pythonProjectRoot, t.bzlPackage, fileName).Imp + } + t.deps.Add(dep) return t } @@ -138,9 +134,6 @@ func (t *targetBuilder) generateImportsAttribute() *targetBuilder { // build returns the assembled *rule.Rule for the target. func (t *targetBuilder) build() *rule.Rule { r := rule.NewRule(t.kind, t.name) - if t.uuid != "" { - r.SetPrivateAttr(uuidKey, t.uuid) - } if !t.srcs.Empty() { r.SetAttr("srcs", t.srcs.Values()) } diff --git a/gazelle/python/testdata/generated_test_entrypoint/BUILD.out b/gazelle/python/testdata/generated_test_entrypoint/BUILD.out index 48df0688a6..e8e304c72b 100644 --- a/gazelle/python/testdata/generated_test_entrypoint/BUILD.out +++ b/gazelle/python/testdata/generated_test_entrypoint/BUILD.out @@ -17,8 +17,5 @@ py_test( name = "generated_test_entrypoint_test", srcs = [":__test__"], main = ":__test__.py", - deps = [ - ":__test__", - ":generated_test_entrypoint", - ], + deps = [":__test__"], ) diff --git a/gazelle/python/testdata/naming_convention/__main__.py b/gazelle/python/testdata/naming_convention/__main__.py index 730755995d..a3afc79dcd 100644 --- a/gazelle/python/testdata/naming_convention/__main__.py +++ b/gazelle/python/testdata/naming_convention/__main__.py @@ -13,3 +13,4 @@ # limitations under the License. # For test purposes only. +import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/naming_convention/__test__.py b/gazelle/python/testdata/naming_convention/__test__.py index 730755995d..a3afc79dcd 100644 --- a/gazelle/python/testdata/naming_convention/__test__.py +++ b/gazelle/python/testdata/naming_convention/__test__.py @@ -13,3 +13,4 @@ # limitations under the License. # For test purposes only. +import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/naming_convention/dont_rename/__main__.py b/gazelle/python/testdata/naming_convention/dont_rename/__main__.py index 730755995d..a3afc79dcd 100644 --- a/gazelle/python/testdata/naming_convention/dont_rename/__main__.py +++ b/gazelle/python/testdata/naming_convention/dont_rename/__main__.py @@ -13,3 +13,4 @@ # limitations under the License. # For test purposes only. +import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/naming_convention/dont_rename/__test__.py b/gazelle/python/testdata/naming_convention/dont_rename/__test__.py index 730755995d..a3afc79dcd 100644 --- a/gazelle/python/testdata/naming_convention/dont_rename/__test__.py +++ b/gazelle/python/testdata/naming_convention/dont_rename/__test__.py @@ -13,3 +13,4 @@ # limitations under the License. # For test purposes only. +import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py b/gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py index 730755995d..a3afc79dcd 100644 --- a/gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py +++ b/gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py @@ -13,3 +13,4 @@ # limitations under the License. # For test purposes only. +import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py b/gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py index 730755995d..a3afc79dcd 100644 --- a/gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py +++ b/gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py @@ -13,3 +13,4 @@ # limitations under the License. # For test purposes only. +import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/python_target_with_test_in_name/real_test.py b/gazelle/python/testdata/python_target_with_test_in_name/real_test.py index 2f032112ef..e390866be3 100644 --- a/gazelle/python/testdata/python_target_with_test_in_name/real_test.py +++ b/gazelle/python/testdata/python_target_with_test_in_name/real_test.py @@ -13,5 +13,6 @@ # limitations under the License. import boto3 +import __init__ _ = boto3 diff --git a/gazelle/python/testdata/python_target_with_test_in_name/test_reality.py b/gazelle/python/testdata/python_target_with_test_in_name/test_reality.py index 730755995d..a3afc79dcd 100644 --- a/gazelle/python/testdata/python_target_with_test_in_name/test_reality.py +++ b/gazelle/python/testdata/python_target_with_test_in_name/test_reality.py @@ -13,3 +13,4 @@ # limitations under the License. # For test purposes only. +import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/sibling_imports/README.md b/gazelle/python/testdata/sibling_imports/README.md new file mode 100644 index 0000000000..e59be07634 --- /dev/null +++ b/gazelle/python/testdata/sibling_imports/README.md @@ -0,0 +1,3 @@ +# Sibling imports + +This test case asserts that imports from sibling modules are resolved correctly. It covers 3 different types of imports in `pkg/unit_test.py` \ No newline at end of file diff --git a/gazelle/python/testdata/sibling_imports/WORKSPACE b/gazelle/python/testdata/sibling_imports/WORKSPACE new file mode 100644 index 0000000000..faff6af87a --- /dev/null +++ b/gazelle/python/testdata/sibling_imports/WORKSPACE @@ -0,0 +1 @@ +# This is a Bazel workspace for the Gazelle test data. diff --git a/gazelle/python/testdata/sibling_imports/pkg/BUILD.in b/gazelle/python/testdata/sibling_imports/pkg/BUILD.in new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/python/testdata/sibling_imports/pkg/BUILD.out b/gazelle/python/testdata/sibling_imports/pkg/BUILD.out new file mode 100644 index 0000000000..edb40a8bcb --- /dev/null +++ b/gazelle/python/testdata/sibling_imports/pkg/BUILD.out @@ -0,0 +1,29 @@ +load("@rules_python//python:defs.bzl", "py_library", "py_test") + +py_library( + name = "pkg", + srcs = [ + "__init__.py", + "a.py", + "b.py", + ], + imports = [".."], + visibility = ["//:__subpackages__"], +) + +py_test( + name = "test_util", + srcs = ["test_util.py"], + imports = [".."], +) + +py_test( + name = "unit_test", + srcs = ["unit_test.py"], + imports = [".."], + deps = [ + ":pkg", + ":test_util", + ], +) + diff --git a/gazelle/python/testdata/sibling_imports/pkg/__init__.py b/gazelle/python/testdata/sibling_imports/pkg/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/python/testdata/sibling_imports/pkg/a.py b/gazelle/python/testdata/sibling_imports/pkg/a.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/python/testdata/sibling_imports/pkg/b.py b/gazelle/python/testdata/sibling_imports/pkg/b.py new file mode 100644 index 0000000000..7095bdcfb2 --- /dev/null +++ b/gazelle/python/testdata/sibling_imports/pkg/b.py @@ -0,0 +1,2 @@ +def run(): + pass \ No newline at end of file diff --git a/gazelle/python/testdata/sibling_imports/pkg/test_util.py b/gazelle/python/testdata/sibling_imports/pkg/test_util.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/python/testdata/sibling_imports/pkg/unit_test.py b/gazelle/python/testdata/sibling_imports/pkg/unit_test.py new file mode 100644 index 0000000000..a3218e2ec2 --- /dev/null +++ b/gazelle/python/testdata/sibling_imports/pkg/unit_test.py @@ -0,0 +1,3 @@ +import a +from b import run +import test_util \ No newline at end of file diff --git a/gazelle/python/testdata/sibling_imports/test.yaml b/gazelle/python/testdata/sibling_imports/test.yaml new file mode 100644 index 0000000000..ed97d539c0 --- /dev/null +++ b/gazelle/python/testdata/sibling_imports/test.yaml @@ -0,0 +1 @@ +--- diff --git a/gazelle/python/testdata/simple_binary_with_library/__main__.py b/gazelle/python/testdata/simple_binary_with_library/__main__.py index 730755995d..bc7ddf0a71 100644 --- a/gazelle/python/testdata/simple_binary_with_library/__main__.py +++ b/gazelle/python/testdata/simple_binary_with_library/__main__.py @@ -13,3 +13,4 @@ # limitations under the License. # For test purposes only. +import foo diff --git a/gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py b/gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py index 730755995d..bd0fe61faa 100644 --- a/gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py +++ b/gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py @@ -13,3 +13,4 @@ # limitations under the License. # For test purposes only. +import foo.has_main.python.my_module \ No newline at end of file diff --git a/gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py b/gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py index 730755995d..3c9ed1a1bd 100644 --- a/gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py +++ b/gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py @@ -13,3 +13,4 @@ # limitations under the License. # For test purposes only. +import foo.has_test.python.my_module \ No newline at end of file diff --git a/gazelle/python/testdata/with_third_party_requirements/BUILD.out b/gazelle/python/testdata/with_third_party_requirements/BUILD.out index 2da7f2bd86..2a97d8bc1e 100644 --- a/gazelle/python/testdata/with_third_party_requirements/BUILD.out +++ b/gazelle/python/testdata/with_third_party_requirements/BUILD.out @@ -20,5 +20,5 @@ py_binary( srcs = ["__main__.py"], main = "__main__.py", visibility = ["//:__subpackages__"], - deps = [":with_third_party_requirements"], + deps = ["@gazelle_python_test_baz//:pkg"], ) From 6e5a5641bf5cc1caf0d003fe6bd852a7324e61e1 Mon Sep 17 00:00:00 2001 From: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Date: Tue, 31 Jan 2023 16:47:17 -0800 Subject: [PATCH 147/234] fix: reorder imports (#1034) Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- gazelle/python/target.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gazelle/python/target.go b/gazelle/python/target.go index fdc99fc68c..149c158a94 100644 --- a/gazelle/python/target.go +++ b/gazelle/python/target.go @@ -15,11 +15,12 @@ package python import ( + "path/filepath" + "github.com/bazelbuild/bazel-gazelle/config" "github.com/bazelbuild/bazel-gazelle/rule" "github.com/emirpasic/gods/sets/treeset" godsutils "github.com/emirpasic/gods/utils" - "path/filepath" ) // targetBuilder builds targets to be generated by Gazelle. From 3d17505eed7a3bdd40a51e2ae9bc5f31c6cd14c6 Mon Sep 17 00:00:00 2001 From: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Date: Tue, 31 Jan 2023 17:43:22 -0800 Subject: [PATCH 148/234] Revert "Resolving sibling modules with absolute imports" (#1035) Revert "Resolving sibling modules with absolute imports (#1029)" This reverts commit 9fc7cfa82ac834f0dcc5ba321a46b93e9b728f87. Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- gazelle/python/generate.go | 19 +++++++++--- gazelle/python/resolve.go | 11 +++++++ gazelle/python/target.go | 24 +++++++++------ .../generated_test_entrypoint/BUILD.out | 5 +++- .../testdata/naming_convention/__main__.py | 1 - .../testdata/naming_convention/__test__.py | 1 - .../naming_convention/dont_rename/__main__.py | 1 - .../naming_convention/dont_rename/__test__.py | 1 - .../resolve_conflict/__main__.py | 1 - .../resolve_conflict/__test__.py | 1 - .../real_test.py | 1 - .../test_reality.py | 1 - .../python/testdata/sibling_imports/README.md | 3 -- .../python/testdata/sibling_imports/WORKSPACE | 1 - .../testdata/sibling_imports/pkg/BUILD.in | 0 .../testdata/sibling_imports/pkg/BUILD.out | 29 ------------------- .../testdata/sibling_imports/pkg/__init__.py | 0 .../python/testdata/sibling_imports/pkg/a.py | 0 .../python/testdata/sibling_imports/pkg/b.py | 2 -- .../testdata/sibling_imports/pkg/test_util.py | 0 .../testdata/sibling_imports/pkg/unit_test.py | 3 -- .../python/testdata/sibling_imports/test.yaml | 1 - .../simple_binary_with_library/__main__.py | 1 - .../subdir_sources/foo/has_main/__main__.py | 1 - .../subdir_sources/foo/has_test/__test__.py | 1 - .../with_third_party_requirements/BUILD.out | 2 +- 26 files changed, 46 insertions(+), 65 deletions(-) delete mode 100644 gazelle/python/testdata/sibling_imports/README.md delete mode 100644 gazelle/python/testdata/sibling_imports/WORKSPACE delete mode 100644 gazelle/python/testdata/sibling_imports/pkg/BUILD.in delete mode 100644 gazelle/python/testdata/sibling_imports/pkg/BUILD.out delete mode 100644 gazelle/python/testdata/sibling_imports/pkg/__init__.py delete mode 100644 gazelle/python/testdata/sibling_imports/pkg/a.py delete mode 100644 gazelle/python/testdata/sibling_imports/pkg/b.py delete mode 100644 gazelle/python/testdata/sibling_imports/pkg/test_util.py delete mode 100644 gazelle/python/testdata/sibling_imports/pkg/unit_test.py delete mode 100644 gazelle/python/testdata/sibling_imports/test.yaml diff --git a/gazelle/python/generate.go b/gazelle/python/generate.go index 74e5f66509..4ebb40f6bb 100644 --- a/gazelle/python/generate.go +++ b/gazelle/python/generate.go @@ -224,6 +224,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } pyLibrary = newTargetBuilder(pyLibraryKind, pyLibraryTargetName, pythonProjectRoot, args.Rel, pyLibraryFilenames.Union(pyTestFilenames)). + setUUID(label.New("", args.Rel, pyLibraryTargetName).String()). addVisibility(visibility). addSrcs(pyLibraryFilenames). addModuleDependencies(deps). @@ -266,6 +267,10 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes addModuleDependencies(deps). generateImportsAttribute() + if pyLibrary != nil { + pyBinaryTarget.addModuleDependency(module{Name: pyLibrary.PrivateAttr(uuidKey).(string)}) + } + pyBinary := pyBinaryTarget.build() result.Gen = append(result.Gen, pyBinary) @@ -296,6 +301,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } conftestTarget := newTargetBuilder(pyLibraryKind, conftestTargetname, pythonProjectRoot, args.Rel, pyLibraryFilenames.Union(pyTestFilenames)). + setUUID(label.New("", args.Rel, conftestTargetname).String()). addSrc(conftestFilename). addModuleDependencies(deps). addVisibility(visibility). @@ -309,8 +315,8 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } var pyTestTargets []*targetBuilder - newPyTestTargetBuilder := func(srcs *treeset.Set, pyTestTargetName string) *targetBuilder { - deps, err := parser.parse(srcs) + newPyTestTargetBuilder := func(pyTestFilenames *treeset.Set, pyTestTargetName string) *targetBuilder { + deps, err := parser.parse(pyTestFilenames) if err != nil { log.Fatalf("ERROR: %v\n", err) } @@ -331,7 +337,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } } return newTargetBuilder(pyTestKind, pyTestTargetName, pythonProjectRoot, args.Rel, pyLibraryFilenames.Union(pyTestFilenames)). - addSrcs(srcs). + addSrcs(pyTestFilenames). addModuleDependencies(deps). generateImportsAttribute() } @@ -365,9 +371,14 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } for _, pyTestTarget := range pyTestTargets { + if pyLibrary != nil { + pyTestTarget.addModuleDependency(module{Name: pyLibrary.PrivateAttr(uuidKey).(string)}) + } + if conftest != nil { - pyTestTarget.addModuleDependency(module{Name: strings.TrimSuffix(conftestFilename, ".py")}) + pyTestTarget.addModuleDependency(module{Name: conftest.PrivateAttr(uuidKey).(string)}) } + pyTest := pyTestTarget.build() result.Gen = append(result.Gen, pyTest) diff --git a/gazelle/python/resolve.go b/gazelle/python/resolve.go index 46014e50ec..607776aee3 100644 --- a/gazelle/python/resolve.go +++ b/gazelle/python/resolve.go @@ -39,6 +39,10 @@ const ( // resolvedDepsKey is the attribute key used to pass dependencies that don't // need to be resolved by the dependency resolver in the Resolver step. resolvedDepsKey = "_gazelle_python_resolved_deps" + // uuidKey is the attribute key used to uniquely identify a py_library + // target that should be imported by a py_test or py_binary in the same + // Bazel package. + uuidKey = "_gazelle_python_library_uuid" ) // Resolver satisfies the resolve.Resolver interface. It resolves dependencies @@ -67,6 +71,13 @@ func (py *Resolver) Imports(c *config.Config, r *rule.Rule, f *rule.File) []reso provides = append(provides, provide) } } + if r.PrivateAttr(uuidKey) != nil { + provide := resolve.ImportSpec{ + Lang: languageName, + Imp: r.PrivateAttr(uuidKey).(string), + } + provides = append(provides, provide) + } if len(provides) == 0 { return nil } diff --git a/gazelle/python/target.go b/gazelle/python/target.go index 149c158a94..69711ce643 100644 --- a/gazelle/python/target.go +++ b/gazelle/python/target.go @@ -29,6 +29,7 @@ type targetBuilder struct { name string pythonProjectRoot string bzlPackage string + uuid string srcs *treeset.Set siblingSrcs *treeset.Set deps *treeset.Set @@ -54,6 +55,15 @@ func newTargetBuilder(kind, name, pythonProjectRoot, bzlPackage string, siblingS } } +// setUUID sets the given UUID for the target. It's used to index the generated +// target based on this value in addition to the other ways the targets can be +// imported. py_{binary,test} targets in the same Bazel package can add a +// virtual dependency to this UUID that gets resolved in the Resolver interface. +func (t *targetBuilder) setUUID(uuid string) *targetBuilder { + t.uuid = uuid + return t +} + // addSrc adds a single src to the target. func (t *targetBuilder) addSrc(src string) *targetBuilder { t.srcs.Add(src) @@ -71,16 +81,9 @@ func (t *targetBuilder) addSrcs(srcs *treeset.Set) *targetBuilder { // addModuleDependency adds a single module dep to the target. func (t *targetBuilder) addModuleDependency(dep module) *targetBuilder { - fileName := dep.Name + ".py" - if dep.From != "" { - fileName = dep.From + ".py" + if dep.Name+".py" == filepath.Base(dep.Filepath) || !t.siblingSrcs.Contains(dep.Name+".py") { + t.deps.Add(dep) } - if t.siblingSrcs.Contains(fileName) && fileName != filepath.Base(dep.Filepath) { - // importing another module from the same package, converting to absolute imports to make - // dependency resolution easier - dep.Name = importSpecFromSrc(t.pythonProjectRoot, t.bzlPackage, fileName).Imp - } - t.deps.Add(dep) return t } @@ -135,6 +138,9 @@ func (t *targetBuilder) generateImportsAttribute() *targetBuilder { // build returns the assembled *rule.Rule for the target. func (t *targetBuilder) build() *rule.Rule { r := rule.NewRule(t.kind, t.name) + if t.uuid != "" { + r.SetPrivateAttr(uuidKey, t.uuid) + } if !t.srcs.Empty() { r.SetAttr("srcs", t.srcs.Values()) } diff --git a/gazelle/python/testdata/generated_test_entrypoint/BUILD.out b/gazelle/python/testdata/generated_test_entrypoint/BUILD.out index e8e304c72b..48df0688a6 100644 --- a/gazelle/python/testdata/generated_test_entrypoint/BUILD.out +++ b/gazelle/python/testdata/generated_test_entrypoint/BUILD.out @@ -17,5 +17,8 @@ py_test( name = "generated_test_entrypoint_test", srcs = [":__test__"], main = ":__test__.py", - deps = [":__test__"], + deps = [ + ":__test__", + ":generated_test_entrypoint", + ], ) diff --git a/gazelle/python/testdata/naming_convention/__main__.py b/gazelle/python/testdata/naming_convention/__main__.py index a3afc79dcd..730755995d 100644 --- a/gazelle/python/testdata/naming_convention/__main__.py +++ b/gazelle/python/testdata/naming_convention/__main__.py @@ -13,4 +13,3 @@ # limitations under the License. # For test purposes only. -import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/naming_convention/__test__.py b/gazelle/python/testdata/naming_convention/__test__.py index a3afc79dcd..730755995d 100644 --- a/gazelle/python/testdata/naming_convention/__test__.py +++ b/gazelle/python/testdata/naming_convention/__test__.py @@ -13,4 +13,3 @@ # limitations under the License. # For test purposes only. -import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/naming_convention/dont_rename/__main__.py b/gazelle/python/testdata/naming_convention/dont_rename/__main__.py index a3afc79dcd..730755995d 100644 --- a/gazelle/python/testdata/naming_convention/dont_rename/__main__.py +++ b/gazelle/python/testdata/naming_convention/dont_rename/__main__.py @@ -13,4 +13,3 @@ # limitations under the License. # For test purposes only. -import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/naming_convention/dont_rename/__test__.py b/gazelle/python/testdata/naming_convention/dont_rename/__test__.py index a3afc79dcd..730755995d 100644 --- a/gazelle/python/testdata/naming_convention/dont_rename/__test__.py +++ b/gazelle/python/testdata/naming_convention/dont_rename/__test__.py @@ -13,4 +13,3 @@ # limitations under the License. # For test purposes only. -import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py b/gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py index a3afc79dcd..730755995d 100644 --- a/gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py +++ b/gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py @@ -13,4 +13,3 @@ # limitations under the License. # For test purposes only. -import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py b/gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py index a3afc79dcd..730755995d 100644 --- a/gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py +++ b/gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py @@ -13,4 +13,3 @@ # limitations under the License. # For test purposes only. -import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/python_target_with_test_in_name/real_test.py b/gazelle/python/testdata/python_target_with_test_in_name/real_test.py index e390866be3..2f032112ef 100644 --- a/gazelle/python/testdata/python_target_with_test_in_name/real_test.py +++ b/gazelle/python/testdata/python_target_with_test_in_name/real_test.py @@ -13,6 +13,5 @@ # limitations under the License. import boto3 -import __init__ _ = boto3 diff --git a/gazelle/python/testdata/python_target_with_test_in_name/test_reality.py b/gazelle/python/testdata/python_target_with_test_in_name/test_reality.py index a3afc79dcd..730755995d 100644 --- a/gazelle/python/testdata/python_target_with_test_in_name/test_reality.py +++ b/gazelle/python/testdata/python_target_with_test_in_name/test_reality.py @@ -13,4 +13,3 @@ # limitations under the License. # For test purposes only. -import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/sibling_imports/README.md b/gazelle/python/testdata/sibling_imports/README.md deleted file mode 100644 index e59be07634..0000000000 --- a/gazelle/python/testdata/sibling_imports/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Sibling imports - -This test case asserts that imports from sibling modules are resolved correctly. It covers 3 different types of imports in `pkg/unit_test.py` \ No newline at end of file diff --git a/gazelle/python/testdata/sibling_imports/WORKSPACE b/gazelle/python/testdata/sibling_imports/WORKSPACE deleted file mode 100644 index faff6af87a..0000000000 --- a/gazelle/python/testdata/sibling_imports/WORKSPACE +++ /dev/null @@ -1 +0,0 @@ -# This is a Bazel workspace for the Gazelle test data. diff --git a/gazelle/python/testdata/sibling_imports/pkg/BUILD.in b/gazelle/python/testdata/sibling_imports/pkg/BUILD.in deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/gazelle/python/testdata/sibling_imports/pkg/BUILD.out b/gazelle/python/testdata/sibling_imports/pkg/BUILD.out deleted file mode 100644 index edb40a8bcb..0000000000 --- a/gazelle/python/testdata/sibling_imports/pkg/BUILD.out +++ /dev/null @@ -1,29 +0,0 @@ -load("@rules_python//python:defs.bzl", "py_library", "py_test") - -py_library( - name = "pkg", - srcs = [ - "__init__.py", - "a.py", - "b.py", - ], - imports = [".."], - visibility = ["//:__subpackages__"], -) - -py_test( - name = "test_util", - srcs = ["test_util.py"], - imports = [".."], -) - -py_test( - name = "unit_test", - srcs = ["unit_test.py"], - imports = [".."], - deps = [ - ":pkg", - ":test_util", - ], -) - diff --git a/gazelle/python/testdata/sibling_imports/pkg/__init__.py b/gazelle/python/testdata/sibling_imports/pkg/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/gazelle/python/testdata/sibling_imports/pkg/a.py b/gazelle/python/testdata/sibling_imports/pkg/a.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/gazelle/python/testdata/sibling_imports/pkg/b.py b/gazelle/python/testdata/sibling_imports/pkg/b.py deleted file mode 100644 index 7095bdcfb2..0000000000 --- a/gazelle/python/testdata/sibling_imports/pkg/b.py +++ /dev/null @@ -1,2 +0,0 @@ -def run(): - pass \ No newline at end of file diff --git a/gazelle/python/testdata/sibling_imports/pkg/test_util.py b/gazelle/python/testdata/sibling_imports/pkg/test_util.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/gazelle/python/testdata/sibling_imports/pkg/unit_test.py b/gazelle/python/testdata/sibling_imports/pkg/unit_test.py deleted file mode 100644 index a3218e2ec2..0000000000 --- a/gazelle/python/testdata/sibling_imports/pkg/unit_test.py +++ /dev/null @@ -1,3 +0,0 @@ -import a -from b import run -import test_util \ No newline at end of file diff --git a/gazelle/python/testdata/sibling_imports/test.yaml b/gazelle/python/testdata/sibling_imports/test.yaml deleted file mode 100644 index ed97d539c0..0000000000 --- a/gazelle/python/testdata/sibling_imports/test.yaml +++ /dev/null @@ -1 +0,0 @@ ---- diff --git a/gazelle/python/testdata/simple_binary_with_library/__main__.py b/gazelle/python/testdata/simple_binary_with_library/__main__.py index bc7ddf0a71..730755995d 100644 --- a/gazelle/python/testdata/simple_binary_with_library/__main__.py +++ b/gazelle/python/testdata/simple_binary_with_library/__main__.py @@ -13,4 +13,3 @@ # limitations under the License. # For test purposes only. -import foo diff --git a/gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py b/gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py index bd0fe61faa..730755995d 100644 --- a/gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py +++ b/gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py @@ -13,4 +13,3 @@ # limitations under the License. # For test purposes only. -import foo.has_main.python.my_module \ No newline at end of file diff --git a/gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py b/gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py index 3c9ed1a1bd..730755995d 100644 --- a/gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py +++ b/gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py @@ -13,4 +13,3 @@ # limitations under the License. # For test purposes only. -import foo.has_test.python.my_module \ No newline at end of file diff --git a/gazelle/python/testdata/with_third_party_requirements/BUILD.out b/gazelle/python/testdata/with_third_party_requirements/BUILD.out index 2a97d8bc1e..2da7f2bd86 100644 --- a/gazelle/python/testdata/with_third_party_requirements/BUILD.out +++ b/gazelle/python/testdata/with_third_party_requirements/BUILD.out @@ -20,5 +20,5 @@ py_binary( srcs = ["__main__.py"], main = "__main__.py", visibility = ["//:__subpackages__"], - deps = ["@gazelle_python_test_baz//:pkg"], + deps = [":with_third_party_requirements"], ) From a47c6cd681b34b1ad990ed40dcc01ab5f024406a Mon Sep 17 00:00:00 2001 From: Daniel Wagner-Hall Date: Wed, 1 Feb 2023 16:23:49 +0000 Subject: [PATCH 149/234] Fix glob includes/exclues (#1038) --- python/repositories.bzl | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/python/repositories.bzl b/python/repositories.bzl index faaec64d95..e61b057d22 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -198,13 +198,24 @@ def _python_repository_impl(rctx): python_bin = "python.exe" if ("windows" in platform) else "bin/python3" glob_include = [] + glob_exclude = [ + "**/* *", # Bazel does not support spaces in file names. + # Unused shared libraries. `python` executable and the `:libpython` target + # depend on `libpython{python_version}.so.1.0`. + "lib/libpython{python_version}.so", + # static libraries + "lib/**/*.a", + # tests for the standard libraries. + "lib/python{python_version}/**/test/**", + "lib/python{python_version}/**/tests/**", + ] if rctx.attr.ignore_root_user_error: - glob_include += [ - "# These pycache files are created on first use of the associated python files.", - "# Exclude them from the glob because otherwise between the first time and second time a python toolchain is used,", - "# the definition of this filegroup will change, and depending rules will get invalidated.", - "# See https://github.com/bazelbuild/rules_python/issues/1008 for unconditionally adding these to toolchains so we can stop ignoring them.", + glob_exclude += [ + # These pycache files are created on first use of the associated python files. + # Exclude them from the glob because otherwise between the first time and second time a python toolchain is used," + # the definition of this filegroup will change, and depending rules will get invalidated." + # See https://github.com/bazelbuild/rules_python/issues/1008 for unconditionally adding these to toolchains so we can stop ignoring them." "**/__pycache__/*.pyc", "**/__pycache__/*.pyo", ] @@ -245,17 +256,7 @@ filegroup( include = {glob_include}, # Platform-agnostic filegroup can't match on all patterns. allow_empty = True, - exclude = [ - "**/* *", # Bazel does not support spaces in file names. - # Unused shared libraries. `python` executable and the `:libpython` target - # depend on `libpython{python_version}.so.1.0`. - "lib/libpython{python_version}.so", - # static libraries - "lib/**/*.a", - # tests for the standard libraries. - "lib/python{python_version}/**/test/**", - "lib/python{python_version}/**/tests/**", - ], + exclude = {glob_exclude}, ), ) @@ -321,6 +322,7 @@ py_runtime_pair( py3_runtime = ":py3_runtime", ) """.format( + glob_exclude = repr(glob_exclude), glob_include = repr(glob_include), python_path = python_bin, python_version = python_short_version, From 0e55ced05fa495760d0d804d21c83fa502c0a50d Mon Sep 17 00:00:00 2001 From: Zhongpeng Lin Date: Wed, 1 Feb 2023 19:17:20 -0800 Subject: [PATCH 150/234] Fixed glob includes for ignore_root_user_error (#1037) --- .bazelci/presubmit.yml | 21 +++++++++++++++++++++ tests/ignore_root_user_error/.bazelrc | 5 +++++ tests/ignore_root_user_error/.gitignore | 1 + tests/ignore_root_user_error/BUILD.bazel | 7 +++++++ tests/ignore_root_user_error/README.md | 2 ++ tests/ignore_root_user_error/WORKSPACE | 12 ++++++++++++ tests/ignore_root_user_error/foo_test.py | 13 +++++++++++++ 7 files changed, 61 insertions(+) create mode 100644 tests/ignore_root_user_error/.bazelrc create mode 100644 tests/ignore_root_user_error/.gitignore create mode 100644 tests/ignore_root_user_error/BUILD.bazel create mode 100644 tests/ignore_root_user_error/README.md create mode 100644 tests/ignore_root_user_error/WORKSPACE create mode 100644 tests/ignore_root_user_error/foo_test.py diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index a4003604d0..76f9d8b5aa 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -273,3 +273,24 @@ tasks: name: pip_repository_entry_points integration tests on Windows working_directory: tests/pip_repository_entry_points platform: windows + + integration_test_ignore_root_user_error_ubuntu: + <<: *reusable_build_test_all + name: ignore_root_user_error integration tests on Ubuntu + working_directory: tests/ignore_root_user_error + platform: ubuntu2004 + integration_test_ignore_root_user_error_debian: + <<: *reusable_build_test_all + name: ignore_root_user_error integration tests on Debian + working_directory: tests/ignore_root_user_error + platform: debian11 + integration_test_ignore_root_user_error_macos: + <<: *reusable_build_test_all + name: ignore_root_user_error integration tests on macOS + working_directory: tests/ignore_root_user_error + platform: macos + integration_test_ignore_root_user_error_windows: + <<: *reusable_build_test_all + name: ignore_root_user_error integration tests on Windows + working_directory: tests/ignore_root_user_error + platform: windows diff --git a/tests/ignore_root_user_error/.bazelrc b/tests/ignore_root_user_error/.bazelrc new file mode 100644 index 0000000000..f23315a7a1 --- /dev/null +++ b/tests/ignore_root_user_error/.bazelrc @@ -0,0 +1,5 @@ +test --test_output=errors + +# Windows requires these for multi-python support: +build --enable_runfiles +startup --windows_enable_symlinks diff --git a/tests/ignore_root_user_error/.gitignore b/tests/ignore_root_user_error/.gitignore new file mode 100644 index 0000000000..ac51a054d2 --- /dev/null +++ b/tests/ignore_root_user_error/.gitignore @@ -0,0 +1 @@ +bazel-* diff --git a/tests/ignore_root_user_error/BUILD.bazel b/tests/ignore_root_user_error/BUILD.bazel new file mode 100644 index 0000000000..f907624767 --- /dev/null +++ b/tests/ignore_root_user_error/BUILD.bazel @@ -0,0 +1,7 @@ +load("@rules_python//python:defs.bzl", "py_test") + +py_test( + name = "foo_test", + srcs = ["foo_test.py"], + visibility = ["//visibility:public"], +) diff --git a/tests/ignore_root_user_error/README.md b/tests/ignore_root_user_error/README.md new file mode 100644 index 0000000000..47da5eb9ad --- /dev/null +++ b/tests/ignore_root_user_error/README.md @@ -0,0 +1,2 @@ +# ignore_root_user_errors +There are cases when we have to run Python targets with root, e.g., in Docker containers, requiring setting `ignore_root_user_error = True` when registering Python toolchain. This test makes sure that rules_python works in this case. \ No newline at end of file diff --git a/tests/ignore_root_user_error/WORKSPACE b/tests/ignore_root_user_error/WORKSPACE new file mode 100644 index 0000000000..d2f4d6ec3a --- /dev/null +++ b/tests/ignore_root_user_error/WORKSPACE @@ -0,0 +1,12 @@ +local_repository( + name = "rules_python", + path = "../..", +) + +load("@rules_python//python:repositories.bzl", "python_register_toolchains") + +python_register_toolchains( + name = "python39", + ignore_root_user_error = True, + python_version = "3.9", +) diff --git a/tests/ignore_root_user_error/foo_test.py b/tests/ignore_root_user_error/foo_test.py new file mode 100644 index 0000000000..724cdcb69a --- /dev/null +++ b/tests/ignore_root_user_error/foo_test.py @@ -0,0 +1,13 @@ +# Copyright 2019 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. From 2607797b1a33b5a5e38f5c41cdd28bb6162c0bbe Mon Sep 17 00:00:00 2001 From: Simon Stewart Date: Fri, 3 Feb 2023 00:26:23 +0000 Subject: [PATCH 151/234] Pass cpp flags through in all cases to repository rule compilations (#1040) Remove a line that prevents local builds of lxml to fail --- python/pip_install/pip_repository.bzl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl index 511da349c8..d5d93f3e9d 100644 --- a/python/pip_install/pip_repository.bzl +++ b/python/pip_install/pip_repository.bzl @@ -93,10 +93,6 @@ def _get_xcode_location_cflags(rctx): if not rctx.os.name.lower().startswith("mac os"): return [] - # Only update the location when using a hermetic toolchain. - if not is_standalone_interpreter(rctx, rctx.attr.python_interpreter_target): - return [] - # Locate xcode-select xcode_select = rctx.which("xcode-select") From b832d501e9f4514e39d07358de636ab0622dd342 Mon Sep 17 00:00:00 2001 From: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Date: Fri, 3 Feb 2023 12:15:49 -0800 Subject: [PATCH 152/234] feat: add logic from #1029 back with fix (#1039) --- gazelle/python/generate.go | 51 ++++++++----------- gazelle/python/resolve.go | 11 ---- gazelle/python/target.go | 27 ++++------ .../generated_test_entrypoint/BUILD.out | 5 +- .../testdata/naming_convention/__main__.py | 1 + .../testdata/naming_convention/__test__.py | 1 + .../naming_convention/dont_rename/__main__.py | 1 + .../naming_convention/dont_rename/__test__.py | 1 + .../resolve_conflict/__main__.py | 1 + .../resolve_conflict/__test__.py | 1 + .../real_test.py | 1 + .../test_reality.py | 1 + .../python/testdata/sibling_imports/README.md | 3 ++ .../python/testdata/sibling_imports/WORKSPACE | 1 + .../testdata/sibling_imports/pkg/BUILD.in | 0 .../testdata/sibling_imports/pkg/BUILD.out | 29 +++++++++++ .../testdata/sibling_imports/pkg/__init__.py | 0 .../python/testdata/sibling_imports/pkg/a.py | 0 .../python/testdata/sibling_imports/pkg/b.py | 2 + .../testdata/sibling_imports/pkg/test_util.py | 0 .../testdata/sibling_imports/pkg/unit_test.py | 3 ++ .../python/testdata/sibling_imports/test.yaml | 1 + .../simple_binary_with_library/__main__.py | 1 + .../simple_test_with_conftest/bar/BUILD.in | 1 + .../simple_test_with_conftest/bar/BUILD.out | 30 +++++++++++ .../simple_test_with_conftest/bar/__init__.py | 17 +++++++ .../simple_test_with_conftest/bar/__test__.py | 26 ++++++++++ .../simple_test_with_conftest/bar/bar.py | 17 +++++++ .../simple_test_with_conftest/bar/conftest.py | 13 +++++ .../subdir_sources/foo/has_main/__main__.py | 1 + .../subdir_sources/foo/has_test/__test__.py | 1 + .../with_third_party_requirements/BUILD.out | 2 +- 32 files changed, 188 insertions(+), 62 deletions(-) create mode 100644 gazelle/python/testdata/sibling_imports/README.md create mode 100644 gazelle/python/testdata/sibling_imports/WORKSPACE create mode 100644 gazelle/python/testdata/sibling_imports/pkg/BUILD.in create mode 100644 gazelle/python/testdata/sibling_imports/pkg/BUILD.out create mode 100644 gazelle/python/testdata/sibling_imports/pkg/__init__.py create mode 100644 gazelle/python/testdata/sibling_imports/pkg/a.py create mode 100644 gazelle/python/testdata/sibling_imports/pkg/b.py create mode 100644 gazelle/python/testdata/sibling_imports/pkg/test_util.py create mode 100644 gazelle/python/testdata/sibling_imports/pkg/unit_test.py create mode 100644 gazelle/python/testdata/sibling_imports/test.yaml create mode 100644 gazelle/python/testdata/simple_test_with_conftest/bar/BUILD.in create mode 100644 gazelle/python/testdata/simple_test_with_conftest/bar/BUILD.out create mode 100644 gazelle/python/testdata/simple_test_with_conftest/bar/__init__.py create mode 100644 gazelle/python/testdata/simple_test_with_conftest/bar/__test__.py create mode 100644 gazelle/python/testdata/simple_test_with_conftest/bar/bar.py create mode 100644 gazelle/python/testdata/simple_test_with_conftest/bar/conftest.py diff --git a/gazelle/python/generate.go b/gazelle/python/generate.go index 4ebb40f6bb..3d63124028 100644 --- a/gazelle/python/generate.go +++ b/gazelle/python/generate.go @@ -76,6 +76,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes pyLibraryFilenames := treeset.NewWith(godsutils.StringComparator) pyTestFilenames := treeset.NewWith(godsutils.StringComparator) + pyFileNames := treeset.NewWith(godsutils.StringComparator) // hasPyBinary controls whether a py_binary target should be generated for // this package or not. @@ -92,16 +93,19 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes continue } ext := filepath.Ext(f) - if !hasPyBinary && f == pyBinaryEntrypointFilename { - hasPyBinary = true - } else if !hasPyTestEntryPointFile && f == pyTestEntrypointFilename { - hasPyTestEntryPointFile = true - } else if f == conftestFilename { - hasConftestFile = true - } else if strings.HasSuffix(f, "_test.py") || (strings.HasPrefix(f, "test_") && ext == ".py") { - pyTestFilenames.Add(f) - } else if ext == ".py" { - pyLibraryFilenames.Add(f) + if ext == ".py" { + pyFileNames.Add(f) + if !hasPyBinary && f == pyBinaryEntrypointFilename { + hasPyBinary = true + } else if !hasPyTestEntryPointFile && f == pyTestEntrypointFilename { + hasPyTestEntryPointFile = true + } else if f == conftestFilename { + hasConftestFile = true + } else if strings.HasSuffix(f, "_test.py") || strings.HasPrefix(f, "test_") { + pyTestFilenames.Add(f) + } else { + pyLibraryFilenames.Add(f) + } } } @@ -223,8 +227,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } } - pyLibrary = newTargetBuilder(pyLibraryKind, pyLibraryTargetName, pythonProjectRoot, args.Rel, pyLibraryFilenames.Union(pyTestFilenames)). - setUUID(label.New("", args.Rel, pyLibraryTargetName).String()). + pyLibrary = newTargetBuilder(pyLibraryKind, pyLibraryTargetName, pythonProjectRoot, args.Rel, pyFileNames). addVisibility(visibility). addSrcs(pyLibraryFilenames). addModuleDependencies(deps). @@ -260,17 +263,13 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } } - pyBinaryTarget := newTargetBuilder(pyBinaryKind, pyBinaryTargetName, pythonProjectRoot, args.Rel, pyLibraryFilenames.Union(pyTestFilenames)). + pyBinaryTarget := newTargetBuilder(pyBinaryKind, pyBinaryTargetName, pythonProjectRoot, args.Rel, pyFileNames). setMain(pyBinaryEntrypointFilename). addVisibility(visibility). addSrc(pyBinaryEntrypointFilename). addModuleDependencies(deps). generateImportsAttribute() - if pyLibrary != nil { - pyBinaryTarget.addModuleDependency(module{Name: pyLibrary.PrivateAttr(uuidKey).(string)}) - } - pyBinary := pyBinaryTarget.build() result.Gen = append(result.Gen, pyBinary) @@ -300,8 +299,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } } - conftestTarget := newTargetBuilder(pyLibraryKind, conftestTargetname, pythonProjectRoot, args.Rel, pyLibraryFilenames.Union(pyTestFilenames)). - setUUID(label.New("", args.Rel, conftestTargetname).String()). + conftestTarget := newTargetBuilder(pyLibraryKind, conftestTargetname, pythonProjectRoot, args.Rel, pyFileNames). addSrc(conftestFilename). addModuleDependencies(deps). addVisibility(visibility). @@ -315,8 +313,8 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } var pyTestTargets []*targetBuilder - newPyTestTargetBuilder := func(pyTestFilenames *treeset.Set, pyTestTargetName string) *targetBuilder { - deps, err := parser.parse(pyTestFilenames) + newPyTestTargetBuilder := func(srcs *treeset.Set, pyTestTargetName string) *targetBuilder { + deps, err := parser.parse(srcs) if err != nil { log.Fatalf("ERROR: %v\n", err) } @@ -336,8 +334,8 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } } } - return newTargetBuilder(pyTestKind, pyTestTargetName, pythonProjectRoot, args.Rel, pyLibraryFilenames.Union(pyTestFilenames)). - addSrcs(pyTestFilenames). + return newTargetBuilder(pyTestKind, pyTestTargetName, pythonProjectRoot, args.Rel, pyFileNames). + addSrcs(srcs). addModuleDependencies(deps). generateImportsAttribute() } @@ -371,14 +369,9 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } for _, pyTestTarget := range pyTestTargets { - if pyLibrary != nil { - pyTestTarget.addModuleDependency(module{Name: pyLibrary.PrivateAttr(uuidKey).(string)}) - } - if conftest != nil { - pyTestTarget.addModuleDependency(module{Name: conftest.PrivateAttr(uuidKey).(string)}) + pyTestTarget.addModuleDependency(module{Name: strings.TrimSuffix(conftestFilename, ".py")}) } - pyTest := pyTestTarget.build() result.Gen = append(result.Gen, pyTest) diff --git a/gazelle/python/resolve.go b/gazelle/python/resolve.go index 607776aee3..46014e50ec 100644 --- a/gazelle/python/resolve.go +++ b/gazelle/python/resolve.go @@ -39,10 +39,6 @@ const ( // resolvedDepsKey is the attribute key used to pass dependencies that don't // need to be resolved by the dependency resolver in the Resolver step. resolvedDepsKey = "_gazelle_python_resolved_deps" - // uuidKey is the attribute key used to uniquely identify a py_library - // target that should be imported by a py_test or py_binary in the same - // Bazel package. - uuidKey = "_gazelle_python_library_uuid" ) // Resolver satisfies the resolve.Resolver interface. It resolves dependencies @@ -71,13 +67,6 @@ func (py *Resolver) Imports(c *config.Config, r *rule.Rule, f *rule.File) []reso provides = append(provides, provide) } } - if r.PrivateAttr(uuidKey) != nil { - provide := resolve.ImportSpec{ - Lang: languageName, - Imp: r.PrivateAttr(uuidKey).(string), - } - provides = append(provides, provide) - } if len(provides) == 0 { return nil } diff --git a/gazelle/python/target.go b/gazelle/python/target.go index 69711ce643..fdc99fc68c 100644 --- a/gazelle/python/target.go +++ b/gazelle/python/target.go @@ -15,12 +15,11 @@ package python import ( - "path/filepath" - "github.com/bazelbuild/bazel-gazelle/config" "github.com/bazelbuild/bazel-gazelle/rule" "github.com/emirpasic/gods/sets/treeset" godsutils "github.com/emirpasic/gods/utils" + "path/filepath" ) // targetBuilder builds targets to be generated by Gazelle. @@ -29,7 +28,6 @@ type targetBuilder struct { name string pythonProjectRoot string bzlPackage string - uuid string srcs *treeset.Set siblingSrcs *treeset.Set deps *treeset.Set @@ -55,15 +53,6 @@ func newTargetBuilder(kind, name, pythonProjectRoot, bzlPackage string, siblingS } } -// setUUID sets the given UUID for the target. It's used to index the generated -// target based on this value in addition to the other ways the targets can be -// imported. py_{binary,test} targets in the same Bazel package can add a -// virtual dependency to this UUID that gets resolved in the Resolver interface. -func (t *targetBuilder) setUUID(uuid string) *targetBuilder { - t.uuid = uuid - return t -} - // addSrc adds a single src to the target. func (t *targetBuilder) addSrc(src string) *targetBuilder { t.srcs.Add(src) @@ -81,9 +70,16 @@ func (t *targetBuilder) addSrcs(srcs *treeset.Set) *targetBuilder { // addModuleDependency adds a single module dep to the target. func (t *targetBuilder) addModuleDependency(dep module) *targetBuilder { - if dep.Name+".py" == filepath.Base(dep.Filepath) || !t.siblingSrcs.Contains(dep.Name+".py") { - t.deps.Add(dep) + fileName := dep.Name + ".py" + if dep.From != "" { + fileName = dep.From + ".py" } + if t.siblingSrcs.Contains(fileName) && fileName != filepath.Base(dep.Filepath) { + // importing another module from the same package, converting to absolute imports to make + // dependency resolution easier + dep.Name = importSpecFromSrc(t.pythonProjectRoot, t.bzlPackage, fileName).Imp + } + t.deps.Add(dep) return t } @@ -138,9 +134,6 @@ func (t *targetBuilder) generateImportsAttribute() *targetBuilder { // build returns the assembled *rule.Rule for the target. func (t *targetBuilder) build() *rule.Rule { r := rule.NewRule(t.kind, t.name) - if t.uuid != "" { - r.SetPrivateAttr(uuidKey, t.uuid) - } if !t.srcs.Empty() { r.SetAttr("srcs", t.srcs.Values()) } diff --git a/gazelle/python/testdata/generated_test_entrypoint/BUILD.out b/gazelle/python/testdata/generated_test_entrypoint/BUILD.out index 48df0688a6..e8e304c72b 100644 --- a/gazelle/python/testdata/generated_test_entrypoint/BUILD.out +++ b/gazelle/python/testdata/generated_test_entrypoint/BUILD.out @@ -17,8 +17,5 @@ py_test( name = "generated_test_entrypoint_test", srcs = [":__test__"], main = ":__test__.py", - deps = [ - ":__test__", - ":generated_test_entrypoint", - ], + deps = [":__test__"], ) diff --git a/gazelle/python/testdata/naming_convention/__main__.py b/gazelle/python/testdata/naming_convention/__main__.py index 730755995d..a3afc79dcd 100644 --- a/gazelle/python/testdata/naming_convention/__main__.py +++ b/gazelle/python/testdata/naming_convention/__main__.py @@ -13,3 +13,4 @@ # limitations under the License. # For test purposes only. +import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/naming_convention/__test__.py b/gazelle/python/testdata/naming_convention/__test__.py index 730755995d..a3afc79dcd 100644 --- a/gazelle/python/testdata/naming_convention/__test__.py +++ b/gazelle/python/testdata/naming_convention/__test__.py @@ -13,3 +13,4 @@ # limitations under the License. # For test purposes only. +import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/naming_convention/dont_rename/__main__.py b/gazelle/python/testdata/naming_convention/dont_rename/__main__.py index 730755995d..a3afc79dcd 100644 --- a/gazelle/python/testdata/naming_convention/dont_rename/__main__.py +++ b/gazelle/python/testdata/naming_convention/dont_rename/__main__.py @@ -13,3 +13,4 @@ # limitations under the License. # For test purposes only. +import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/naming_convention/dont_rename/__test__.py b/gazelle/python/testdata/naming_convention/dont_rename/__test__.py index 730755995d..a3afc79dcd 100644 --- a/gazelle/python/testdata/naming_convention/dont_rename/__test__.py +++ b/gazelle/python/testdata/naming_convention/dont_rename/__test__.py @@ -13,3 +13,4 @@ # limitations under the License. # For test purposes only. +import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py b/gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py index 730755995d..a3afc79dcd 100644 --- a/gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py +++ b/gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py @@ -13,3 +13,4 @@ # limitations under the License. # For test purposes only. +import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py b/gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py index 730755995d..a3afc79dcd 100644 --- a/gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py +++ b/gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py @@ -13,3 +13,4 @@ # limitations under the License. # For test purposes only. +import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/python_target_with_test_in_name/real_test.py b/gazelle/python/testdata/python_target_with_test_in_name/real_test.py index 2f032112ef..e390866be3 100644 --- a/gazelle/python/testdata/python_target_with_test_in_name/real_test.py +++ b/gazelle/python/testdata/python_target_with_test_in_name/real_test.py @@ -13,5 +13,6 @@ # limitations under the License. import boto3 +import __init__ _ = boto3 diff --git a/gazelle/python/testdata/python_target_with_test_in_name/test_reality.py b/gazelle/python/testdata/python_target_with_test_in_name/test_reality.py index 730755995d..a3afc79dcd 100644 --- a/gazelle/python/testdata/python_target_with_test_in_name/test_reality.py +++ b/gazelle/python/testdata/python_target_with_test_in_name/test_reality.py @@ -13,3 +13,4 @@ # limitations under the License. # For test purposes only. +import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/sibling_imports/README.md b/gazelle/python/testdata/sibling_imports/README.md new file mode 100644 index 0000000000..e59be07634 --- /dev/null +++ b/gazelle/python/testdata/sibling_imports/README.md @@ -0,0 +1,3 @@ +# Sibling imports + +This test case asserts that imports from sibling modules are resolved correctly. It covers 3 different types of imports in `pkg/unit_test.py` \ No newline at end of file diff --git a/gazelle/python/testdata/sibling_imports/WORKSPACE b/gazelle/python/testdata/sibling_imports/WORKSPACE new file mode 100644 index 0000000000..faff6af87a --- /dev/null +++ b/gazelle/python/testdata/sibling_imports/WORKSPACE @@ -0,0 +1 @@ +# This is a Bazel workspace for the Gazelle test data. diff --git a/gazelle/python/testdata/sibling_imports/pkg/BUILD.in b/gazelle/python/testdata/sibling_imports/pkg/BUILD.in new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/python/testdata/sibling_imports/pkg/BUILD.out b/gazelle/python/testdata/sibling_imports/pkg/BUILD.out new file mode 100644 index 0000000000..edb40a8bcb --- /dev/null +++ b/gazelle/python/testdata/sibling_imports/pkg/BUILD.out @@ -0,0 +1,29 @@ +load("@rules_python//python:defs.bzl", "py_library", "py_test") + +py_library( + name = "pkg", + srcs = [ + "__init__.py", + "a.py", + "b.py", + ], + imports = [".."], + visibility = ["//:__subpackages__"], +) + +py_test( + name = "test_util", + srcs = ["test_util.py"], + imports = [".."], +) + +py_test( + name = "unit_test", + srcs = ["unit_test.py"], + imports = [".."], + deps = [ + ":pkg", + ":test_util", + ], +) + diff --git a/gazelle/python/testdata/sibling_imports/pkg/__init__.py b/gazelle/python/testdata/sibling_imports/pkg/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/python/testdata/sibling_imports/pkg/a.py b/gazelle/python/testdata/sibling_imports/pkg/a.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/python/testdata/sibling_imports/pkg/b.py b/gazelle/python/testdata/sibling_imports/pkg/b.py new file mode 100644 index 0000000000..7095bdcfb2 --- /dev/null +++ b/gazelle/python/testdata/sibling_imports/pkg/b.py @@ -0,0 +1,2 @@ +def run(): + pass \ No newline at end of file diff --git a/gazelle/python/testdata/sibling_imports/pkg/test_util.py b/gazelle/python/testdata/sibling_imports/pkg/test_util.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/python/testdata/sibling_imports/pkg/unit_test.py b/gazelle/python/testdata/sibling_imports/pkg/unit_test.py new file mode 100644 index 0000000000..a3218e2ec2 --- /dev/null +++ b/gazelle/python/testdata/sibling_imports/pkg/unit_test.py @@ -0,0 +1,3 @@ +import a +from b import run +import test_util \ No newline at end of file diff --git a/gazelle/python/testdata/sibling_imports/test.yaml b/gazelle/python/testdata/sibling_imports/test.yaml new file mode 100644 index 0000000000..ed97d539c0 --- /dev/null +++ b/gazelle/python/testdata/sibling_imports/test.yaml @@ -0,0 +1 @@ +--- diff --git a/gazelle/python/testdata/simple_binary_with_library/__main__.py b/gazelle/python/testdata/simple_binary_with_library/__main__.py index 730755995d..bc7ddf0a71 100644 --- a/gazelle/python/testdata/simple_binary_with_library/__main__.py +++ b/gazelle/python/testdata/simple_binary_with_library/__main__.py @@ -13,3 +13,4 @@ # limitations under the License. # For test purposes only. +import foo diff --git a/gazelle/python/testdata/simple_test_with_conftest/bar/BUILD.in b/gazelle/python/testdata/simple_test_with_conftest/bar/BUILD.in new file mode 100644 index 0000000000..3f2beb3147 --- /dev/null +++ b/gazelle/python/testdata/simple_test_with_conftest/bar/BUILD.in @@ -0,0 +1 @@ +load("@rules_python//python:defs.bzl", "py_library") diff --git a/gazelle/python/testdata/simple_test_with_conftest/bar/BUILD.out b/gazelle/python/testdata/simple_test_with_conftest/bar/BUILD.out new file mode 100644 index 0000000000..e42c4998b1 --- /dev/null +++ b/gazelle/python/testdata/simple_test_with_conftest/bar/BUILD.out @@ -0,0 +1,30 @@ +load("@rules_python//python:defs.bzl", "py_library", "py_test") + +py_library( + name = "bar", + srcs = [ + "__init__.py", + "bar.py", + ], + imports = [".."], + visibility = ["//:__subpackages__"], +) + +py_library( + name = "conftest", + testonly = True, + srcs = ["conftest.py"], + imports = [".."], + visibility = ["//:__subpackages__"], +) + +py_test( + name = "bar_test", + srcs = ["__test__.py"], + imports = [".."], + main = "__test__.py", + deps = [ + ":bar", + ":conftest", + ], +) diff --git a/gazelle/python/testdata/simple_test_with_conftest/bar/__init__.py b/gazelle/python/testdata/simple_test_with_conftest/bar/__init__.py new file mode 100644 index 0000000000..3f0275e179 --- /dev/null +++ b/gazelle/python/testdata/simple_test_with_conftest/bar/__init__.py @@ -0,0 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from bar import bar + +_ = bar diff --git a/gazelle/python/testdata/simple_test_with_conftest/bar/__test__.py b/gazelle/python/testdata/simple_test_with_conftest/bar/__test__.py new file mode 100644 index 0000000000..00c4c28247 --- /dev/null +++ b/gazelle/python/testdata/simple_test_with_conftest/bar/__test__.py @@ -0,0 +1,26 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest + +from __init__ import bar + + +class BarTest(unittest.TestCase): + def test_bar(self): + self.assertEqual("bar", bar()) + + +if __name__ == "__main__": + unittest.main() diff --git a/gazelle/python/testdata/simple_test_with_conftest/bar/bar.py b/gazelle/python/testdata/simple_test_with_conftest/bar/bar.py new file mode 100644 index 0000000000..ba6a62db30 --- /dev/null +++ b/gazelle/python/testdata/simple_test_with_conftest/bar/bar.py @@ -0,0 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +def bar(): + return "bar" diff --git a/gazelle/python/testdata/simple_test_with_conftest/bar/conftest.py b/gazelle/python/testdata/simple_test_with_conftest/bar/conftest.py new file mode 100644 index 0000000000..41010956cf --- /dev/null +++ b/gazelle/python/testdata/simple_test_with_conftest/bar/conftest.py @@ -0,0 +1,13 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py b/gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py index 730755995d..bd0fe61faa 100644 --- a/gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py +++ b/gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py @@ -13,3 +13,4 @@ # limitations under the License. # For test purposes only. +import foo.has_main.python.my_module \ No newline at end of file diff --git a/gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py b/gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py index 730755995d..3c9ed1a1bd 100644 --- a/gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py +++ b/gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py @@ -13,3 +13,4 @@ # limitations under the License. # For test purposes only. +import foo.has_test.python.my_module \ No newline at end of file diff --git a/gazelle/python/testdata/with_third_party_requirements/BUILD.out b/gazelle/python/testdata/with_third_party_requirements/BUILD.out index 2da7f2bd86..2a97d8bc1e 100644 --- a/gazelle/python/testdata/with_third_party_requirements/BUILD.out +++ b/gazelle/python/testdata/with_third_party_requirements/BUILD.out @@ -20,5 +20,5 @@ py_binary( srcs = ["__main__.py"], main = "__main__.py", visibility = ["//:__subpackages__"], - deps = [":with_third_party_requirements"], + deps = ["@gazelle_python_test_baz//:pkg"], ) From 7948858daa60ab957368405103f58e711a3f7404 Mon Sep 17 00:00:00 2001 From: Zhongpeng Lin Date: Sun, 5 Feb 2023 18:07:42 -0800 Subject: [PATCH 153/234] clean up UUID (#1028) --- gazelle/deps.bzl | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/gazelle/deps.bzl b/gazelle/deps.bzl index 9ecb0c3436..357944302c 100644 --- a/gazelle/deps.bzl +++ b/gazelle/deps.bzl @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -"This file managed by `bazel run //:update_go_deps`" +"This file managed by `bazel run //:gazelle_update_repos`" load("@bazel_gazelle//:deps.bzl", _go_repository = "go_repository") @@ -149,12 +149,6 @@ def gazelle_deps(): sum = "h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=", version = "v0.5.9", ) - go_repository( - name = "com_github_google_uuid", - importpath = "github.com/google/uuid", - sum = "h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=", - version = "v1.3.0", - ) go_repository( name = "com_github_pelletier_go_toml", importpath = "github.com/pelletier/go-toml", From 8984efd76ebad434d1c32d65a0c4514948ef25fc Mon Sep 17 00:00:00 2001 From: Zhongpeng Lin Date: Mon, 6 Feb 2023 10:56:05 -0800 Subject: [PATCH 154/234] Use go_test to verify manifest (#1044) --- gazelle/manifest/defs.bzl | 21 ++++-------- gazelle/manifest/test/BUILD.bazel | 18 ++--------- gazelle/manifest/test/run.sh | 25 --------------- gazelle/manifest/test/test.go | 53 ++++++++++--------------------- 4 files changed, 25 insertions(+), 92 deletions(-) delete mode 100755 gazelle/manifest/test/run.sh diff --git a/gazelle/manifest/defs.bzl b/gazelle/manifest/defs.bzl index 8540c0e310..78e0c272ac 100644 --- a/gazelle/manifest/defs.bzl +++ b/gazelle/manifest/defs.bzl @@ -16,7 +16,7 @@ for updating and testing the Gazelle manifest file. """ -load("@io_bazel_rules_go//go:def.bzl", "GoSource", "go_binary") +load("@io_bazel_rules_go//go:def.bzl", "GoSource", "go_binary", "go_test") def gazelle_python_manifest( name, @@ -81,31 +81,22 @@ def gazelle_python_manifest( tags = ["manual"], ) - test_binary = "_{}_test_bin".format(name) - - go_binary( - name = test_binary, - embed = [Label("//manifest/test:test_lib")], - visibility = ["//visibility:private"], - ) - - native.sh_test( + go_test( name = "{}.test".format(name), - srcs = [Label("//manifest/test:run.sh")], + srcs = [Label("//manifest/test:test.go")], data = [ - ":{}".format(test_binary), manifest, requirements, manifest_generator_hash, ], env = { - "_TEST_BINARY": "$(rootpath :{})".format(test_binary), "_TEST_MANIFEST": "$(rootpath {})".format(manifest), "_TEST_MANIFEST_GENERATOR_HASH": "$(rootpath {})".format(manifest_generator_hash), "_TEST_REQUIREMENTS": "$(rootpath {})".format(requirements), }, - visibility = ["//visibility:private"], - timeout = "short", + rundir = ".", + deps = [Label("//manifest")], + size = "small", ) native.filegroup( diff --git a/gazelle/manifest/test/BUILD.bazel b/gazelle/manifest/test/BUILD.bazel index c8b28286f3..28c6c548d9 100644 --- a/gazelle/manifest/test/BUILD.bazel +++ b/gazelle/manifest/test/BUILD.bazel @@ -1,20 +1,6 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") +# gazelle:ignore -go_library( - name = "test_lib", - srcs = ["test.go"], - importpath = "github.com/bazelbuild/rules_python/gazelle/manifest/test", - visibility = ["//visibility:public"], - deps = ["//manifest"], -) - -go_binary( - name = "test", - embed = [":test_lib"], - visibility = ["//visibility:public"], -) - -exports_files(["run.sh"]) +exports_files(["test.go"]) filegroup( name = "distribution", diff --git a/gazelle/manifest/test/run.sh b/gazelle/manifest/test/run.sh deleted file mode 100755 index 95efef009d..0000000000 --- a/gazelle/manifest/test/run.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash -# Copyright 2023 The Bazel Authors. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -# This file exists to allow passing the runfile paths to the Go program via -# environment variables. - -set -o errexit -o nounset - -"${_TEST_BINARY}" \ - --manifest-generator-hash "${_TEST_MANIFEST_GENERATOR_HASH}" \ - --requirements "${_TEST_REQUIREMENTS}" \ - --manifest "${_TEST_MANIFEST}" diff --git a/gazelle/manifest/test/test.go b/gazelle/manifest/test/test.go index ae9fdfe0d6..72cb260d4d 100644 --- a/gazelle/manifest/test/test.go +++ b/gazelle/manifest/test/test.go @@ -13,85 +13,66 @@ // limitations under the License. /* -test.go is a program that asserts the Gazelle YAML manifest is up-to-date in +test.go is a unit test that asserts the Gazelle YAML manifest is up-to-date in regards to the requirements.txt. It re-hashes the requirements.txt and compares it to the recorded one in the existing generated Gazelle manifest. */ -package main +package test import ( - "flag" - "log" "os" "path/filepath" + "testing" "github.com/bazelbuild/rules_python/gazelle/manifest" ) -func main() { - var manifestGeneratorHashPath string - var requirementsPath string - var manifestPath string - flag.StringVar( - &manifestGeneratorHashPath, - "manifest-generator-hash", - "", - "The file containing the hash for the source code of the manifest generator."+ - "This is important to force manifest updates when the generator logic changes.") - flag.StringVar( - &requirementsPath, - "requirements", - "", - "The requirements.txt file.") - flag.StringVar( - &manifestPath, - "manifest", - "", - "The manifest YAML file.") - flag.Parse() - +func TestGazelleManifestIsUpdated(t *testing.T) { + requirementsPath := os.Getenv("_TEST_REQUIREMENTS") if requirementsPath == "" { - log.Fatalln("ERROR: --requirements must be set") + t.Fatalf("_TEST_REQUIREMENTS must be set") } + manifestPath := os.Getenv("_TEST_MANIFEST") if manifestPath == "" { - log.Fatalln("ERROR: --manifest must be set") + t.Fatalf("_TEST_MANIFEST must be set") } manifestFile := new(manifest.File) if err := manifestFile.Decode(manifestPath); err != nil { - log.Fatalf("ERROR: %v\n", err) + t.Fatalf("decoding manifest file: %v", err) } if manifestFile.Integrity == "" { - log.Fatalln("ERROR: failed to find the Gazelle manifest file integrity") + t.Fatal("failed to find the Gazelle manifest file integrity") } + manifestGeneratorHashPath := os.Getenv("_TEST_MANIFEST_GENERATOR_HASH") manifestGeneratorHash, err := os.Open(manifestGeneratorHashPath) if err != nil { - log.Fatalf("ERROR: %v\n", err) + t.Fatalf("opening %q: %v", manifestGeneratorHashPath, err) } defer manifestGeneratorHash.Close() requirements, err := os.Open(requirementsPath) if err != nil { - log.Fatalf("ERROR: %v\n", err) + t.Fatalf("opening %q: %v", requirementsPath, err) } defer requirements.Close() valid, err := manifestFile.VerifyIntegrity(manifestGeneratorHash, requirements) if err != nil { - log.Fatalf("ERROR: %v\n", err) + t.Fatalf("verifying integrity: %v", err) } if !valid { manifestRealpath, err := filepath.EvalSymlinks(manifestPath) if err != nil { - log.Fatalf("ERROR: %v\n", err) + t.Fatalf("evaluating symlink %q: %v", manifestPath, err) } - log.Fatalf( - "ERROR: %q is out-of-date. Follow the update instructions in that file to resolve this.\n", + t.Errorf( + "%q is out-of-date. Follow the update instructions in that file to resolve this", manifestRealpath) } } From e7b51d7e557a2a5a244c58a81f77b5ab090f4973 Mon Sep 17 00:00:00 2001 From: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Date: Mon, 6 Feb 2023 17:58:03 -0800 Subject: [PATCH 155/234] fix: move coverage pkg to end of sys.path to avoid collisions (#1045) * fix: move coverage to end of sys.path when running pip-compile Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: generic fix for getting the coverage package right Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --------- Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- python/private/BUILD.bazel | 1 + python/private/coverage.patch | 15 +++++++++++++++ python/private/coverage_deps.bzl | 4 ++++ 3 files changed, 20 insertions(+) create mode 100644 python/private/coverage.patch diff --git a/python/private/BUILD.bazel b/python/private/BUILD.bazel index 811f28599f..f2e1c9b8bc 100644 --- a/python/private/BUILD.bazel +++ b/python/private/BUILD.bazel @@ -36,6 +36,7 @@ filegroup( # on Skylib.) exports_files( [ + "coverage.patch", "py_package.bzl", "py_wheel.bzl", "reexports.bzl", diff --git a/python/private/coverage.patch b/python/private/coverage.patch new file mode 100644 index 0000000000..4cab60cddc --- /dev/null +++ b/python/private/coverage.patch @@ -0,0 +1,15 @@ +# Because of how coverage is run, the current directory is the first in +# sys.path. This is a problem for the tests, because they may import a module of +# the same name as a module in the current directory. +diff --git a/coverage/cmdline.py b/coverage/cmdline.py +index dbf66e0a..780505ac 100644 +--- a/coverage/cmdline.py ++++ b/coverage/cmdline.py +@@ -937,6 +937,7 @@ def main(argv=None): + This is installed as the script entry point. + + """ ++ sys.path.append(sys.path.pop(0)) + if argv is None: + argv = sys.argv[1:] + try: diff --git a/python/private/coverage_deps.bzl b/python/private/coverage_deps.bzl index d6092e675b..377dfb7494 100644 --- a/python/private/coverage_deps.bzl +++ b/python/private/coverage_deps.bzl @@ -97,6 +97,8 @@ _coverage_deps = { } #END: managed by update_coverage_deps.py script +_coverage_patch = Label("//python/private:coverage.patch") + def coverage_dep(name, python_version, platform, visibility, install = True): """Register a singe coverage dependency based on the python version and platform. @@ -149,6 +151,8 @@ filegroup( """.format( visibility = visibility, ), + patch_args = ["-p1"], + patches = [_coverage_patch], sha256 = sha256, type = "zip", urls = [url], From 68ede14a92114bbb0e23cdb951a2c26a9be828fd Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Tue, 7 Feb 2023 16:47:00 -0600 Subject: [PATCH 156/234] fix(release): minimum needed to run twine to publish (#1021) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(release): minimum needed to run twine to publish Earlier attempts to publish 0.17 have failed mysteriously at the pypa/gh-action-pypi-publish step. This PR replaces that with a command that I can test locally. TWINE_USERNAME=__token__ TWINE_PASSWORD=pypi-*** bazel run --stamp --embed_label=1.2.4 //python/runfiles:wheel.publish -- --repository testpypi Uploading bazel_runfiles-1.2.4-py3-none-any.whl 100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 11.0/11.0 kB • 00:00 • 27.3 MB/s View at: https://test.pypi.org/project/bazel-runfiles/1.2.4/ * fixup! fix(release): minimum needed to run twine to publish * refactor: move twine deps to its own folder * Update WORKSPACE Co-authored-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * Update python/runfiles/BUILD.bazel Co-authored-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * show CI failure * remove actual publish for this PR * chore: exclude requirements test on RBE * Add darwin requirements --------- Co-authored-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- .gitattributes | 1 + WORKSPACE | 19 ++ python/runfiles/BUILD.bazel | 19 +- python/runfiles/{README.md => README.rst} | 17 +- tools/publish/BUILD.bazel | 15 ++ tools/publish/README.md | 6 + tools/publish/requirements.in | 1 + tools/publish/requirements.txt | 297 ++++++++++++++++++++++ tools/publish/requirements_darwin.txt | 192 ++++++++++++++ tools/publish/requirements_windows.txt | 196 ++++++++++++++ 10 files changed, 753 insertions(+), 10 deletions(-) rename python/runfiles/{README.md => README.rst} (81%) create mode 100644 tools/publish/BUILD.bazel create mode 100644 tools/publish/README.md create mode 100644 tools/publish/requirements.in create mode 100644 tools/publish/requirements.txt create mode 100644 tools/publish/requirements_darwin.txt create mode 100644 tools/publish/requirements_windows.txt diff --git a/.gitattributes b/.gitattributes index fb496ed760..64d09fff91 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,2 @@ docs/*.md linguist-generated=true +tools/publish/*.txt linguist-generated=true diff --git a/WORKSPACE b/WORKSPACE index b7059b6271..a833de8384 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -67,3 +67,22 @@ load("@rules_python_gazelle_plugin//:deps.bzl", _py_gazelle_deps = "gazelle_deps # This rule loads and compiles various go dependencies that running gazelle # for python requirements. _py_gazelle_deps() + +##################### +# Install twine for our own runfiles wheel publishing. +# Eventually we might want to install twine automatically for users too, see: +# https://github.com/bazelbuild/rules_python/issues/1016. +load("@python//3.11.1:defs.bzl", "interpreter") +load("@rules_python//python:pip.bzl", "pip_parse") + +pip_parse( + name = "publish_deps", + python_interpreter_target = interpreter, + requirements_darwin = "//tools/publish:requirements_darwin.txt", + requirements_lock = "//tools/publish:requirements.txt", + requirements_windows = "//tools/publish:requirements_windows.txt", +) + +load("@publish_deps//:requirements.bzl", "install_deps") + +install_deps() diff --git a/python/runfiles/BUILD.bazel b/python/runfiles/BUILD.bazel index ea327d7bd4..835c9b4ae2 100644 --- a/python/runfiles/BUILD.bazel +++ b/python/runfiles/BUILD.bazel @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -load("//python:defs.bzl", "py_library") +load("//python:defs.bzl", "py_binary", "py_library") load("//python:packaging.bzl", "py_wheel") filegroup( @@ -40,12 +40,27 @@ py_wheel( "Development Status :: 5 - Production/Stable", "License :: OSI Approved :: Apache Software License", ], - description_file = "README.md", + description_file = "README.rst", dist_folder = "dist", distribution = "bazel_runfiles", homepage = "https://github.com/bazelbuild/rules_python", strip_path_prefixes = ["python"], + # this can be replaced by building with --stamp --embed_label=1.2.3 version = "{BUILD_EMBED_LABEL}", visibility = ["//visibility:public"], deps = [":runfiles"], ) + +# TODO(alexeagle): carry forward #1015 to make this part of the py_wheel macro +py_binary( + name = "wheel.publish", + srcs = ["@publish_deps_twine//:rules_python_wheel_entry_point_twine.py"], + args = [ + "upload", + "$(execpath :wheel.dist)/*", + ], + data = [":wheel.dist"], + imports = ["."], + main = "@publish_deps_twine//:rules_python_wheel_entry_point_twine.py", + deps = ["@publish_deps_twine//:pkg"], +) diff --git a/python/runfiles/README.md b/python/runfiles/README.rst similarity index 81% rename from python/runfiles/README.md rename to python/runfiles/README.rst index 79ba82c1de..59a3852c5f 100644 --- a/python/runfiles/README.md +++ b/python/runfiles/README.rst @@ -1,4 +1,5 @@ -# bazel-runfiles library +bazel-runfiles library +====================== This is a Bazel Runfiles lookup library for Bazel-built Python binaries and tests. @@ -6,9 +7,9 @@ Typical Usage ------------- 1. Add the 'runfiles' dependency along with other third-party dependencies, for example in your - `requirements.txt` file. + ``requirements.txt`` file. -2. Depend on this runfiles library from your build rule, like you would other third-party libraries. +2. Depend on this runfiles library from your build rule, like you would other third-party libraries:: py_binary( name = "my_binary", @@ -16,11 +17,11 @@ Typical Usage deps = [requirement("runfiles")], ) -3. Import the runfiles library. +3. Import the runfiles library:: import runfiles # not "from runfiles import runfiles" -4. Create a Runfiles object and use rlocation to look up runfile paths: +4. Create a Runfiles object and use rlocation to look up runfile paths:: r = runfiles.Create() ... @@ -32,15 +33,15 @@ Typical Usage on the environment variables in os.environ. See `Create()` for more info. If you want to explicitly create a manifest- or directory-based - implementations, you can do so as follows: + implementations, you can do so as follows:: r1 = runfiles.CreateManifestBased("path/to/foo.runfiles_manifest") r2 = runfiles.CreateDirectoryBased("path/to/foo.runfiles/") - If you wnat to start subprocesses, and the subprocess can't automatically + If you want to start subprocesses, and the subprocess can't automatically find the correct runfiles directory, you can explicitly set the right - environment variables for them: + environment variables for them:: import subprocess import runfiles diff --git a/tools/publish/BUILD.bazel b/tools/publish/BUILD.bazel new file mode 100644 index 0000000000..8c4b3ab4a2 --- /dev/null +++ b/tools/publish/BUILD.bazel @@ -0,0 +1,15 @@ +load("//python:pip.bzl", "compile_pip_requirements") + +compile_pip_requirements( + name = "requirements", + requirements_darwin = "requirements_darwin.txt", + requirements_windows = "requirements_windows.txt", + # This fails on RBE right now, and we don't need coverage there: + # WARNING: Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) + # after connection broken by 'NewConnectionError(': + # Failed to establish a new connection: [Errno -3] Temporary failure in name resolution')': /simple/twine/ + # + # ERROR: Could not find a version that satisfies the requirement twine==4.0.2 + # (from -r tools/publish/requirements.in (line 1)) (from versions: none) + tags = ["no-remote-exec"], +) diff --git a/tools/publish/README.md b/tools/publish/README.md new file mode 100644 index 0000000000..6f1e54901b --- /dev/null +++ b/tools/publish/README.md @@ -0,0 +1,6 @@ +# Publish to pypi with twine + +https://packaging.python.org/en/latest/tutorials/packaging-projects/ indicates that the twine +package is used to publish wheels to pypi. + +See more: https://twine.readthedocs.io/en/stable/ diff --git a/tools/publish/requirements.in b/tools/publish/requirements.in new file mode 100644 index 0000000000..af996cf7e2 --- /dev/null +++ b/tools/publish/requirements.in @@ -0,0 +1 @@ +twine diff --git a/tools/publish/requirements.txt b/tools/publish/requirements.txt new file mode 100644 index 0000000000..858fc51e4c --- /dev/null +++ b/tools/publish/requirements.txt @@ -0,0 +1,297 @@ +# +# This file is autogenerated by pip-compile with Python 3.11 +# by the following command: +# +# bazel run //tools/publish:requirements.update +# +bleach==6.0.0 \ + --hash=sha256:1a1a85c1595e07d8db14c5f09f09e6433502c51c595970edc090551f0db99414 \ + --hash=sha256:33c16e3353dbd13028ab4799a0f89a83f113405c766e9c122df8a06f5b85b3f4 + # via readme-renderer +certifi==2022.12.7 \ + --hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \ + --hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18 + # via requests +cffi==1.15.1 \ + --hash=sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5 \ + --hash=sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef \ + --hash=sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104 \ + --hash=sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426 \ + --hash=sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405 \ + --hash=sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375 \ + --hash=sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a \ + --hash=sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e \ + --hash=sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc \ + --hash=sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf \ + --hash=sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185 \ + --hash=sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497 \ + --hash=sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3 \ + --hash=sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35 \ + --hash=sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c \ + --hash=sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83 \ + --hash=sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21 \ + --hash=sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca \ + --hash=sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984 \ + --hash=sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac \ + --hash=sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd \ + --hash=sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee \ + --hash=sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a \ + --hash=sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2 \ + --hash=sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192 \ + --hash=sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7 \ + --hash=sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585 \ + --hash=sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f \ + --hash=sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e \ + --hash=sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27 \ + --hash=sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b \ + --hash=sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e \ + --hash=sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e \ + --hash=sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d \ + --hash=sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c \ + --hash=sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415 \ + --hash=sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82 \ + --hash=sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02 \ + --hash=sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314 \ + --hash=sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325 \ + --hash=sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c \ + --hash=sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3 \ + --hash=sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914 \ + --hash=sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045 \ + --hash=sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d \ + --hash=sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9 \ + --hash=sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5 \ + --hash=sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2 \ + --hash=sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c \ + --hash=sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3 \ + --hash=sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2 \ + --hash=sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8 \ + --hash=sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d \ + --hash=sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d \ + --hash=sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9 \ + --hash=sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162 \ + --hash=sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76 \ + --hash=sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4 \ + --hash=sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e \ + --hash=sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9 \ + --hash=sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6 \ + --hash=sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b \ + --hash=sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01 \ + --hash=sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0 + # via cryptography +charset-normalizer==3.0.1 \ + --hash=sha256:00d3ffdaafe92a5dc603cb9bd5111aaa36dfa187c8285c543be562e61b755f6b \ + --hash=sha256:024e606be3ed92216e2b6952ed859d86b4cfa52cd5bc5f050e7dc28f9b43ec42 \ + --hash=sha256:0298eafff88c99982a4cf66ba2efa1128e4ddaca0b05eec4c456bbc7db691d8d \ + --hash=sha256:02a51034802cbf38db3f89c66fb5d2ec57e6fe7ef2f4a44d070a593c3688667b \ + --hash=sha256:083c8d17153ecb403e5e1eb76a7ef4babfc2c48d58899c98fcaa04833e7a2f9a \ + --hash=sha256:0a11e971ed097d24c534c037d298ad32c6ce81a45736d31e0ff0ad37ab437d59 \ + --hash=sha256:0bf2dae5291758b6f84cf923bfaa285632816007db0330002fa1de38bfcb7154 \ + --hash=sha256:0c0a590235ccd933d9892c627dec5bc7511ce6ad6c1011fdf5b11363022746c1 \ + --hash=sha256:0f438ae3532723fb6ead77e7c604be7c8374094ef4ee2c5e03a3a17f1fca256c \ + --hash=sha256:109487860ef6a328f3eec66f2bf78b0b72400280d8f8ea05f69c51644ba6521a \ + --hash=sha256:11b53acf2411c3b09e6af37e4b9005cba376c872503c8f28218c7243582df45d \ + --hash=sha256:12db3b2c533c23ab812c2b25934f60383361f8a376ae272665f8e48b88e8e1c6 \ + --hash=sha256:14e76c0f23218b8f46c4d87018ca2e441535aed3632ca134b10239dfb6dadd6b \ + --hash=sha256:16a8663d6e281208d78806dbe14ee9903715361cf81f6d4309944e4d1e59ac5b \ + --hash=sha256:292d5e8ba896bbfd6334b096e34bffb56161c81408d6d036a7dfa6929cff8783 \ + --hash=sha256:2c03cc56021a4bd59be889c2b9257dae13bf55041a3372d3295416f86b295fb5 \ + --hash=sha256:2e396d70bc4ef5325b72b593a72c8979999aa52fb8bcf03f701c1b03e1166918 \ + --hash=sha256:2edb64ee7bf1ed524a1da60cdcd2e1f6e2b4f66ef7c077680739f1641f62f555 \ + --hash=sha256:31a9ddf4718d10ae04d9b18801bd776693487cbb57d74cc3458a7673f6f34639 \ + --hash=sha256:356541bf4381fa35856dafa6a965916e54bed415ad8a24ee6de6e37deccf2786 \ + --hash=sha256:358a7c4cb8ba9b46c453b1dd8d9e431452d5249072e4f56cfda3149f6ab1405e \ + --hash=sha256:37f8febc8ec50c14f3ec9637505f28e58d4f66752207ea177c1d67df25da5aed \ + --hash=sha256:39049da0ffb96c8cbb65cbf5c5f3ca3168990adf3551bd1dee10c48fce8ae820 \ + --hash=sha256:39cf9ed17fe3b1bc81f33c9ceb6ce67683ee7526e65fde1447c772afc54a1bb8 \ + --hash=sha256:3ae1de54a77dc0d6d5fcf623290af4266412a7c4be0b1ff7444394f03f5c54e3 \ + --hash=sha256:3b590df687e3c5ee0deef9fc8c547d81986d9a1b56073d82de008744452d6541 \ + --hash=sha256:3e45867f1f2ab0711d60c6c71746ac53537f1684baa699f4f668d4c6f6ce8e14 \ + --hash=sha256:3fc1c4a2ffd64890aebdb3f97e1278b0cc72579a08ca4de8cd2c04799a3a22be \ + --hash=sha256:4457ea6774b5611f4bed5eaa5df55f70abde42364d498c5134b7ef4c6958e20e \ + --hash=sha256:44ba614de5361b3e5278e1241fda3dc1838deed864b50a10d7ce92983797fa76 \ + --hash=sha256:4a8fcf28c05c1f6d7e177a9a46a1c52798bfe2ad80681d275b10dcf317deaf0b \ + --hash=sha256:4b0d02d7102dd0f997580b51edc4cebcf2ab6397a7edf89f1c73b586c614272c \ + --hash=sha256:502218f52498a36d6bf5ea77081844017bf7982cdbe521ad85e64cabee1b608b \ + --hash=sha256:503e65837c71b875ecdd733877d852adbc465bd82c768a067badd953bf1bc5a3 \ + --hash=sha256:5995f0164fa7df59db4746112fec3f49c461dd6b31b841873443bdb077c13cfc \ + --hash=sha256:59e5686dd847347e55dffcc191a96622f016bc0ad89105e24c14e0d6305acbc6 \ + --hash=sha256:601f36512f9e28f029d9481bdaf8e89e5148ac5d89cffd3b05cd533eeb423b59 \ + --hash=sha256:608862a7bf6957f2333fc54ab4399e405baad0163dc9f8d99cb236816db169d4 \ + --hash=sha256:62595ab75873d50d57323a91dd03e6966eb79c41fa834b7a1661ed043b2d404d \ + --hash=sha256:70990b9c51340e4044cfc394a81f614f3f90d41397104d226f21e66de668730d \ + --hash=sha256:71140351489970dfe5e60fc621ada3e0f41104a5eddaca47a7acb3c1b851d6d3 \ + --hash=sha256:72966d1b297c741541ca8cf1223ff262a6febe52481af742036a0b296e35fa5a \ + --hash=sha256:74292fc76c905c0ef095fe11e188a32ebd03bc38f3f3e9bcb85e4e6db177b7ea \ + --hash=sha256:761e8904c07ad053d285670f36dd94e1b6ab7f16ce62b9805c475b7aa1cffde6 \ + --hash=sha256:772b87914ff1152b92a197ef4ea40efe27a378606c39446ded52c8f80f79702e \ + --hash=sha256:79909e27e8e4fcc9db4addea88aa63f6423ebb171db091fb4373e3312cb6d603 \ + --hash=sha256:7e189e2e1d3ed2f4aebabd2d5b0f931e883676e51c7624826e0a4e5fe8a0bf24 \ + --hash=sha256:7eb33a30d75562222b64f569c642ff3dc6689e09adda43a082208397f016c39a \ + --hash=sha256:81d6741ab457d14fdedc215516665050f3822d3e56508921cc7239f8c8e66a58 \ + --hash=sha256:8499ca8f4502af841f68135133d8258f7b32a53a1d594aa98cc52013fff55678 \ + --hash=sha256:84c3990934bae40ea69a82034912ffe5a62c60bbf6ec5bc9691419641d7d5c9a \ + --hash=sha256:87701167f2a5c930b403e9756fab1d31d4d4da52856143b609e30a1ce7160f3c \ + --hash=sha256:88600c72ef7587fe1708fd242b385b6ed4b8904976d5da0893e31df8b3480cb6 \ + --hash=sha256:8ac7b6a045b814cf0c47f3623d21ebd88b3e8cf216a14790b455ea7ff0135d18 \ + --hash=sha256:8b8af03d2e37866d023ad0ddea594edefc31e827fee64f8de5611a1dbc373174 \ + --hash=sha256:8c7fe7afa480e3e82eed58e0ca89f751cd14d767638e2550c77a92a9e749c317 \ + --hash=sha256:8eade758719add78ec36dc13201483f8e9b5d940329285edcd5f70c0a9edbd7f \ + --hash=sha256:911d8a40b2bef5b8bbae2e36a0b103f142ac53557ab421dc16ac4aafee6f53dc \ + --hash=sha256:93ad6d87ac18e2a90b0fe89df7c65263b9a99a0eb98f0a3d2e079f12a0735837 \ + --hash=sha256:95dea361dd73757c6f1c0a1480ac499952c16ac83f7f5f4f84f0658a01b8ef41 \ + --hash=sha256:9ab77acb98eba3fd2a85cd160851816bfce6871d944d885febf012713f06659c \ + --hash=sha256:9cb3032517f1627cc012dbc80a8ec976ae76d93ea2b5feaa9d2a5b8882597579 \ + --hash=sha256:9cf4e8ad252f7c38dd1f676b46514f92dc0ebeb0db5552f5f403509705e24753 \ + --hash=sha256:9d9153257a3f70d5f69edf2325357251ed20f772b12e593f3b3377b5f78e7ef8 \ + --hash=sha256:a152f5f33d64a6be73f1d30c9cc82dfc73cec6477ec268e7c6e4c7d23c2d2291 \ + --hash=sha256:a16418ecf1329f71df119e8a65f3aa68004a3f9383821edcb20f0702934d8087 \ + --hash=sha256:a60332922359f920193b1d4826953c507a877b523b2395ad7bc716ddd386d866 \ + --hash=sha256:a8d0fc946c784ff7f7c3742310cc8a57c5c6dc31631269876a88b809dbeff3d3 \ + --hash=sha256:ab5de034a886f616a5668aa5d098af2b5385ed70142090e2a31bcbd0af0fdb3d \ + --hash=sha256:c22d3fe05ce11d3671297dc8973267daa0f938b93ec716e12e0f6dee81591dc1 \ + --hash=sha256:c2ac1b08635a8cd4e0cbeaf6f5e922085908d48eb05d44c5ae9eabab148512ca \ + --hash=sha256:c512accbd6ff0270939b9ac214b84fb5ada5f0409c44298361b2f5e13f9aed9e \ + --hash=sha256:c75ffc45f25324e68ab238cb4b5c0a38cd1c3d7f1fb1f72b5541de469e2247db \ + --hash=sha256:c95a03c79bbe30eec3ec2b7f076074f4281526724c8685a42872974ef4d36b72 \ + --hash=sha256:cadaeaba78750d58d3cc6ac4d1fd867da6fc73c88156b7a3212a3cd4819d679d \ + --hash=sha256:cd6056167405314a4dc3c173943f11249fa0f1b204f8b51ed4bde1a9cd1834dc \ + --hash=sha256:db72b07027db150f468fbada4d85b3b2729a3db39178abf5c543b784c1254539 \ + --hash=sha256:df2c707231459e8a4028eabcd3cfc827befd635b3ef72eada84ab13b52e1574d \ + --hash=sha256:e62164b50f84e20601c1ff8eb55620d2ad25fb81b59e3cd776a1902527a788af \ + --hash=sha256:e696f0dd336161fca9adbb846875d40752e6eba585843c768935ba5c9960722b \ + --hash=sha256:eaa379fcd227ca235d04152ca6704c7cb55564116f8bc52545ff357628e10602 \ + --hash=sha256:ebea339af930f8ca5d7a699b921106c6e29c617fe9606fa7baa043c1cdae326f \ + --hash=sha256:f4c39b0e3eac288fedc2b43055cfc2ca7a60362d0e5e87a637beac5d801ef478 \ + --hash=sha256:f5057856d21e7586765171eac8b9fc3f7d44ef39425f85dbcccb13b3ebea806c \ + --hash=sha256:f6f45710b4459401609ebebdbcfb34515da4fc2aa886f95107f556ac69a9147e \ + --hash=sha256:f97e83fa6c25693c7a35de154681fcc257c1c41b38beb0304b9c4d2d9e164479 \ + --hash=sha256:f9d0c5c045a3ca9bedfc35dca8526798eb91a07aa7a2c0fee134c6c6f321cbd7 \ + --hash=sha256:ff6f3db31555657f3163b15a6b7c6938d08df7adbfc9dd13d9d19edad678f1e8 + # via requests +cryptography==39.0.0 \ + --hash=sha256:1a6915075c6d3a5e1215eab5d99bcec0da26036ff2102a1038401d6ef5bef25b \ + --hash=sha256:1ee1fd0de9851ff32dbbb9362a4d833b579b4a6cc96883e8e6d2ff2a6bc7104f \ + --hash=sha256:407cec680e811b4fc829de966f88a7c62a596faa250fc1a4b520a0355b9bc190 \ + --hash=sha256:50386acb40fbabbceeb2986332f0287f50f29ccf1497bae31cf5c3e7b4f4b34f \ + --hash=sha256:6f97109336df5c178ee7c9c711b264c502b905c2d2a29ace99ed761533a3460f \ + --hash=sha256:754978da4d0457e7ca176f58c57b1f9de6556591c19b25b8bcce3c77d314f5eb \ + --hash=sha256:76c24dd4fd196a80f9f2f5405a778a8ca132f16b10af113474005635fe7e066c \ + --hash=sha256:7dacfdeee048814563eaaec7c4743c8aea529fe3dd53127313a792f0dadc1773 \ + --hash=sha256:80ee674c08aaef194bc4627b7f2956e5ba7ef29c3cc3ca488cf15854838a8f72 \ + --hash=sha256:844ad4d7c3850081dffba91cdd91950038ee4ac525c575509a42d3fc806b83c8 \ + --hash=sha256:875aea1039d78557c7c6b4db2fe0e9d2413439f4676310a5f269dd342ca7a717 \ + --hash=sha256:887cbc1ea60786e534b00ba8b04d1095f4272d380ebd5f7a7eb4cc274710fad9 \ + --hash=sha256:ad04f413436b0781f20c52a661660f1e23bcd89a0e9bb1d6d20822d048cf2856 \ + --hash=sha256:bae6c7f4a36a25291b619ad064a30a07110a805d08dc89984f4f441f6c1f3f96 \ + --hash=sha256:c52a1a6f81e738d07f43dab57831c29e57d21c81a942f4602fac7ee21b27f288 \ + --hash=sha256:e0a05aee6a82d944f9b4edd6a001178787d1546ec7c6223ee9a848a7ade92e39 \ + --hash=sha256:e324de6972b151f99dc078defe8fb1b0a82c6498e37bff335f5bc6b1e3ab5a1e \ + --hash=sha256:e5d71c5d5bd5b5c3eebcf7c5c2bb332d62ec68921a8c593bea8c394911a005ce \ + --hash=sha256:f3ed2d864a2fa1666e749fe52fb8e23d8e06b8012e8bd8147c73797c506e86f1 \ + --hash=sha256:f671c1bb0d6088e94d61d80c606d65baacc0d374e67bf895148883461cd848de \ + --hash=sha256:f6c0db08d81ead9576c4d94bbb27aed8d7a430fa27890f39084c2d0e2ec6b0df \ + --hash=sha256:f964c7dcf7802d133e8dbd1565914fa0194f9d683d82411989889ecd701e8adf \ + --hash=sha256:fec8b932f51ae245121c4671b4bbc030880f363354b2f0e0bd1366017d891458 + # via secretstorage +docutils==0.19 \ + --hash=sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6 \ + --hash=sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc + # via readme-renderer +idna==3.4 \ + --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ + --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 + # via requests +importlib-metadata==6.0.0 \ + --hash=sha256:7efb448ec9a5e313a57655d35aa54cd3e01b7e1fbcf72dce1bf06119420f5bad \ + --hash=sha256:e354bedeb60efa6affdcc8ae121b73544a7aa74156d047311948f6d711cd378d + # via + # keyring + # twine +jaraco-classes==3.2.3 \ + --hash=sha256:2353de3288bc6b82120752201c6b1c1a14b058267fa424ed5ce5984e3b922158 \ + --hash=sha256:89559fa5c1d3c34eff6f631ad80bb21f378dbcbb35dd161fd2c6b93f5be2f98a + # via keyring +jeepney==0.8.0 \ + --hash=sha256:5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806 \ + --hash=sha256:c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755 + # via + # keyring + # secretstorage +keyring==23.13.1 \ + --hash=sha256:771ed2a91909389ed6148631de678f82ddc73737d85a927f382a8a1b157898cd \ + --hash=sha256:ba2e15a9b35e21908d0aaf4e0a47acc52d6ae33444df0da2b49d41a46ef6d678 + # via twine +markdown-it-py==2.1.0 \ + --hash=sha256:93de681e5c021a432c63147656fe21790bc01231e0cd2da73626f1aa3ac0fe27 \ + --hash=sha256:cf7e59fed14b5ae17c0006eff14a2d9a00ed5f3a846148153899a0224e2c07da + # via rich +mdurl==0.1.2 \ + --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ + --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba + # via markdown-it-py +more-itertools==9.0.0 \ + --hash=sha256:250e83d7e81d0c87ca6bd942e6aeab8cc9daa6096d12c5308f3f92fa5e5c1f41 \ + --hash=sha256:5a6257e40878ef0520b1803990e3e22303a41b5714006c32a3fd8304b26ea1ab + # via jaraco-classes +pkginfo==1.9.6 \ + --hash=sha256:4b7a555a6d5a22169fcc9cf7bfd78d296b0361adad412a346c1226849af5e546 \ + --hash=sha256:8fd5896e8718a4372f0ea9cc9d96f6417c9b986e23a4d116dda26b62cc29d046 + # via twine +pycparser==2.21 \ + --hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \ + --hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206 + # via cffi +pygments==2.14.0 \ + --hash=sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297 \ + --hash=sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717 + # via + # readme-renderer + # rich +readme-renderer==37.3 \ + --hash=sha256:cd653186dfc73055656f090f227f5cb22a046d7f71a841dfa305f55c9a513273 \ + --hash=sha256:f67a16caedfa71eef48a31b39708637a6f4664c4394801a7b0d6432d13907343 + # via twine +requests==2.28.2 \ + --hash=sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa \ + --hash=sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf + # via + # requests-toolbelt + # twine +requests-toolbelt==0.10.1 \ + --hash=sha256:18565aa58116d9951ac39baa288d3adb5b3ff975c4f25eee78555d89e8f247f7 \ + --hash=sha256:62e09f7ff5ccbda92772a29f394a49c3ad6cb181d568b1337626b2abb628a63d + # via twine +rfc3986==2.0.0 \ + --hash=sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd \ + --hash=sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c + # via twine +rich==13.2.0 \ + --hash=sha256:7c963f0d03819221e9ac561e1bc866e3f95a02248c1234daa48954e6d381c003 \ + --hash=sha256:f1a00cdd3eebf999a15d85ec498bfe0b1a77efe9b34f645768a54132ef444ac5 + # via twine +secretstorage==3.3.3 \ + --hash=sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77 \ + --hash=sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99 + # via keyring +six==1.16.0 \ + --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ + --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 + # via bleach +twine==4.0.2 \ + --hash=sha256:929bc3c280033347a00f847236564d1c52a3e61b1ac2516c97c48f3ceab756d8 \ + --hash=sha256:9e102ef5fdd5a20661eb88fad46338806c3bd32cf1db729603fe3697b1bc83c8 + # via -r tools/publish/requirements.in +urllib3==1.26.14 \ + --hash=sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72 \ + --hash=sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1 + # via + # requests + # twine +webencodings==0.5.1 \ + --hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \ + --hash=sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923 + # via bleach +zipp==3.11.0 \ + --hash=sha256:83a28fcb75844b5c0cdaf5aa4003c2d728c77e05f5aeabe8e95e56727005fbaa \ + --hash=sha256:a7a22e05929290a67401440b39690ae6563279bced5f314609d9d03798f56766 + # via importlib-metadata diff --git a/tools/publish/requirements_darwin.txt b/tools/publish/requirements_darwin.txt new file mode 100644 index 0000000000..cb35e69c97 --- /dev/null +++ b/tools/publish/requirements_darwin.txt @@ -0,0 +1,192 @@ +# +# This file is autogenerated by pip-compile with Python 3.11 +# by the following command: +# +# bazel run //tools/publish:requirements.update +# +bleach==6.0.0 \ + --hash=sha256:1a1a85c1595e07d8db14c5f09f09e6433502c51c595970edc090551f0db99414 \ + --hash=sha256:33c16e3353dbd13028ab4799a0f89a83f113405c766e9c122df8a06f5b85b3f4 + # via readme-renderer +certifi==2022.12.7 \ + --hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \ + --hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18 + # via requests +charset-normalizer==3.0.1 \ + --hash=sha256:00d3ffdaafe92a5dc603cb9bd5111aaa36dfa187c8285c543be562e61b755f6b \ + --hash=sha256:024e606be3ed92216e2b6952ed859d86b4cfa52cd5bc5f050e7dc28f9b43ec42 \ + --hash=sha256:0298eafff88c99982a4cf66ba2efa1128e4ddaca0b05eec4c456bbc7db691d8d \ + --hash=sha256:02a51034802cbf38db3f89c66fb5d2ec57e6fe7ef2f4a44d070a593c3688667b \ + --hash=sha256:083c8d17153ecb403e5e1eb76a7ef4babfc2c48d58899c98fcaa04833e7a2f9a \ + --hash=sha256:0a11e971ed097d24c534c037d298ad32c6ce81a45736d31e0ff0ad37ab437d59 \ + --hash=sha256:0bf2dae5291758b6f84cf923bfaa285632816007db0330002fa1de38bfcb7154 \ + --hash=sha256:0c0a590235ccd933d9892c627dec5bc7511ce6ad6c1011fdf5b11363022746c1 \ + --hash=sha256:0f438ae3532723fb6ead77e7c604be7c8374094ef4ee2c5e03a3a17f1fca256c \ + --hash=sha256:109487860ef6a328f3eec66f2bf78b0b72400280d8f8ea05f69c51644ba6521a \ + --hash=sha256:11b53acf2411c3b09e6af37e4b9005cba376c872503c8f28218c7243582df45d \ + --hash=sha256:12db3b2c533c23ab812c2b25934f60383361f8a376ae272665f8e48b88e8e1c6 \ + --hash=sha256:14e76c0f23218b8f46c4d87018ca2e441535aed3632ca134b10239dfb6dadd6b \ + --hash=sha256:16a8663d6e281208d78806dbe14ee9903715361cf81f6d4309944e4d1e59ac5b \ + --hash=sha256:292d5e8ba896bbfd6334b096e34bffb56161c81408d6d036a7dfa6929cff8783 \ + --hash=sha256:2c03cc56021a4bd59be889c2b9257dae13bf55041a3372d3295416f86b295fb5 \ + --hash=sha256:2e396d70bc4ef5325b72b593a72c8979999aa52fb8bcf03f701c1b03e1166918 \ + --hash=sha256:2edb64ee7bf1ed524a1da60cdcd2e1f6e2b4f66ef7c077680739f1641f62f555 \ + --hash=sha256:31a9ddf4718d10ae04d9b18801bd776693487cbb57d74cc3458a7673f6f34639 \ + --hash=sha256:356541bf4381fa35856dafa6a965916e54bed415ad8a24ee6de6e37deccf2786 \ + --hash=sha256:358a7c4cb8ba9b46c453b1dd8d9e431452d5249072e4f56cfda3149f6ab1405e \ + --hash=sha256:37f8febc8ec50c14f3ec9637505f28e58d4f66752207ea177c1d67df25da5aed \ + --hash=sha256:39049da0ffb96c8cbb65cbf5c5f3ca3168990adf3551bd1dee10c48fce8ae820 \ + --hash=sha256:39cf9ed17fe3b1bc81f33c9ceb6ce67683ee7526e65fde1447c772afc54a1bb8 \ + --hash=sha256:3ae1de54a77dc0d6d5fcf623290af4266412a7c4be0b1ff7444394f03f5c54e3 \ + --hash=sha256:3b590df687e3c5ee0deef9fc8c547d81986d9a1b56073d82de008744452d6541 \ + --hash=sha256:3e45867f1f2ab0711d60c6c71746ac53537f1684baa699f4f668d4c6f6ce8e14 \ + --hash=sha256:3fc1c4a2ffd64890aebdb3f97e1278b0cc72579a08ca4de8cd2c04799a3a22be \ + --hash=sha256:4457ea6774b5611f4bed5eaa5df55f70abde42364d498c5134b7ef4c6958e20e \ + --hash=sha256:44ba614de5361b3e5278e1241fda3dc1838deed864b50a10d7ce92983797fa76 \ + --hash=sha256:4a8fcf28c05c1f6d7e177a9a46a1c52798bfe2ad80681d275b10dcf317deaf0b \ + --hash=sha256:4b0d02d7102dd0f997580b51edc4cebcf2ab6397a7edf89f1c73b586c614272c \ + --hash=sha256:502218f52498a36d6bf5ea77081844017bf7982cdbe521ad85e64cabee1b608b \ + --hash=sha256:503e65837c71b875ecdd733877d852adbc465bd82c768a067badd953bf1bc5a3 \ + --hash=sha256:5995f0164fa7df59db4746112fec3f49c461dd6b31b841873443bdb077c13cfc \ + --hash=sha256:59e5686dd847347e55dffcc191a96622f016bc0ad89105e24c14e0d6305acbc6 \ + --hash=sha256:601f36512f9e28f029d9481bdaf8e89e5148ac5d89cffd3b05cd533eeb423b59 \ + --hash=sha256:608862a7bf6957f2333fc54ab4399e405baad0163dc9f8d99cb236816db169d4 \ + --hash=sha256:62595ab75873d50d57323a91dd03e6966eb79c41fa834b7a1661ed043b2d404d \ + --hash=sha256:70990b9c51340e4044cfc394a81f614f3f90d41397104d226f21e66de668730d \ + --hash=sha256:71140351489970dfe5e60fc621ada3e0f41104a5eddaca47a7acb3c1b851d6d3 \ + --hash=sha256:72966d1b297c741541ca8cf1223ff262a6febe52481af742036a0b296e35fa5a \ + --hash=sha256:74292fc76c905c0ef095fe11e188a32ebd03bc38f3f3e9bcb85e4e6db177b7ea \ + --hash=sha256:761e8904c07ad053d285670f36dd94e1b6ab7f16ce62b9805c475b7aa1cffde6 \ + --hash=sha256:772b87914ff1152b92a197ef4ea40efe27a378606c39446ded52c8f80f79702e \ + --hash=sha256:79909e27e8e4fcc9db4addea88aa63f6423ebb171db091fb4373e3312cb6d603 \ + --hash=sha256:7e189e2e1d3ed2f4aebabd2d5b0f931e883676e51c7624826e0a4e5fe8a0bf24 \ + --hash=sha256:7eb33a30d75562222b64f569c642ff3dc6689e09adda43a082208397f016c39a \ + --hash=sha256:81d6741ab457d14fdedc215516665050f3822d3e56508921cc7239f8c8e66a58 \ + --hash=sha256:8499ca8f4502af841f68135133d8258f7b32a53a1d594aa98cc52013fff55678 \ + --hash=sha256:84c3990934bae40ea69a82034912ffe5a62c60bbf6ec5bc9691419641d7d5c9a \ + --hash=sha256:87701167f2a5c930b403e9756fab1d31d4d4da52856143b609e30a1ce7160f3c \ + --hash=sha256:88600c72ef7587fe1708fd242b385b6ed4b8904976d5da0893e31df8b3480cb6 \ + --hash=sha256:8ac7b6a045b814cf0c47f3623d21ebd88b3e8cf216a14790b455ea7ff0135d18 \ + --hash=sha256:8b8af03d2e37866d023ad0ddea594edefc31e827fee64f8de5611a1dbc373174 \ + --hash=sha256:8c7fe7afa480e3e82eed58e0ca89f751cd14d767638e2550c77a92a9e749c317 \ + --hash=sha256:8eade758719add78ec36dc13201483f8e9b5d940329285edcd5f70c0a9edbd7f \ + --hash=sha256:911d8a40b2bef5b8bbae2e36a0b103f142ac53557ab421dc16ac4aafee6f53dc \ + --hash=sha256:93ad6d87ac18e2a90b0fe89df7c65263b9a99a0eb98f0a3d2e079f12a0735837 \ + --hash=sha256:95dea361dd73757c6f1c0a1480ac499952c16ac83f7f5f4f84f0658a01b8ef41 \ + --hash=sha256:9ab77acb98eba3fd2a85cd160851816bfce6871d944d885febf012713f06659c \ + --hash=sha256:9cb3032517f1627cc012dbc80a8ec976ae76d93ea2b5feaa9d2a5b8882597579 \ + --hash=sha256:9cf4e8ad252f7c38dd1f676b46514f92dc0ebeb0db5552f5f403509705e24753 \ + --hash=sha256:9d9153257a3f70d5f69edf2325357251ed20f772b12e593f3b3377b5f78e7ef8 \ + --hash=sha256:a152f5f33d64a6be73f1d30c9cc82dfc73cec6477ec268e7c6e4c7d23c2d2291 \ + --hash=sha256:a16418ecf1329f71df119e8a65f3aa68004a3f9383821edcb20f0702934d8087 \ + --hash=sha256:a60332922359f920193b1d4826953c507a877b523b2395ad7bc716ddd386d866 \ + --hash=sha256:a8d0fc946c784ff7f7c3742310cc8a57c5c6dc31631269876a88b809dbeff3d3 \ + --hash=sha256:ab5de034a886f616a5668aa5d098af2b5385ed70142090e2a31bcbd0af0fdb3d \ + --hash=sha256:c22d3fe05ce11d3671297dc8973267daa0f938b93ec716e12e0f6dee81591dc1 \ + --hash=sha256:c2ac1b08635a8cd4e0cbeaf6f5e922085908d48eb05d44c5ae9eabab148512ca \ + --hash=sha256:c512accbd6ff0270939b9ac214b84fb5ada5f0409c44298361b2f5e13f9aed9e \ + --hash=sha256:c75ffc45f25324e68ab238cb4b5c0a38cd1c3d7f1fb1f72b5541de469e2247db \ + --hash=sha256:c95a03c79bbe30eec3ec2b7f076074f4281526724c8685a42872974ef4d36b72 \ + --hash=sha256:cadaeaba78750d58d3cc6ac4d1fd867da6fc73c88156b7a3212a3cd4819d679d \ + --hash=sha256:cd6056167405314a4dc3c173943f11249fa0f1b204f8b51ed4bde1a9cd1834dc \ + --hash=sha256:db72b07027db150f468fbada4d85b3b2729a3db39178abf5c543b784c1254539 \ + --hash=sha256:df2c707231459e8a4028eabcd3cfc827befd635b3ef72eada84ab13b52e1574d \ + --hash=sha256:e62164b50f84e20601c1ff8eb55620d2ad25fb81b59e3cd776a1902527a788af \ + --hash=sha256:e696f0dd336161fca9adbb846875d40752e6eba585843c768935ba5c9960722b \ + --hash=sha256:eaa379fcd227ca235d04152ca6704c7cb55564116f8bc52545ff357628e10602 \ + --hash=sha256:ebea339af930f8ca5d7a699b921106c6e29c617fe9606fa7baa043c1cdae326f \ + --hash=sha256:f4c39b0e3eac288fedc2b43055cfc2ca7a60362d0e5e87a637beac5d801ef478 \ + --hash=sha256:f5057856d21e7586765171eac8b9fc3f7d44ef39425f85dbcccb13b3ebea806c \ + --hash=sha256:f6f45710b4459401609ebebdbcfb34515da4fc2aa886f95107f556ac69a9147e \ + --hash=sha256:f97e83fa6c25693c7a35de154681fcc257c1c41b38beb0304b9c4d2d9e164479 \ + --hash=sha256:f9d0c5c045a3ca9bedfc35dca8526798eb91a07aa7a2c0fee134c6c6f321cbd7 \ + --hash=sha256:ff6f3db31555657f3163b15a6b7c6938d08df7adbfc9dd13d9d19edad678f1e8 + # via requests +docutils==0.19 \ + --hash=sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6 \ + --hash=sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc + # via readme-renderer +idna==3.4 \ + --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ + --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 + # via requests +importlib-metadata==6.0.0 \ + --hash=sha256:7efb448ec9a5e313a57655d35aa54cd3e01b7e1fbcf72dce1bf06119420f5bad \ + --hash=sha256:e354bedeb60efa6affdcc8ae121b73544a7aa74156d047311948f6d711cd378d + # via + # keyring + # twine +jaraco-classes==3.2.3 \ + --hash=sha256:2353de3288bc6b82120752201c6b1c1a14b058267fa424ed5ce5984e3b922158 \ + --hash=sha256:89559fa5c1d3c34eff6f631ad80bb21f378dbcbb35dd161fd2c6b93f5be2f98a + # via keyring +keyring==23.13.1 \ + --hash=sha256:771ed2a91909389ed6148631de678f82ddc73737d85a927f382a8a1b157898cd \ + --hash=sha256:ba2e15a9b35e21908d0aaf4e0a47acc52d6ae33444df0da2b49d41a46ef6d678 + # via twine +markdown-it-py==2.1.0 \ + --hash=sha256:93de681e5c021a432c63147656fe21790bc01231e0cd2da73626f1aa3ac0fe27 \ + --hash=sha256:cf7e59fed14b5ae17c0006eff14a2d9a00ed5f3a846148153899a0224e2c07da + # via rich +mdurl==0.1.2 \ + --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ + --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba + # via markdown-it-py +more-itertools==9.0.0 \ + --hash=sha256:250e83d7e81d0c87ca6bd942e6aeab8cc9daa6096d12c5308f3f92fa5e5c1f41 \ + --hash=sha256:5a6257e40878ef0520b1803990e3e22303a41b5714006c32a3fd8304b26ea1ab + # via jaraco-classes +pkginfo==1.9.6 \ + --hash=sha256:4b7a555a6d5a22169fcc9cf7bfd78d296b0361adad412a346c1226849af5e546 \ + --hash=sha256:8fd5896e8718a4372f0ea9cc9d96f6417c9b986e23a4d116dda26b62cc29d046 + # via twine +pygments==2.14.0 \ + --hash=sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297 \ + --hash=sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717 + # via + # readme-renderer + # rich +readme-renderer==37.3 \ + --hash=sha256:cd653186dfc73055656f090f227f5cb22a046d7f71a841dfa305f55c9a513273 \ + --hash=sha256:f67a16caedfa71eef48a31b39708637a6f4664c4394801a7b0d6432d13907343 + # via twine +requests==2.28.2 \ + --hash=sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa \ + --hash=sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf + # via + # requests-toolbelt + # twine +requests-toolbelt==0.10.1 \ + --hash=sha256:18565aa58116d9951ac39baa288d3adb5b3ff975c4f25eee78555d89e8f247f7 \ + --hash=sha256:62e09f7ff5ccbda92772a29f394a49c3ad6cb181d568b1337626b2abb628a63d + # via twine +rfc3986==2.0.0 \ + --hash=sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd \ + --hash=sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c + # via twine +rich==13.2.0 \ + --hash=sha256:7c963f0d03819221e9ac561e1bc866e3f95a02248c1234daa48954e6d381c003 \ + --hash=sha256:f1a00cdd3eebf999a15d85ec498bfe0b1a77efe9b34f645768a54132ef444ac5 + # via twine +six==1.16.0 \ + --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ + --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 + # via bleach +twine==4.0.2 \ + --hash=sha256:929bc3c280033347a00f847236564d1c52a3e61b1ac2516c97c48f3ceab756d8 \ + --hash=sha256:9e102ef5fdd5a20661eb88fad46338806c3bd32cf1db729603fe3697b1bc83c8 + # via -r tools/publish/requirements.in +urllib3==1.26.14 \ + --hash=sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72 \ + --hash=sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1 + # via + # requests + # twine +webencodings==0.5.1 \ + --hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \ + --hash=sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923 + # via bleach +zipp==3.11.0 \ + --hash=sha256:83a28fcb75844b5c0cdaf5aa4003c2d728c77e05f5aeabe8e95e56727005fbaa \ + --hash=sha256:a7a22e05929290a67401440b39690ae6563279bced5f314609d9d03798f56766 + # via importlib-metadata diff --git a/tools/publish/requirements_windows.txt b/tools/publish/requirements_windows.txt new file mode 100644 index 0000000000..cd175c68ef --- /dev/null +++ b/tools/publish/requirements_windows.txt @@ -0,0 +1,196 @@ +# +# This file is autogenerated by pip-compile with Python 3.11 +# by the following command: +# +# bazel run //tools/publish:requirements.update +# +bleach==6.0.0 \ + --hash=sha256:1a1a85c1595e07d8db14c5f09f09e6433502c51c595970edc090551f0db99414 \ + --hash=sha256:33c16e3353dbd13028ab4799a0f89a83f113405c766e9c122df8a06f5b85b3f4 + # via readme-renderer +certifi==2022.12.7 \ + --hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \ + --hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18 + # via requests +charset-normalizer==3.0.1 \ + --hash=sha256:00d3ffdaafe92a5dc603cb9bd5111aaa36dfa187c8285c543be562e61b755f6b \ + --hash=sha256:024e606be3ed92216e2b6952ed859d86b4cfa52cd5bc5f050e7dc28f9b43ec42 \ + --hash=sha256:0298eafff88c99982a4cf66ba2efa1128e4ddaca0b05eec4c456bbc7db691d8d \ + --hash=sha256:02a51034802cbf38db3f89c66fb5d2ec57e6fe7ef2f4a44d070a593c3688667b \ + --hash=sha256:083c8d17153ecb403e5e1eb76a7ef4babfc2c48d58899c98fcaa04833e7a2f9a \ + --hash=sha256:0a11e971ed097d24c534c037d298ad32c6ce81a45736d31e0ff0ad37ab437d59 \ + --hash=sha256:0bf2dae5291758b6f84cf923bfaa285632816007db0330002fa1de38bfcb7154 \ + --hash=sha256:0c0a590235ccd933d9892c627dec5bc7511ce6ad6c1011fdf5b11363022746c1 \ + --hash=sha256:0f438ae3532723fb6ead77e7c604be7c8374094ef4ee2c5e03a3a17f1fca256c \ + --hash=sha256:109487860ef6a328f3eec66f2bf78b0b72400280d8f8ea05f69c51644ba6521a \ + --hash=sha256:11b53acf2411c3b09e6af37e4b9005cba376c872503c8f28218c7243582df45d \ + --hash=sha256:12db3b2c533c23ab812c2b25934f60383361f8a376ae272665f8e48b88e8e1c6 \ + --hash=sha256:14e76c0f23218b8f46c4d87018ca2e441535aed3632ca134b10239dfb6dadd6b \ + --hash=sha256:16a8663d6e281208d78806dbe14ee9903715361cf81f6d4309944e4d1e59ac5b \ + --hash=sha256:292d5e8ba896bbfd6334b096e34bffb56161c81408d6d036a7dfa6929cff8783 \ + --hash=sha256:2c03cc56021a4bd59be889c2b9257dae13bf55041a3372d3295416f86b295fb5 \ + --hash=sha256:2e396d70bc4ef5325b72b593a72c8979999aa52fb8bcf03f701c1b03e1166918 \ + --hash=sha256:2edb64ee7bf1ed524a1da60cdcd2e1f6e2b4f66ef7c077680739f1641f62f555 \ + --hash=sha256:31a9ddf4718d10ae04d9b18801bd776693487cbb57d74cc3458a7673f6f34639 \ + --hash=sha256:356541bf4381fa35856dafa6a965916e54bed415ad8a24ee6de6e37deccf2786 \ + --hash=sha256:358a7c4cb8ba9b46c453b1dd8d9e431452d5249072e4f56cfda3149f6ab1405e \ + --hash=sha256:37f8febc8ec50c14f3ec9637505f28e58d4f66752207ea177c1d67df25da5aed \ + --hash=sha256:39049da0ffb96c8cbb65cbf5c5f3ca3168990adf3551bd1dee10c48fce8ae820 \ + --hash=sha256:39cf9ed17fe3b1bc81f33c9ceb6ce67683ee7526e65fde1447c772afc54a1bb8 \ + --hash=sha256:3ae1de54a77dc0d6d5fcf623290af4266412a7c4be0b1ff7444394f03f5c54e3 \ + --hash=sha256:3b590df687e3c5ee0deef9fc8c547d81986d9a1b56073d82de008744452d6541 \ + --hash=sha256:3e45867f1f2ab0711d60c6c71746ac53537f1684baa699f4f668d4c6f6ce8e14 \ + --hash=sha256:3fc1c4a2ffd64890aebdb3f97e1278b0cc72579a08ca4de8cd2c04799a3a22be \ + --hash=sha256:4457ea6774b5611f4bed5eaa5df55f70abde42364d498c5134b7ef4c6958e20e \ + --hash=sha256:44ba614de5361b3e5278e1241fda3dc1838deed864b50a10d7ce92983797fa76 \ + --hash=sha256:4a8fcf28c05c1f6d7e177a9a46a1c52798bfe2ad80681d275b10dcf317deaf0b \ + --hash=sha256:4b0d02d7102dd0f997580b51edc4cebcf2ab6397a7edf89f1c73b586c614272c \ + --hash=sha256:502218f52498a36d6bf5ea77081844017bf7982cdbe521ad85e64cabee1b608b \ + --hash=sha256:503e65837c71b875ecdd733877d852adbc465bd82c768a067badd953bf1bc5a3 \ + --hash=sha256:5995f0164fa7df59db4746112fec3f49c461dd6b31b841873443bdb077c13cfc \ + --hash=sha256:59e5686dd847347e55dffcc191a96622f016bc0ad89105e24c14e0d6305acbc6 \ + --hash=sha256:601f36512f9e28f029d9481bdaf8e89e5148ac5d89cffd3b05cd533eeb423b59 \ + --hash=sha256:608862a7bf6957f2333fc54ab4399e405baad0163dc9f8d99cb236816db169d4 \ + --hash=sha256:62595ab75873d50d57323a91dd03e6966eb79c41fa834b7a1661ed043b2d404d \ + --hash=sha256:70990b9c51340e4044cfc394a81f614f3f90d41397104d226f21e66de668730d \ + --hash=sha256:71140351489970dfe5e60fc621ada3e0f41104a5eddaca47a7acb3c1b851d6d3 \ + --hash=sha256:72966d1b297c741541ca8cf1223ff262a6febe52481af742036a0b296e35fa5a \ + --hash=sha256:74292fc76c905c0ef095fe11e188a32ebd03bc38f3f3e9bcb85e4e6db177b7ea \ + --hash=sha256:761e8904c07ad053d285670f36dd94e1b6ab7f16ce62b9805c475b7aa1cffde6 \ + --hash=sha256:772b87914ff1152b92a197ef4ea40efe27a378606c39446ded52c8f80f79702e \ + --hash=sha256:79909e27e8e4fcc9db4addea88aa63f6423ebb171db091fb4373e3312cb6d603 \ + --hash=sha256:7e189e2e1d3ed2f4aebabd2d5b0f931e883676e51c7624826e0a4e5fe8a0bf24 \ + --hash=sha256:7eb33a30d75562222b64f569c642ff3dc6689e09adda43a082208397f016c39a \ + --hash=sha256:81d6741ab457d14fdedc215516665050f3822d3e56508921cc7239f8c8e66a58 \ + --hash=sha256:8499ca8f4502af841f68135133d8258f7b32a53a1d594aa98cc52013fff55678 \ + --hash=sha256:84c3990934bae40ea69a82034912ffe5a62c60bbf6ec5bc9691419641d7d5c9a \ + --hash=sha256:87701167f2a5c930b403e9756fab1d31d4d4da52856143b609e30a1ce7160f3c \ + --hash=sha256:88600c72ef7587fe1708fd242b385b6ed4b8904976d5da0893e31df8b3480cb6 \ + --hash=sha256:8ac7b6a045b814cf0c47f3623d21ebd88b3e8cf216a14790b455ea7ff0135d18 \ + --hash=sha256:8b8af03d2e37866d023ad0ddea594edefc31e827fee64f8de5611a1dbc373174 \ + --hash=sha256:8c7fe7afa480e3e82eed58e0ca89f751cd14d767638e2550c77a92a9e749c317 \ + --hash=sha256:8eade758719add78ec36dc13201483f8e9b5d940329285edcd5f70c0a9edbd7f \ + --hash=sha256:911d8a40b2bef5b8bbae2e36a0b103f142ac53557ab421dc16ac4aafee6f53dc \ + --hash=sha256:93ad6d87ac18e2a90b0fe89df7c65263b9a99a0eb98f0a3d2e079f12a0735837 \ + --hash=sha256:95dea361dd73757c6f1c0a1480ac499952c16ac83f7f5f4f84f0658a01b8ef41 \ + --hash=sha256:9ab77acb98eba3fd2a85cd160851816bfce6871d944d885febf012713f06659c \ + --hash=sha256:9cb3032517f1627cc012dbc80a8ec976ae76d93ea2b5feaa9d2a5b8882597579 \ + --hash=sha256:9cf4e8ad252f7c38dd1f676b46514f92dc0ebeb0db5552f5f403509705e24753 \ + --hash=sha256:9d9153257a3f70d5f69edf2325357251ed20f772b12e593f3b3377b5f78e7ef8 \ + --hash=sha256:a152f5f33d64a6be73f1d30c9cc82dfc73cec6477ec268e7c6e4c7d23c2d2291 \ + --hash=sha256:a16418ecf1329f71df119e8a65f3aa68004a3f9383821edcb20f0702934d8087 \ + --hash=sha256:a60332922359f920193b1d4826953c507a877b523b2395ad7bc716ddd386d866 \ + --hash=sha256:a8d0fc946c784ff7f7c3742310cc8a57c5c6dc31631269876a88b809dbeff3d3 \ + --hash=sha256:ab5de034a886f616a5668aa5d098af2b5385ed70142090e2a31bcbd0af0fdb3d \ + --hash=sha256:c22d3fe05ce11d3671297dc8973267daa0f938b93ec716e12e0f6dee81591dc1 \ + --hash=sha256:c2ac1b08635a8cd4e0cbeaf6f5e922085908d48eb05d44c5ae9eabab148512ca \ + --hash=sha256:c512accbd6ff0270939b9ac214b84fb5ada5f0409c44298361b2f5e13f9aed9e \ + --hash=sha256:c75ffc45f25324e68ab238cb4b5c0a38cd1c3d7f1fb1f72b5541de469e2247db \ + --hash=sha256:c95a03c79bbe30eec3ec2b7f076074f4281526724c8685a42872974ef4d36b72 \ + --hash=sha256:cadaeaba78750d58d3cc6ac4d1fd867da6fc73c88156b7a3212a3cd4819d679d \ + --hash=sha256:cd6056167405314a4dc3c173943f11249fa0f1b204f8b51ed4bde1a9cd1834dc \ + --hash=sha256:db72b07027db150f468fbada4d85b3b2729a3db39178abf5c543b784c1254539 \ + --hash=sha256:df2c707231459e8a4028eabcd3cfc827befd635b3ef72eada84ab13b52e1574d \ + --hash=sha256:e62164b50f84e20601c1ff8eb55620d2ad25fb81b59e3cd776a1902527a788af \ + --hash=sha256:e696f0dd336161fca9adbb846875d40752e6eba585843c768935ba5c9960722b \ + --hash=sha256:eaa379fcd227ca235d04152ca6704c7cb55564116f8bc52545ff357628e10602 \ + --hash=sha256:ebea339af930f8ca5d7a699b921106c6e29c617fe9606fa7baa043c1cdae326f \ + --hash=sha256:f4c39b0e3eac288fedc2b43055cfc2ca7a60362d0e5e87a637beac5d801ef478 \ + --hash=sha256:f5057856d21e7586765171eac8b9fc3f7d44ef39425f85dbcccb13b3ebea806c \ + --hash=sha256:f6f45710b4459401609ebebdbcfb34515da4fc2aa886f95107f556ac69a9147e \ + --hash=sha256:f97e83fa6c25693c7a35de154681fcc257c1c41b38beb0304b9c4d2d9e164479 \ + --hash=sha256:f9d0c5c045a3ca9bedfc35dca8526798eb91a07aa7a2c0fee134c6c6f321cbd7 \ + --hash=sha256:ff6f3db31555657f3163b15a6b7c6938d08df7adbfc9dd13d9d19edad678f1e8 + # via requests +docutils==0.19 \ + --hash=sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6 \ + --hash=sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc + # via readme-renderer +idna==3.4 \ + --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ + --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 + # via requests +importlib-metadata==6.0.0 \ + --hash=sha256:7efb448ec9a5e313a57655d35aa54cd3e01b7e1fbcf72dce1bf06119420f5bad \ + --hash=sha256:e354bedeb60efa6affdcc8ae121b73544a7aa74156d047311948f6d711cd378d + # via + # keyring + # twine +jaraco-classes==3.2.3 \ + --hash=sha256:2353de3288bc6b82120752201c6b1c1a14b058267fa424ed5ce5984e3b922158 \ + --hash=sha256:89559fa5c1d3c34eff6f631ad80bb21f378dbcbb35dd161fd2c6b93f5be2f98a + # via keyring +keyring==23.13.1 \ + --hash=sha256:771ed2a91909389ed6148631de678f82ddc73737d85a927f382a8a1b157898cd \ + --hash=sha256:ba2e15a9b35e21908d0aaf4e0a47acc52d6ae33444df0da2b49d41a46ef6d678 + # via twine +markdown-it-py==2.1.0 \ + --hash=sha256:93de681e5c021a432c63147656fe21790bc01231e0cd2da73626f1aa3ac0fe27 \ + --hash=sha256:cf7e59fed14b5ae17c0006eff14a2d9a00ed5f3a846148153899a0224e2c07da + # via rich +mdurl==0.1.2 \ + --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ + --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba + # via markdown-it-py +more-itertools==9.0.0 \ + --hash=sha256:250e83d7e81d0c87ca6bd942e6aeab8cc9daa6096d12c5308f3f92fa5e5c1f41 \ + --hash=sha256:5a6257e40878ef0520b1803990e3e22303a41b5714006c32a3fd8304b26ea1ab + # via jaraco-classes +pkginfo==1.9.6 \ + --hash=sha256:4b7a555a6d5a22169fcc9cf7bfd78d296b0361adad412a346c1226849af5e546 \ + --hash=sha256:8fd5896e8718a4372f0ea9cc9d96f6417c9b986e23a4d116dda26b62cc29d046 + # via twine +pygments==2.14.0 \ + --hash=sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297 \ + --hash=sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717 + # via + # readme-renderer + # rich +pywin32-ctypes==0.2.0 \ + --hash=sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942 \ + --hash=sha256:9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98 + # via keyring +readme-renderer==37.3 \ + --hash=sha256:cd653186dfc73055656f090f227f5cb22a046d7f71a841dfa305f55c9a513273 \ + --hash=sha256:f67a16caedfa71eef48a31b39708637a6f4664c4394801a7b0d6432d13907343 + # via twine +requests==2.28.2 \ + --hash=sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa \ + --hash=sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf + # via + # requests-toolbelt + # twine +requests-toolbelt==0.10.1 \ + --hash=sha256:18565aa58116d9951ac39baa288d3adb5b3ff975c4f25eee78555d89e8f247f7 \ + --hash=sha256:62e09f7ff5ccbda92772a29f394a49c3ad6cb181d568b1337626b2abb628a63d + # via twine +rfc3986==2.0.0 \ + --hash=sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd \ + --hash=sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c + # via twine +rich==13.2.0 \ + --hash=sha256:7c963f0d03819221e9ac561e1bc866e3f95a02248c1234daa48954e6d381c003 \ + --hash=sha256:f1a00cdd3eebf999a15d85ec498bfe0b1a77efe9b34f645768a54132ef444ac5 + # via twine +six==1.16.0 \ + --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ + --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 + # via bleach +twine==4.0.2 \ + --hash=sha256:929bc3c280033347a00f847236564d1c52a3e61b1ac2516c97c48f3ceab756d8 \ + --hash=sha256:9e102ef5fdd5a20661eb88fad46338806c3bd32cf1db729603fe3697b1bc83c8 + # via -r tools/publish/requirements.in +urllib3==1.26.14 \ + --hash=sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72 \ + --hash=sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1 + # via + # requests + # twine +webencodings==0.5.1 \ + --hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \ + --hash=sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923 + # via bleach +zipp==3.11.0 \ + --hash=sha256:83a28fcb75844b5c0cdaf5aa4003c2d728c77e05f5aeabe8e95e56727005fbaa \ + --hash=sha256:a7a22e05929290a67401440b39690ae6563279bced5f314609d9d03798f56766 + # via importlib-metadata From c4d8cf48fcd87a084e75710f713108f4a65d19fa Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Tue, 7 Feb 2023 17:49:52 -0600 Subject: [PATCH 157/234] release: publish our runfiles wheel to pypi (#1048) --- .github/workflows/release.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1e89fa85a2..eb23bc8411 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,6 +28,14 @@ jobs: uses: actions/checkout@v2 - name: Create release archive and notes run: .github/workflows/create_archive_and_notes.sh + - name: Publish wheel dist + env: + # This special value tells pypi that the user identity is supplied within the token + TWINE_USERNAME: __token__ + # Note, the PYPI_API_TOKEN is for the rules-python pypi user, added by @rickylev on + # https://github.com/bazelbuild/rules_python/settings/secrets/actions + TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} + run: bazel run --stamp --embed_label=${{ github.ref_name }} //python/runfiles:wheel.publish - name: Release uses: softprops/action-gh-release@v1 with: From 339c7e262fe0a7f8ca53b41a5de624f15b4d7984 Mon Sep 17 00:00:00 2001 From: Matt Date: Wed, 8 Feb 2023 15:56:25 +1100 Subject: [PATCH 158/234] Add requires-network to pip requirements update. (#1050) :requirements_test would previously fail if sandboxing was enabled. --- python/pip_install/requirements.bzl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/pip_install/requirements.bzl b/python/pip_install/requirements.bzl index 35399da4ff..51e34a2246 100644 --- a/python/pip_install/requirements.bzl +++ b/python/pip_install/requirements.bzl @@ -101,6 +101,8 @@ def compile_pip_requirements( requirement("more_itertools"), ] + extra_deps + tags = tags or [] + tags.append("requires-network") attrs = { "args": args, "data": data, From 13a912095ed2959f5a1b17ecda75b2382382dfd5 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Tue, 7 Feb 2023 20:57:26 -0800 Subject: [PATCH 159/234] Document the pypi user and how to manage it. (#1049) * Document the pypi user and how to manage it. The mention in the release config isn't easily found and I want to make sure there is some reference for how to manage the account. * Revert "Document the pypi user and how to manage it." This reverts commit bfcb3acb82a62c52eb84b60d8af05d90c1d291b9. * Document the pypi user and how to manage it. This time without reformating everything. --- DEVELOPING.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/DEVELOPING.md b/DEVELOPING.md index 96db780e7e..092e3efeaf 100644 --- a/DEVELOPING.md +++ b/DEVELOPING.md @@ -21,4 +21,12 @@ those with only bug fixes and other minor changes bump the patch digit. #### After release creation in Github 1. Ping @philwo to get the new release added to mirror.bazel.build. See [this comment on issue #400](https://github.com/bazelbuild/rules_python/issues/400#issuecomment-779159530) for more context. -1. Announce the release in the #python channel in the Bazel slack (bazelbuild.slack.com). +1. Announce the release in the #python channel in the Bazel slack (bazelbuild.slack.com). + +## Secrets + +### PyPI user rules-python + +Part of the release process uploads packages to PyPI as the user `rules-python`. +This account is managed by Google; contact rules-python-pyi@google.com if +something needs to be done with the PyPI account. From 6c8ae765564b27f202b12700e4cc91ed494bd82c Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Wed, 8 Feb 2023 10:33:37 -0600 Subject: [PATCH 160/234] fix(release): wrong replacement for $(location) during code review (#1051) --- python/runfiles/BUILD.bazel | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/python/runfiles/BUILD.bazel b/python/runfiles/BUILD.bazel index 835c9b4ae2..19d7804c06 100644 --- a/python/runfiles/BUILD.bazel +++ b/python/runfiles/BUILD.bazel @@ -52,12 +52,16 @@ py_wheel( ) # TODO(alexeagle): carry forward #1015 to make this part of the py_wheel macro +# Typical command-line to run this: +# TWINE_USERNAME=__token__ TWINE_PASSWORD=pypi-*** \ +# bazel run --stamp --embed_label=1.2.4 -- \ +# //python/runfiles:wheel.publish --repository testpypi py_binary( name = "wheel.publish", srcs = ["@publish_deps_twine//:rules_python_wheel_entry_point_twine.py"], args = [ "upload", - "$(execpath :wheel.dist)/*", + "$(rootpath :wheel.dist)/*", ], data = [":wheel.dist"], imports = ["."], From d9ed9c978dccc28ca13e1ba6593f16604907f017 Mon Sep 17 00:00:00 2001 From: Zhongpeng Lin Date: Wed, 8 Feb 2023 19:14:35 -0800 Subject: [PATCH 161/234] Making exclusions more strict (#1054) --- gazelle/python/configure.go | 2 +- gazelle/python/generate.go | 9 ++++--- gazelle/python/python_test.go | 26 ++++++-------------- gazelle/python/testdata/monorepo/a/BUILD.in | 1 + gazelle/python/testdata/monorepo/a/BUILD.out | 1 + gazelle/python/testdata/monorepo/a/README.md | 3 +++ 6 files changed, 19 insertions(+), 23 deletions(-) create mode 100644 gazelle/python/testdata/monorepo/a/BUILD.in create mode 100644 gazelle/python/testdata/monorepo/a/BUILD.out create mode 100644 gazelle/python/testdata/monorepo/a/README.md diff --git a/gazelle/python/configure.go b/gazelle/python/configure.go index 901c226782..32f9ab0a11 100644 --- a/gazelle/python/configure.go +++ b/gazelle/python/configure.go @@ -103,7 +103,7 @@ func (py *Configurer) Configure(c *config.Config, rel string, f *rule.File) { case "exclude": // We record the exclude directive for coarse-grained packages // since we do manual tree traversal in this mode. - config.AddExcludedPattern(strings.TrimSpace(d.Value)) + config.AddExcludedPattern(filepath.Join(rel, strings.TrimSpace(d.Value))) case pythonconfig.PythonExtensionDirective: switch d.Value { case "enabled": diff --git a/gazelle/python/generate.go b/gazelle/python/generate.go index 3d63124028..26ffedaca2 100644 --- a/gazelle/python/generate.go +++ b/gazelle/python/generate.go @@ -161,13 +161,14 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } if filepath.Ext(path) == ".py" { if cfg.CoarseGrainedGeneration() || !isEntrypointFile(path) { - f, _ := filepath.Rel(args.Dir, path) + srcPath, _ := filepath.Rel(args.Dir, path) + repoPath := filepath.Join(args.Rel, srcPath) excludedPatterns := cfg.ExcludedPatterns() if excludedPatterns != nil { it := excludedPatterns.Iterator() for it.Next() { excludedPattern := it.Value().(string) - isExcluded, err := doublestar.Match(excludedPattern, f) + isExcluded, err := doublestar.Match(excludedPattern, repoPath) if err != nil { return err } @@ -178,9 +179,9 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } baseName := filepath.Base(path) if strings.HasSuffix(baseName, "_test.py") || strings.HasPrefix(baseName, "test_") { - pyTestFilenames.Add(f) + pyTestFilenames.Add(srcPath) } else { - pyLibraryFilenames.Add(f) + pyLibraryFilenames.Add(srcPath) } } } diff --git a/gazelle/python/python_test.go b/gazelle/python/python_test.go index e8edf89275..51e0101df1 100644 --- a/gazelle/python/python_test.go +++ b/gazelle/python/python_test.go @@ -23,7 +23,6 @@ import ( "bytes" "context" "errors" - "fmt" "os" "os/exec" "path/filepath" @@ -33,7 +32,6 @@ import ( "github.com/bazelbuild/bazel-gazelle/testtools" "github.com/bazelbuild/rules_go/go/tools/bazel" - "github.com/emirpasic/gods/lists/singlylinkedlist" "github.com/ghodss/yaml" ) @@ -161,31 +159,23 @@ func testPath(t *testing.T, name string, files []bazel.RunfileEntry) { t.Fatal(err) } } - errs := singlylinkedlist.New() + actualExitCode := cmd.ProcessState.ExitCode() if config.Expect.ExitCode != actualExitCode { - errs.Add(fmt.Errorf("expected gazelle exit code: %d\ngot: %d", - config.Expect.ExitCode, actualExitCode, - )) + t.Errorf("expected gazelle exit code: %d\ngot: %d", + config.Expect.ExitCode, actualExitCode) } actualStdout := stdout.String() if strings.TrimSpace(config.Expect.Stdout) != strings.TrimSpace(actualStdout) { - errs.Add(fmt.Errorf("expected gazelle stdout: %s\ngot: %s", - config.Expect.Stdout, actualStdout, - )) + t.Errorf("expected gazelle stdout: %s\ngot: %s", + config.Expect.Stdout, actualStdout) } actualStderr := stderr.String() if strings.TrimSpace(config.Expect.Stderr) != strings.TrimSpace(actualStderr) { - errs.Add(fmt.Errorf("expected gazelle stderr: %s\ngot: %s", - config.Expect.Stderr, actualStderr, - )) + t.Errorf("expected gazelle stderr: %s\ngot: %s", + config.Expect.Stderr, actualStderr) } - if !errs.Empty() { - errsIt := errs.Iterator() - for errsIt.Next() { - err := errsIt.Value().(error) - t.Log(err) - } + if t.Failed() { t.FailNow() } diff --git a/gazelle/python/testdata/monorepo/a/BUILD.in b/gazelle/python/testdata/monorepo/a/BUILD.in new file mode 100644 index 0000000000..265129ea56 --- /dev/null +++ b/gazelle/python/testdata/monorepo/a/BUILD.in @@ -0,0 +1 @@ +# gazelle:exclude bar/baz/hue.py \ No newline at end of file diff --git a/gazelle/python/testdata/monorepo/a/BUILD.out b/gazelle/python/testdata/monorepo/a/BUILD.out new file mode 100644 index 0000000000..265129ea56 --- /dev/null +++ b/gazelle/python/testdata/monorepo/a/BUILD.out @@ -0,0 +1 @@ +# gazelle:exclude bar/baz/hue.py \ No newline at end of file diff --git a/gazelle/python/testdata/monorepo/a/README.md b/gazelle/python/testdata/monorepo/a/README.md new file mode 100644 index 0000000000..84d3bff052 --- /dev/null +++ b/gazelle/python/testdata/monorepo/a/README.md @@ -0,0 +1,3 @@ +# Exclusions +* Intentionally make the directory "a" so Gazelle visit this before "coarse_grained" +* Making sure that the exclusion here doesn't affect coarse_grained/bar/baz/hue.py \ No newline at end of file From 6bcee35fd72af6c7374318ab24aa71367e5100be Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Thu, 9 Feb 2023 00:49:40 -0600 Subject: [PATCH 162/234] docs: fix requirement line for runfiles example (#1052) The PyPI name is "bazel-runfiles", which is what should be used in `requirement()`; "runfiles" is the import name. --- python/runfiles/README.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/python/runfiles/README.rst b/python/runfiles/README.rst index 59a3852c5f..ac61d2dd80 100644 --- a/python/runfiles/README.rst +++ b/python/runfiles/README.rst @@ -3,10 +3,13 @@ bazel-runfiles library This is a Bazel Runfiles lookup library for Bazel-built Python binaries and tests. +Learn about runfiles: read `Runfiles guide `_ +or watch `Fabian's BazelCon talk `_. + Typical Usage ------------- -1. Add the 'runfiles' dependency along with other third-party dependencies, for example in your +1. Add the 'bazel-runfiles' dependency along with other third-party dependencies, for example in your ``requirements.txt`` file. 2. Depend on this runfiles library from your build rule, like you would other third-party libraries:: @@ -14,7 +17,7 @@ Typical Usage py_binary( name = "my_binary", ... - deps = [requirement("runfiles")], + deps = [requirement("bazel-runfiles")], ) 3. Import the runfiles library:: From 6905e63ee9e63e210db7d1a2b65ebbae12d691d8 Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius Date: Sat, 11 Feb 2023 14:02:33 +0900 Subject: [PATCH 163/234] fix: make py_proto_library respect PyInfo imports (#1046) py_proto_library has an implicitly dependency on the protobuf client runtime, and it was ending up in runfiles, but it wasn't imported because the `imports` value it was setting wasn't be propagated. To fix, make py_proto_library properly propagate the imports attribute the protobuf client runtime so that the libraries are added to sys.path correct. Also adds an example for bzlmod and old way of using the py_proto_library as a test. --------- Co-authored-by: Richard Levasseur --- .bazelci/presubmit.yml | 52 +++++++++++++++++++ .bazelrc | 4 +- examples/BUILD.bazel | 12 +++++ examples/py_proto_library/.bazelrc | 0 examples/py_proto_library/.gitignore | 4 ++ examples/py_proto_library/BUILD.bazel | 22 ++++++++ examples/py_proto_library/MODULE.bazel | 28 ++++++++++ examples/py_proto_library/WORKSPACE | 48 +++++++++++++++++ examples/py_proto_library/WORKSPACE.bzlmod | 0 examples/py_proto_library/pricetag.proto | 8 +++ examples/py_proto_library/test.py | 17 ++++++ python/private/proto/py_proto_library.bzl | 7 +++ .../bazel_integration_test.bzl | 5 +- 13 files changed, 203 insertions(+), 4 deletions(-) create mode 100644 examples/py_proto_library/.bazelrc create mode 100644 examples/py_proto_library/.gitignore create mode 100644 examples/py_proto_library/BUILD.bazel create mode 100644 examples/py_proto_library/MODULE.bazel create mode 100644 examples/py_proto_library/WORKSPACE create mode 100644 examples/py_proto_library/WORKSPACE.bzlmod create mode 100644 examples/py_proto_library/pricetag.proto create mode 100644 examples/py_proto_library/test.py diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 76f9d8b5aa..706c655f73 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -31,6 +31,11 @@ buildifier: - "..." test_flags: - "--test_tag_filters=-integration-test" +.common_bzlmod_flags: &common_bzlmod_flags + test_flags: + - "--experimental_enable_bzlmod" + build_flags: + - "--experimental_enable_bzlmod" .reusable_build_test_all: &reusable_build_test_all build_targets: ["..."] test_targets: ["..."] @@ -211,6 +216,53 @@ tasks: # We don't run pip_parse_vendored under Windows as the file checked in is # generated from a repository rule containing OS-specific rendered paths. + integration_test_py_proto_library_ubuntu: + <<: *reusable_build_test_all + name: py_proto_library integration tests on Ubuntu + working_directory: examples/py_proto_library + platform: ubuntu2004 + integration_test_py_proto_library_debian: + <<: *reusable_build_test_all + name: py_proto_library integration tests on Debian + working_directory: examples/py_proto_library + platform: debian11 + integration_test_py_proto_library_macos: + <<: *reusable_build_test_all + name: py_proto_library integration tests on macOS + working_directory: examples/py_proto_library + platform: macos + integration_test_py_proto_library_windows: + <<: *reusable_build_test_all + name: py_proto_library integration tests on Windows + working_directory: examples/py_proto_library + platform: windows + + # Check the same using bzlmod as well + integration_test_py_proto_library_bzlmod_ubuntu: + <<: *reusable_build_test_all + <<: *common_bzlmod_flags + name: py_proto_library bzlmod integration tests on Ubuntu + working_directory: examples/py_proto_library + platform: ubuntu2004 + integration_test_py_proto_library_bzlmod_debian: + <<: *reusable_build_test_all + <<: *common_bzlmod_flags + name: py_proto_library bzlmod integration tests on Debian + working_directory: examples/py_proto_library + platform: debian11 + integration_test_py_proto_library_bzlmod_macos: + <<: *reusable_build_test_all + <<: *common_bzlmod_flags + name: py_proto_library bzlmod integration tests on macOS + working_directory: examples/py_proto_library + platform: macos + integration_test_py_proto_library_bzlmod_windows: + <<: *reusable_build_test_all + <<: *common_bzlmod_flags + name: py_proto_library bzlmod integration tests on Windows + working_directory: examples/py_proto_library + platform: windows + integration_test_pip_repository_annotations_ubuntu: <<: *reusable_build_test_all name: pip_repository_annotations integration tests on Ubuntu diff --git a/.bazelrc b/.bazelrc index 2dc32594d4..d607cdd9b7 100644 --- a/.bazelrc +++ b/.bazelrc @@ -3,8 +3,8 @@ # This lets us glob() up all the files inside the examples to make them inputs to tests # (Note, we cannot use `common --deleted_packages` because the bazel version command doesn't support it) # To update these lines, run tools/bazel_integration_test/update_deleted_packages.sh -build --deleted_packages=examples/build_file_generation,examples/build_file_generation/get_url,examples/bzlmod,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/runfiles,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps -query --deleted_packages=examples/build_file_generation,examples/build_file_generation/get_url,examples/bzlmod,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/runfiles,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps +build --deleted_packages=examples/build_file_generation,examples/build_file_generation/get_url,examples/bzlmod,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/runfiles,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/py_proto_library,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps +query --deleted_packages=examples/build_file_generation,examples/build_file_generation/get_url,examples/bzlmod,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/runfiles,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/py_proto_library,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps test --test_output=errors diff --git a/examples/BUILD.bazel b/examples/BUILD.bazel index e0a7e5a72d..3ef89054c9 100644 --- a/examples/BUILD.bazel +++ b/examples/BUILD.bazel @@ -43,6 +43,18 @@ bazel_integration_test( timeout = "long", ) +bazel_integration_test( + name = "py_proto_library_example", + timeout = "long", +) + +bazel_integration_test( + name = "py_proto_library_example_bzlmod", + timeout = "long", + bzlmod = True, + dirname = "py_proto_library", +) + bazel_integration_test( name = "multi_python_versions_example", timeout = "long", diff --git a/examples/py_proto_library/.bazelrc b/examples/py_proto_library/.bazelrc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/py_proto_library/.gitignore b/examples/py_proto_library/.gitignore new file mode 100644 index 0000000000..e5ae073b3c --- /dev/null +++ b/examples/py_proto_library/.gitignore @@ -0,0 +1,4 @@ +# git ignore patterns + +/bazel-* +user.bazelrc diff --git a/examples/py_proto_library/BUILD.bazel b/examples/py_proto_library/BUILD.bazel new file mode 100644 index 0000000000..7a18a5e4e1 --- /dev/null +++ b/examples/py_proto_library/BUILD.bazel @@ -0,0 +1,22 @@ +load("@rules_proto//proto:defs.bzl", "proto_library") +load("@rules_python//python:defs.bzl", "py_test") +load("@rules_python//python:proto.bzl", "py_proto_library") + +py_proto_library( + name = "pricetag_proto_py_pb2", + deps = [":pricetag_proto"], +) + +proto_library( + name = "pricetag_proto", + srcs = ["pricetag.proto"], +) + +py_test( + name = "pricetag_test", + srcs = ["test.py"], + main = "test.py", + deps = [ + ":pricetag_proto_py_pb2", + ], +) diff --git a/examples/py_proto_library/MODULE.bazel b/examples/py_proto_library/MODULE.bazel new file mode 100644 index 0000000000..5ce0924a99 --- /dev/null +++ b/examples/py_proto_library/MODULE.bazel @@ -0,0 +1,28 @@ +module( + name = "rules_python_py_proto_library_example", + version = "0.0.0", + compatibility_level = 1, +) + +bazel_dep(name = "rules_python", version = "0.17.3") + +# The following local_path_override is only needed to run this example as part of our CI. +local_path_override( + module_name = "rules_python", + path = "../..", +) + +python = use_extension("@rules_python//python:extensions.bzl", "python") +python.toolchain( + name = "python3_9", + configure_coverage_tool = True, + python_version = "3.9", +) +use_repo(python, "python3_9_toolchains") + +register_toolchains( + "@python3_9_toolchains//:all", +) + +# We are using rules_proto to define rules_proto targets to be consumed by py_proto_library. +bazel_dep(name = "rules_proto", version = "5.3.0-21.7") diff --git a/examples/py_proto_library/WORKSPACE b/examples/py_proto_library/WORKSPACE new file mode 100644 index 0000000000..bf38112f98 --- /dev/null +++ b/examples/py_proto_library/WORKSPACE @@ -0,0 +1,48 @@ +workspace(name = "rules_python_py_proto_library_example") + +# The following local_path_override is only needed to run this example as part of our CI. +local_repository( + name = "rules_python", + path = "../..", +) + +# When not using this example in the rules_python git repo you would load the python +# rules using http_archive(), as documented in the release notes. + +load("@rules_python//python:repositories.bzl", "py_repositories", "python_register_toolchains") + +# We install the rules_python dependencies using the function below. +py_repositories() + +python_register_toolchains( + name = "python39", + python_version = "3.9", +) + +# Then we need to setup dependencies in order to use py_proto_library +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +http_archive( + name = "rules_proto", + sha256 = "dc3fb206a2cb3441b485eb1e423165b231235a1ea9b031b4433cf7bc1fa460dd", + strip_prefix = "rules_proto-5.3.0-21.7", + urls = [ + "https://github.com/bazelbuild/rules_proto/archive/refs/tags/5.3.0-21.7.tar.gz", + ], +) + +http_archive( + name = "com_google_protobuf", + sha256 = "75be42bd736f4df6d702a0e4e4d30de9ee40eac024c4b845d17ae4cc831fe4ae", + strip_prefix = "protobuf-21.7", + urls = [ + "https://mirror.bazel.build/github.com/protocolbuffers/protobuf/archive/v21.7.tar.gz", + "https://github.com/protocolbuffers/protobuf/archive/v21.7.tar.gz", + ], +) + +load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains") + +rules_proto_dependencies() + +rules_proto_toolchains() diff --git a/examples/py_proto_library/WORKSPACE.bzlmod b/examples/py_proto_library/WORKSPACE.bzlmod new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/py_proto_library/pricetag.proto b/examples/py_proto_library/pricetag.proto new file mode 100644 index 0000000000..c952248846 --- /dev/null +++ b/examples/py_proto_library/pricetag.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; + +package rules_python; + +message PriceTag { + string name = 2; + double cost = 1; +} diff --git a/examples/py_proto_library/test.py b/examples/py_proto_library/test.py new file mode 100644 index 0000000000..9f09702f8c --- /dev/null +++ b/examples/py_proto_library/test.py @@ -0,0 +1,17 @@ +import sys +import unittest + +import pricetag_pb2 + + +class TestCase(unittest.TestCase): + def test_pricetag(self): + got = pricetag_pb2.PriceTag( + name="dollar", + cost=5.00, + ) + self.assertIsNotNone(got) + + +if __name__ == "__main__": + unittest.main() diff --git a/python/private/proto/py_proto_library.bzl b/python/private/proto/py_proto_library.bzl index ef5f2cae70..988558500d 100644 --- a/python/private/proto/py_proto_library.bzl +++ b/python/private/proto/py_proto_library.bzl @@ -22,6 +22,9 @@ ProtoLangToolchainInfo = proto_common.ProtoLangToolchainInfo _PyProtoInfo = provider( doc = "Encapsulates information needed by the Python proto rules.", fields = { + "imports": """ + (depset[str]) The field forwarding PyInfo.imports coming from + the proto language runtime dependency.""", "runfiles_from_proto_deps": """ (depset[File]) Files from the transitive closure implicit proto dependencies""", @@ -95,6 +98,9 @@ def _py_proto_aspect_impl(target, ctx): return [ _PyProtoInfo( + imports = depset( + transitive = [dep[PyInfo].imports for dep in api_deps], + ), runfiles_from_proto_deps = runfiles_from_proto_deps, transitive_sources = transitive_sources, ), @@ -142,6 +148,7 @@ def _py_proto_library_rule(ctx): ), PyInfo( transitive_sources = default_outputs, + imports = depset(transitive = [info.imports for info in pyproto_infos]), # Proto always produces 2- and 3- compatible source files has_py2_only_sources = False, has_py3_only_sources = False, diff --git a/tools/bazel_integration_test/bazel_integration_test.bzl b/tools/bazel_integration_test/bazel_integration_test.bzl index 66e0cbded1..c016551319 100644 --- a/tools/bazel_integration_test/bazel_integration_test.bzl +++ b/tools/bazel_integration_test/bazel_integration_test.bzl @@ -84,18 +84,19 @@ _config = rule( attrs = _ATTRS, ) -def bazel_integration_test(name, override_bazel_version = None, bzlmod = False, **kwargs): +def bazel_integration_test(name, override_bazel_version = None, bzlmod = False, dirname = None, **kwargs): """Wrapper macro to set default srcs and run a py_test with config Args: name: name of the resulting py_test override_bazel_version: bazel version to use in test bzlmod: whether the test uses bzlmod + dirname: the directory name of the test. Defaults to value of `name` after trimming the `_example` suffix. **kwargs: additional attributes like timeout and visibility """ # By default, we assume sources for "pip_example" are in examples/pip/**/* - dirname = name[:-len("_example")] + dirname = dirname or name[:-len("_example")] native.filegroup( name = "_%s_sources" % name, srcs = native.glob( From fab77f7781c21e799bedc4a7e2eccb8fd0191916 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Sat, 11 Feb 2023 08:13:34 -0800 Subject: [PATCH 164/234] Make toolchain acceptance tests work with latest Bazel build CI pipeline (#1062) --- .../toolchains/run_acceptance_test.py.tmpl | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/python/tests/toolchains/run_acceptance_test.py.tmpl b/python/tests/toolchains/run_acceptance_test.py.tmpl index b3071a7b3c..150e1a99df 100644 --- a/python/tests/toolchains/run_acceptance_test.py.tmpl +++ b/python/tests/toolchains/run_acceptance_test.py.tmpl @@ -23,9 +23,8 @@ class TestPythonVersion(unittest.TestCase): os.chdir("%test_location%") rules_python_path = os.path.join(os.environ["TEST_SRCDIR"], "rules_python") + test_tmpdir = os.environ["TEST_TMPDIR"] if %is_windows%: - test_tmpdir = os.environ["TEST_TMPDIR"] - home = os.path.join(test_tmpdir, "HOME") os.mkdir(home) os.environ["HOME"] = home @@ -34,6 +33,16 @@ class TestPythonVersion(unittest.TestCase): os.mkdir(local_app_data) os.environ["LocalAppData"] = local_app_data + # Bazelisk requires a cache directory be set + os.environ["XDG_CACHE_HOME"] = os.path.join(test_tmpdir, "xdg-cache-home") + + # Unset this so this works when called by Bazel's latest Bazel build + # pipeline. It sets the following combination, which interfere with each other: + # * --sandbox_tmpfs_path=/tmp + # * --test_env=USE_BAZEL_VERSION + # * USE_BAZEL_VERSION=/tmp/ + os.environ.pop("USE_BAZEL_VERSION", None) + with open(".bazelrc", "w") as bazelrc: bazelrc.write( os.linesep.join( @@ -47,8 +56,11 @@ class TestPythonVersion(unittest.TestCase): ) def test_match_toolchain(self): - stream = os.popen("bazel run @python//:python3 -- --version") - output = stream.read().strip() + output = subprocess.check_output( + f"bazel run @python//:python3 -- --version", + shell = True, # Shell needed to look up via PATH + text=True, + ).strip() self.assertEqual(output, "Python %python_version%") subprocess.run("bazel test //...", shell=True, check=True) From 4f8ca60cce4ca74b56b5b713bc445d87c844a673 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Sat, 11 Feb 2023 09:13:18 -0800 Subject: [PATCH 165/234] Only set `py_runtime.coverage_tool` for Bazel 6 and higher. (#1061) Only set `py_runtime.coverage_tool` for Bazel 6 and higher. Avoid setting it in earlier version by checking `native.bazel_version` in the repository rule and disabling it if less than Bazel 6 is detected. A warning is also printed if coverage was requested, but the Bazel version check is ignoring it. Fixes #1056 --- python/repositories.bzl | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/python/repositories.bzl b/python/repositories.bzl index e61b057d22..df72497d91 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -243,6 +243,21 @@ def _python_repository_impl(rctx): "share/**", ] + if rctx.attr.coverage_tool: + if "windows" in rctx.os.name: + coverage_tool = None + else: + coverage_tool = '"{}"'.format(rctx.attr.coverage_tool) + + coverage_attr_text = """\ + coverage_tool = select({{ + ":coverage_enabled": {coverage_tool}, + "//conditions:default": None + }}), +""".format(coverage_tool = coverage_tool) + else: + coverage_attr_text = " # coverage_tool attribute not supported by this Bazel version" + build_content = """\ # Generated by python/repositories.bzl @@ -308,10 +323,7 @@ config_setting( py_runtime( name = "py3_runtime", files = [":files"], - coverage_tool = select({{ - ":coverage_enabled": {coverage_tool}, - "//conditions:default": None, - }}), +{coverage_attr} interpreter = "{python_path}", python_version = "PY3", ) @@ -327,7 +339,7 @@ py_runtime_pair( python_path = python_bin, python_version = python_short_version, python_version_nodot = python_short_version.replace(".", ""), - coverage_tool = rctx.attr.coverage_tool if rctx.attr.coverage_tool == None or "windows" in rctx.os.name else "\"{}\"".format(rctx.attr.coverage_tool), + coverage_attr = coverage_attr_text, ) rctx.delete("python") rctx.symlink(python_bin, "python") @@ -459,6 +471,8 @@ def python_register_toolchains( distutils_content: see the distutils_content attribute in the python_repository repository rule. register_toolchains: Whether or not to register the downloaded toolchains. register_coverage_tool: Whether or not to register the downloaded coverage tool to the toolchains. + NOTE: Coverage support using the toolchain is only supported in Bazel 6 and higher. + set_python_version_constraint: When set to true, target_compatible_with for the toolchains will include a version constraint. tool_versions: a dict containing a mapping of version with SHASUM and platform info. If not supplied, the defaults in python/versions.bzl will be used. @@ -472,6 +486,19 @@ def python_register_toolchains( toolchain_repo_name = "{name}_toolchains".format(name = name) + bazel_major = int(native.bazel_version.split(".")[0]) + if bazel_major < 6: + if register_coverage_tool: + # buildifier: disable=print + print(( + "WARNING: ignoring register_coverage_tool=True when " + + "registering @{name}: Bazel 6+ required, got {version}" + ).format( + name = name, + version = native.bazel_version, + )) + register_coverage_tool = False + for platform in PLATFORMS.keys(): sha256 = tool_versions[python_version]["sha256"].get(platform, None) if not sha256: From aef1abfacde34bcff22b4b6481998866a346917b Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Sat, 11 Feb 2023 11:24:07 -0800 Subject: [PATCH 166/234] Allow building with unreleased Bazel versions. (#1063) --- python/repositories.bzl | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/python/repositories.bzl b/python/repositories.bzl index df72497d91..f676610ae2 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -486,18 +486,20 @@ def python_register_toolchains( toolchain_repo_name = "{name}_toolchains".format(name = name) - bazel_major = int(native.bazel_version.split(".")[0]) - if bazel_major < 6: - if register_coverage_tool: - # buildifier: disable=print - print(( - "WARNING: ignoring register_coverage_tool=True when " + - "registering @{name}: Bazel 6+ required, got {version}" - ).format( - name = name, - version = native.bazel_version, - )) - register_coverage_tool = False + # When using unreleased Bazel versions, the version is an empty string + if native.bazel_version: + bazel_major = int(native.bazel_version.split(".")[0]) + if bazel_major < 6: + if register_coverage_tool: + # buildifier: disable=print + print(( + "WARNING: ignoring register_coverage_tool=True when " + + "registering @{name}: Bazel 6+ required, got {version}" + ).format( + name = name, + version = native.bazel_version, + )) + register_coverage_tool = False for platform in PLATFORMS.keys(): sha256 = tool_versions[python_version]["sha256"].get(platform, None) From 2f29f1243ca6dd65688fc2053cf6efc46a3e2c01 Mon Sep 17 00:00:00 2001 From: Zhongpeng Lin Date: Mon, 13 Feb 2023 12:35:50 -0800 Subject: [PATCH 167/234] Extending server process timeout (#1060) --- gazelle/python/parser.go | 2 +- gazelle/python/std_modules.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gazelle/python/parser.go b/gazelle/python/parser.go index 3809a461cd..33eb6f4b33 100644 --- a/gazelle/python/parser.go +++ b/gazelle/python/parser.go @@ -46,7 +46,7 @@ func init() { } ctx := context.Background() - ctx, parserCancel := context.WithTimeout(ctx, time.Minute*5) + ctx, parserCancel := context.WithTimeout(ctx, time.Minute*10) cmd := exec.CommandContext(ctx, parseScriptRunfile) cmd.Stderr = os.Stderr diff --git a/gazelle/python/std_modules.go b/gazelle/python/std_modules.go index 17bc5263ae..94ef45666e 100644 --- a/gazelle/python/std_modules.go +++ b/gazelle/python/std_modules.go @@ -47,7 +47,7 @@ func init() { } ctx := context.Background() - ctx, stdModulesCancel := context.WithTimeout(ctx, time.Minute*5) + ctx, stdModulesCancel := context.WithTimeout(ctx, time.Minute*10) cmd := exec.CommandContext(ctx, stdModulesScriptRunfile) cmd.Stderr = os.Stderr From e35cd882386fad30e29354e738ce547ab2600d73 Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius Date: Tue, 14 Feb 2023 05:36:32 +0900 Subject: [PATCH 168/234] chore: regenerate gazelle_python.yaml manifest (#1066) --- examples/build_file_generation/gazelle_python.yaml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/examples/build_file_generation/gazelle_python.yaml b/examples/build_file_generation/gazelle_python.yaml index 9953ad3936..847d1ecc55 100644 --- a/examples/build_file_generation/gazelle_python.yaml +++ b/examples/build_file_generation/gazelle_python.yaml @@ -1,17 +1,3 @@ -# Copyright 2023 The Bazel Authors. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - # GENERATED FILE - DO NOT EDIT! # # To update this file, run: From 00513936230ddb0d3a77728584c82ce9dde2ae89 Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Mon, 13 Feb 2023 14:17:05 -0800 Subject: [PATCH 169/234] feat: wheel publishing (#1015) feat: add a .publish target to py_wheel macro --- docs/packaging.md | 28 +++++++++++++++++++- python/packaging.bzl | 51 +++++++++++++++++++++++++++++++++++-- python/runfiles/BUILD.bazel | 21 ++------------- 3 files changed, 78 insertions(+), 22 deletions(-) diff --git a/docs/packaging.md b/docs/packaging.md index a7a65ab7f8..b244b42767 100755 --- a/docs/packaging.md +++ b/docs/packaging.md @@ -121,7 +121,7 @@ Information about a wheel produced by `py_wheel` ## py_wheel
-py_wheel(name, kwargs)
+py_wheel(name, twine, kwargs)
 
Builds a Python Wheel. @@ -168,6 +168,31 @@ py_wheel( ) ``` +To publish the wheel to Pypi, the twine package is required. +rules_python doesn't provide twine itself, see https://github.com/bazelbuild/rules_python/issues/1016 +However you can install it with pip_parse, just like we do in the WORKSPACE file in rules_python. + +Once you've installed twine, you can pass its label to the `twine` attribute of this macro, +to get a "[name].publish" target. + +Example: + +```python +py_wheel( + name = "my_wheel", + twine = "@publish_deps_twine//:pkg", + ... +) +``` + +Now you can run a command like the following, which publishes to https://test.pypi.org/ + +```sh +% TWINE_USERNAME=__token__ TWINE_PASSWORD=pypi-*** \ + bazel run --stamp --embed_label=1.2.4 -- \ + //path/to:my_wheel.publish --repository testpypi +``` + **PARAMETERS** @@ -175,6 +200,7 @@ py_wheel( | Name | Description | Default Value | | :------------- | :------------- | :------------- | | name | A unique name for this target. | none | +| twine | A label of the external location of the py_library target for twine | None | | kwargs | other named parameters passed to the underlying [py_wheel rule](#py_wheel_rule) | none | diff --git a/python/packaging.bzl b/python/packaging.bzl index 92745792a5..1984eb7b4b 100644 --- a/python/packaging.bzl +++ b/python/packaging.bzl @@ -68,7 +68,7 @@ This also has the advantage that stamping information is included in the wheel's }, ) -def py_wheel(name, **kwargs): +def py_wheel(name, twine = None, **kwargs): """Builds a Python Wheel. Wheels are Python distribution format defined in https://www.python.org/dev/peps/pep-0427/. @@ -113,16 +113,63 @@ def py_wheel(name, **kwargs): ) ``` + To publish the wheel to Pypi, the twine package is required. + rules_python doesn't provide twine itself, see https://github.com/bazelbuild/rules_python/issues/1016 + However you can install it with pip_parse, just like we do in the WORKSPACE file in rules_python. + + Once you've installed twine, you can pass its label to the `twine` attribute of this macro, + to get a "[name].publish" target. + + Example: + + ```python + py_wheel( + name = "my_wheel", + twine = "@publish_deps_twine//:pkg", + ... + ) + ``` + + Now you can run a command like the following, which publishes to https://test.pypi.org/ + + ```sh + % TWINE_USERNAME=__token__ TWINE_PASSWORD=pypi-*** \\ + bazel run --stamp --embed_label=1.2.4 -- \\ + //path/to:my_wheel.publish --repository testpypi + ``` + Args: name: A unique name for this target. + twine: A label of the external location of the py_library target for twine **kwargs: other named parameters passed to the underlying [py_wheel rule](#py_wheel_rule) """ + _dist_target = "{}.dist".format(name) py_wheel_dist( - name = "{}.dist".format(name), + name = _dist_target, wheel = name, out = kwargs.pop("dist_folder", "{}_dist".format(name)), ) _py_wheel(name = name, **kwargs) + if twine: + if not twine.endswith(":pkg"): + fail("twine label should look like @my_twine_repo//:pkg") + twine_main = twine.replace(":pkg", ":rules_python_wheel_entry_point_twine.py") + + # TODO: use py_binary from //python:defs.bzl after our stardoc setup is less brittle + # buildifier: disable=native-py + native.py_binary( + name = "{}.publish".format(name), + srcs = [twine_main], + args = [ + "upload", + "$(rootpath :{})/*".format(_dist_target), + ], + data = [_dist_target], + imports = ["."], + main = twine_main, + deps = [twine], + ) + py_wheel_rule = _py_wheel diff --git a/python/runfiles/BUILD.bazel b/python/runfiles/BUILD.bazel index 19d7804c06..3a93d40f32 100644 --- a/python/runfiles/BUILD.bazel +++ b/python/runfiles/BUILD.bazel @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -load("//python:defs.bzl", "py_binary", "py_library") +load("//python:defs.bzl", "py_library") load("//python:packaging.bzl", "py_wheel") filegroup( @@ -45,26 +45,9 @@ py_wheel( distribution = "bazel_runfiles", homepage = "https://github.com/bazelbuild/rules_python", strip_path_prefixes = ["python"], + twine = "@publish_deps_twine//:pkg", # this can be replaced by building with --stamp --embed_label=1.2.3 version = "{BUILD_EMBED_LABEL}", visibility = ["//visibility:public"], deps = [":runfiles"], ) - -# TODO(alexeagle): carry forward #1015 to make this part of the py_wheel macro -# Typical command-line to run this: -# TWINE_USERNAME=__token__ TWINE_PASSWORD=pypi-*** \ -# bazel run --stamp --embed_label=1.2.4 -- \ -# //python/runfiles:wheel.publish --repository testpypi -py_binary( - name = "wheel.publish", - srcs = ["@publish_deps_twine//:rules_python_wheel_entry_point_twine.py"], - args = [ - "upload", - "$(rootpath :wheel.dist)/*", - ], - data = [":wheel.dist"], - imports = ["."], - main = "@publish_deps_twine//:rules_python_wheel_entry_point_twine.py", - deps = ["@publish_deps_twine//:pkg"], -) From 767b050e45c49e63cfe103e6b97f7e2fd9be5e2e Mon Sep 17 00:00:00 2001 From: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Date: Mon, 13 Feb 2023 14:58:53 -0800 Subject: [PATCH 170/234] fix: checked-in requirements imports generated requirements (#1053) * fix: checked-in requirements imports generated requirements Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: shutil.copy instead of shutil.copyfile This allows copying from one filesystem to another, as the `os.rename` (used by copyfile) doesn't work with multiple filesystems. Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: patch os.replace to use shutil.copy Same as the previous commit. Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: runfiles.Rlocation requires paths to be normalized Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: drop rules_python from import This is not compatible with bzlmod. Importing python.runfiles works for both ways. Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: remove unnecessary runfiles Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * doc: why os.replace = shutil.copy Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: allow the test to still be remote cacheable Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * doc: why shutil.copy Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * doc: add missing punctuation Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: remove unnecessary _fix_up_requirements_in_path Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * test: make sure the locked requirements is updated Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: copy requirements back into src tree if needed Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> * fix: make sure windows uses forward slashes Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --------- Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- .bazelci/presubmit.yml | 28 ++++++ python/pip_install/requirements.bzl | 2 + .../dependency_resolver.py | 89 +++++++++---------- tests/compile_pip_requirements/BUILD.bazel | 3 +- .../compile_pip_requirements/requirements.txt | 1 + tools/publish/BUILD.bazel | 8 -- 6 files changed, 76 insertions(+), 55 deletions(-) create mode 100644 tests/compile_pip_requirements/requirements.txt diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 706c655f73..5f92fbff04 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -289,21 +289,49 @@ tasks: name: compile_pip_requirements integration tests on Ubuntu working_directory: tests/compile_pip_requirements platform: ubuntu2004 + shell_commands: + # Make a change to the locked requirements and then assert that //:requirements.update does the + # right thing. + - "echo '' > requirements_lock.txt" + - "! git diff --exit-code" + - "bazel run //:requirements.update" + - "git diff --exit-code" integration_test_compile_pip_requirements_debian: <<: *reusable_build_test_all name: compile_pip_requirements integration tests on Debian working_directory: tests/compile_pip_requirements platform: debian11 + shell_commands: + # Make a change to the locked requirements and then assert that //:requirements.update does the + # right thing. + - "echo '' > requirements_lock.txt" + - "! git diff --exit-code" + - "bazel run //:requirements.update" + - "git diff --exit-code" integration_test_compile_pip_requirements_macos: <<: *reusable_build_test_all name: compile_pip_requirements integration tests on macOS working_directory: tests/compile_pip_requirements platform: macos + shell_commands: + # Make a change to the locked requirements and then assert that //:requirements.update does the + # right thing. + - "echo '' > requirements_lock.txt" + - "! git diff --exit-code" + - "bazel run //:requirements.update" + - "git diff --exit-code" integration_test_compile_pip_requirements_windows: <<: *reusable_build_test_all name: compile_pip_requirements integration tests on Windows working_directory: tests/compile_pip_requirements platform: windows + shell_commands: + # Make a change to the locked requirements and then assert that //:requirements.update does the + # right thing. + - "echo '' > requirements_lock.txt" + - "! git diff --exit-code" + - "bazel run //:requirements.update" + - "git diff --exit-code" integration_test_pip_repository_entry_points_ubuntu: <<: *reusable_build_test_all diff --git a/python/pip_install/requirements.bzl b/python/pip_install/requirements.bzl index 51e34a2246..af3c194d18 100644 --- a/python/pip_install/requirements.bzl +++ b/python/pip_install/requirements.bzl @@ -103,6 +103,8 @@ def compile_pip_requirements( tags = tags or [] tags.append("requires-network") + tags.append("no-remote-exec") + tags.append("no-sandbox") attrs = { "args": args, "data": data, diff --git a/python/pip_install/tools/dependency_resolver/dependency_resolver.py b/python/pip_install/tools/dependency_resolver/dependency_resolver.py index db84977a0d..e636febd93 100644 --- a/python/pip_install/tools/dependency_resolver/dependency_resolver.py +++ b/python/pip_install/tools/dependency_resolver/dependency_resolver.py @@ -14,14 +14,39 @@ "Set defaults for the pip-compile command to run it under Bazel" +import atexit import os -import re +import shutil import sys from pathlib import Path -from shutil import copyfile +import piptools.writer as piptools_writer from piptools.scripts.compile import cli +# Replace the os.replace function with shutil.copy to work around os.replace not being able to +# replace or move files across filesystems. +os.replace = shutil.copy + +# Next, we override the annotation_style_split and annotation_style_line functions to replace the +# backslashes in the paths with forward slashes. This is so that we can have the same requirements +# file on Windows and Unix-like. +original_annotation_style_split = piptools_writer.annotation_style_split +original_annotation_style_line = piptools_writer.annotation_style_line + + +def annotation_style_split(required_by) -> str: + required_by = set([v.replace("\\", "/") for v in required_by]) + return original_annotation_style_split(required_by) + + +def annotation_style_line(required_by) -> str: + required_by = set([v.replace("\\", "/") for v in required_by]) + return original_annotation_style_line(required_by) + + +piptools_writer.annotation_style_split = annotation_style_split +piptools_writer.annotation_style_line = annotation_style_line + def _select_golden_requirements_file( requirements_txt, requirements_linux, requirements_darwin, requirements_windows @@ -41,19 +66,6 @@ def _select_golden_requirements_file( return requirements_txt -def _fix_up_requirements_in_path(absolute_prefix, output_file): - """Fix up references to the input file inside of the generated requirements file. - - We don't want fully resolved, absolute paths in the generated requirements file. - The paths could differ for every invocation. Replace them with a predictable path. - """ - output_file = Path(output_file) - contents = output_file.read_text() - contents = contents.replace(absolute_prefix, "") - contents = re.sub(r"\\(?!(\n|\r\n))", "/", contents) - output_file.write_text(contents) - - if __name__ == "__main__": if len(sys.argv) < 4: print( @@ -75,7 +87,6 @@ def _fix_up_requirements_in_path(absolute_prefix, output_file): # absolute prefixes in the locked requirements output file. requirements_in_path = Path(requirements_in) resolved_requirements_in = str(requirements_in_path.resolve()) - absolute_prefix = resolved_requirements_in[: -len(str(requirements_in_path))] # Before loading click, set the locale for its parser. # If it leaks through to the system setting, it may fail: @@ -86,7 +97,7 @@ def _fix_up_requirements_in_path(absolute_prefix, output_file): os.environ["LANG"] = "C.UTF-8" UPDATE = True - # Detect if we are running under `bazel test` + # Detect if we are running under `bazel test`. if "TEST_TMPDIR" in os.environ: UPDATE = False # pip-compile wants the cache files to be writeable, but if we point @@ -95,31 +106,13 @@ def _fix_up_requirements_in_path(absolute_prefix, output_file): # In theory this makes the test more hermetic as well. sys.argv.append("--cache-dir") sys.argv.append(os.environ["TEST_TMPDIR"]) - # Make a copy for pip-compile to read and mutate + # Make a copy for pip-compile to read and mutate. requirements_out = os.path.join( os.environ["TEST_TMPDIR"], os.path.basename(requirements_txt) + ".out" ) - copyfile(requirements_txt, requirements_out) - - elif "BUILD_WORKSPACE_DIRECTORY" in os.environ: - # This value, populated when running under `bazel run`, is a path to the - # "root of the workspace where the build was run." - # This matches up with the values passed in via the macro using the 'rootpath' Make variable, - # which for source files provides a path "relative to your workspace root." - # - # Changing to the WORKSPACE root avoids 'file not found' errors when the `.update` target is run - # from different directories within the WORKSPACE. - os.chdir(os.environ["BUILD_WORKSPACE_DIRECTORY"]) - else: - err_msg = ( - "Expected to find BUILD_WORKSPACE_DIRECTORY (running under `bazel run`) or " - "TEST_TMPDIR (running under `bazel test`) in environment." - ) - print( - err_msg, - file=sys.stderr, - ) - sys.exit(1) + # Those two files won't necessarily be on the same filesystem, so we can't use os.replace + # or shutil.copyfile, as they will fail with OSError: [Errno 18] Invalid cross-device link. + shutil.copy(requirements_txt, requirements_out) update_command = os.getenv("CUSTOM_COMPILE_COMMAND") or "bazel run %s" % ( update_target_label, @@ -137,12 +130,17 @@ def _fix_up_requirements_in_path(absolute_prefix, output_file): if UPDATE: print("Updating " + requirements_txt) - try: - cli() - except SystemExit as e: - if e.code == 0: - _fix_up_requirements_in_path(absolute_prefix, requirements_txt) - raise + if "BUILD_WORKSPACE_DIRECTORY" in os.environ: + workspace = os.environ["BUILD_WORKSPACE_DIRECTORY"] + requirements_txt_tree = os.path.join(workspace, requirements_txt) + # In most cases, requirements_txt will be a symlink to the real file in the source tree. + # If symlinks are not enabled (e.g. on Windows), then requirements_txt will be a copy, + # and we should copy the updated requirements back to the source tree. + if not os.path.samefile(requirements_txt, requirements_txt_tree): + atexit.register( + lambda: shutil.copy(requirements_txt, requirements_txt_tree) + ) + cli() else: # cli will exit(0) on success try: @@ -160,7 +158,6 @@ def _fix_up_requirements_in_path(absolute_prefix, output_file): ) sys.exit(1) elif e.code == 0: - _fix_up_requirements_in_path(absolute_prefix, requirements_out) golden_filename = _select_golden_requirements_file( requirements_txt, requirements_linux, diff --git a/tests/compile_pip_requirements/BUILD.bazel b/tests/compile_pip_requirements/BUILD.bazel index 3a67dcca47..d6ac0086ab 100644 --- a/tests/compile_pip_requirements/BUILD.bazel +++ b/tests/compile_pip_requirements/BUILD.bazel @@ -22,12 +22,13 @@ EOF compile_pip_requirements( name = "requirements", data = [ + "requirements.in", "requirements_extra.in", ], extra_args = [ "--allow-unsafe", "--resolver=backtracking", ], - requirements_in = "requirements.in", + requirements_in = "requirements.txt", requirements_txt = "requirements_lock.txt", ) diff --git a/tests/compile_pip_requirements/requirements.txt b/tests/compile_pip_requirements/requirements.txt new file mode 100644 index 0000000000..4826399f01 --- /dev/null +++ b/tests/compile_pip_requirements/requirements.txt @@ -0,0 +1 @@ +-r requirements.in diff --git a/tools/publish/BUILD.bazel b/tools/publish/BUILD.bazel index 8c4b3ab4a2..065e56bd69 100644 --- a/tools/publish/BUILD.bazel +++ b/tools/publish/BUILD.bazel @@ -4,12 +4,4 @@ compile_pip_requirements( name = "requirements", requirements_darwin = "requirements_darwin.txt", requirements_windows = "requirements_windows.txt", - # This fails on RBE right now, and we don't need coverage there: - # WARNING: Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) - # after connection broken by 'NewConnectionError(': - # Failed to establish a new connection: [Errno -3] Temporary failure in name resolution')': /simple/twine/ - # - # ERROR: Could not find a version that satisfies the requirement twine==4.0.2 - # (from -r tools/publish/requirements.in (line 1)) (from versions: none) - tags = ["no-remote-exec"], ) From 2893d858262fd1dd4fd5d011b7f4a6d50ba5d88d Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Wed, 15 Feb 2023 20:08:22 -0800 Subject: [PATCH 171/234] fix: Propagate testonly et al for wheel `.dist` targets (#1064) * Propagate testonly et al for wheel `.dist` targets The `.dist` target depends on the wheel, so it must copy the `testonly` setting as well as some others. * Also adds a utility function to do this, since the multi-version rules also do this copying. Fixes #1057 * fixup! Allow building with unreleased Bazel versions. (#1063) --- docs/BUILD.bazel | 1 + examples/wheel/BUILD.bazel | 7 +++++++ python/packaging.bzl | 2 ++ python/private/BUILD.bazel | 1 + python/private/util.bzl | 31 +++++++++++++++++++++++++++++++ 5 files changed, 42 insertions(+) create mode 100644 python/private/util.bzl diff --git a/docs/BUILD.bazel b/docs/BUILD.bazel index 3abff033ae..2afd0ad7c2 100644 --- a/docs/BUILD.bazel +++ b/docs/BUILD.bazel @@ -84,6 +84,7 @@ bzl_library( "//python/private:py_package.bzl", "//python/private:py_wheel.bzl", "//python/private:stamp.bzl", + "//python/private:util.bzl", ], ) diff --git a/examples/wheel/BUILD.bazel b/examples/wheel/BUILD.bazel index c3dec29c01..4124a826d1 100644 --- a/examples/wheel/BUILD.bazel +++ b/examples/wheel/BUILD.bazel @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +load("@bazel_skylib//rules:build_test.bzl", "build_test") load("//examples/wheel/private:wheel_utils.bzl", "directory_writer") load("//python:defs.bzl", "py_library", "py_test") load("//python:packaging.bzl", "py_package", "py_wheel") @@ -50,6 +51,7 @@ directory_writer( # Package just a specific py_libraries, without their dependencies py_wheel( name = "minimal_with_py_library", + testonly = True, # Set this to verify the generated .dist target doesn't break things # Package data. We're building "example_minimal_library-0.0.1-py3-none-any.whl" distribution = "example_minimal_library", python_tag = "py3", @@ -60,6 +62,11 @@ py_wheel( ], ) +build_test( + name = "dist_build_tests", + targets = [":minimal_with_py_library.dist"], +) + # Package just a specific py_libraries, without their dependencies py_wheel( name = "minimal_with_py_library_with_stamp", diff --git a/python/packaging.bzl b/python/packaging.bzl index 1984eb7b4b..fffd239c15 100644 --- a/python/packaging.bzl +++ b/python/packaging.bzl @@ -16,6 +16,7 @@ load("//python/private:py_package.bzl", "py_package_lib") load("//python/private:py_wheel.bzl", _PyWheelInfo = "PyWheelInfo", _py_wheel = "py_wheel") +load("//python/private:util.bzl", "copy_propagating_kwargs") # Re-export as public API PyWheelInfo = _PyWheelInfo @@ -148,6 +149,7 @@ def py_wheel(name, twine = None, **kwargs): name = _dist_target, wheel = name, out = kwargs.pop("dist_folder", "{}_dist".format(name)), + **copy_propagating_kwargs(kwargs) ) _py_wheel(name = name, **kwargs) diff --git a/python/private/BUILD.bazel b/python/private/BUILD.bazel index f2e1c9b8bc..d56d31b27a 100644 --- a/python/private/BUILD.bazel +++ b/python/private/BUILD.bazel @@ -41,6 +41,7 @@ exports_files( "py_wheel.bzl", "reexports.bzl", "stamp.bzl", + "util.bzl", ], visibility = ["//docs:__pkg__"], ) diff --git a/python/private/util.bzl b/python/private/util.bzl new file mode 100644 index 0000000000..8ea1f493f5 --- /dev/null +++ b/python/private/util.bzl @@ -0,0 +1,31 @@ +"""Functionality shared by multiple pieces of code.""" + +def copy_propagating_kwargs(from_kwargs, into_kwargs = None): + """Copies args that must be compatible between two targets with a dependency relationship. + + This is intended for when one target depends on another, so they must have + compatible settings such as `testonly` and `compatible_with`. This usually + happens when a macro generates multiple targets, some of which depend + on one another, so their settings must be compatible. + + Args: + from_kwargs: keyword args dict whose common kwarg will be copied. + into_kwargs: optional keyword args dict that the values from `from_kwargs` + will be copied into. The values in this dict will take precedence + over the ones in `from_kwargs` (i.e., if this has `testonly` already + set, then it won't be overwritten). + NOTE: THIS WILL BE MODIFIED IN-PLACE. + + Returns: + Keyword args to use for the depender target derived from the dependency + target. If `into_kwargs` was passed in, then that same object is + returned; this is to facilitate easy `**` expansion. + """ + if into_kwargs == None: + into_kwargs = {} + + # Include tags because people generally expect tags to propagate. + for attr in ("testonly", "tags", "compatible_with", "restricted_to"): + if attr in from_kwargs and attr not in into_kwargs: + into_kwargs[attr] = from_kwargs[attr] + return into_kwargs From 64d9d6f59f645ae2c7870623e82ac8b1a9534e44 Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius Date: Thu, 16 Feb 2023 13:11:23 +0900 Subject: [PATCH 172/234] fix: correctly advertise minimum supported version (#1065) * feat: bump the latest supported version to 5.4.0 * feat: add gazelle and RBE minimum supported version tests * feat: pip_parse_vendored example is now 5.4.0 compatible --- .bazelci/presubmit.yml | 100 +++++++++++++++++++ BUILD.bazel | 1 + docs/BUILD.bazel | 1 + examples/pip_parse_vendored/BUILD.bazel | 3 + examples/pip_parse_vendored/requirements.bzl | 2 +- python/pip_install/repositories.bzl | 3 +- version.bzl | 8 +- 7 files changed, 115 insertions(+), 3 deletions(-) diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 5f92fbff04..a1b16bbc66 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -17,6 +17,12 @@ buildifier: version: latest # keep this argument in sync with .pre-commit-config.yaml warnings: "all" +.minimum_supported_version: &minimum_supported_version + # For testing minimum supported version. + # NOTE: Keep in sync with //:version.bzl + bazel: 5.4.0 +.minimum_supported_bzlmod_version: &minimum_supported_bzlmod_version + bazel: 6.0.0 # test minimum supported version of bazel for bzlmod tests .reusable_config: &reusable_config build_targets: - "--" @@ -54,12 +60,24 @@ buildifier: - //tests:version_3_9_test - //tests:version_default_test tasks: + gazelle_extension_min: + <<: *minimum_supported_version + name: Test the Gazelle extension using minimum supported Bazel version + platform: ubuntu2004 + build_targets: ["//..."] + test_targets: ["//..."] + working_directory: gazelle gazelle_extension: name: Test the Gazelle extension platform: ubuntu2004 build_targets: ["//..."] test_targets: ["//..."] working_directory: gazelle + ubuntu_min: + <<: *minimum_supported_version + <<: *reusable_config + name: Default test on Ubuntu using minimum supported Bazel version + platform: ubuntu2004 ubuntu: <<: *reusable_config name: Default test on Ubuntu @@ -78,6 +96,14 @@ tasks: platform: windows test_flags: - "--test_tag_filters=-integration-test,-fix-windows" + + rbe_min: + <<: *minimum_supported_version + <<: *reusable_config + name: Test on RBE using minimum supported Bazel version + platform: rbe_ubuntu1604 + test_flags: + - "--test_tag_filters=-integration-test,-acceptance-test" rbe: <<: *reusable_config name: Test on RBE @@ -85,6 +111,12 @@ tasks: test_flags: - "--test_tag_filters=-integration-test,-acceptance-test" + integration_test_build_file_generation_ubuntu_minimum_supported: + <<: *minimum_supported_version + <<: *reusable_build_test_all + name: build_file_generation integration tests on Ubuntu using minimum supported Bazel version + working_directory: examples/build_file_generation + platform: ubuntu2004 integration_test_build_file_generation_ubuntu: <<: *reusable_build_test_all name: build_file_generation integration tests on Ubuntu @@ -106,6 +138,13 @@ tasks: working_directory: examples/build_file_generation platform: windows + integration_test_bzlmod_ubuntu_min: + <<: *minimum_supported_bzlmod_version + <<: *reusable_build_test_all + <<: *coverage_targets_example_bzlmod + name: bzlmod integration tests on Ubuntu using minimum supported Bazel version + working_directory: examples/bzlmod + platform: ubuntu2004 integration_test_bzlmod_ubuntu: <<: *reusable_build_test_all <<: *coverage_targets_example_bzlmod @@ -131,6 +170,12 @@ tasks: working_directory: examples/bzlmod platform: windows + integration_test_multi_python_versions_ubuntu_min: + <<: *minimum_supported_version + <<: *reusable_build_test_all + name: multi_python_versions integration tests on Ubuntu using minimum supported Bazel version + working_directory: examples/multi_python_versions + platform: ubuntu2004 integration_test_multi_python_versions_ubuntu: <<: *reusable_build_test_all <<: *coverage_targets_example_multi_python @@ -156,6 +201,12 @@ tasks: working_directory: examples/multi_python_versions platform: windows + integration_test_pip_install_ubuntu_min: + <<: *minimum_supported_version + <<: *reusable_build_test_all + name: pip_install integration tests on Ubuntu using minimum supported Bazel version + working_directory: examples/pip_install + platform: ubuntu2004 integration_test_pip_install_ubuntu: <<: *reusable_build_test_all name: pip_install integration tests on Ubuntu @@ -177,6 +228,12 @@ tasks: working_directory: examples/pip_install platform: windows + integration_test_pip_parse_ubuntu_min: + <<: *minimum_supported_version + <<: *reusable_build_test_all + name: pip_parse integration tests on Ubuntu using minimum supported Bazel version + working_directory: examples/pip_parse + platform: ubuntu2004 integration_test_pip_parse_ubuntu: <<: *reusable_build_test_all name: pip_parse integration tests on Ubuntu @@ -198,6 +255,12 @@ tasks: working_directory: examples/pip_parse platform: windows + integration_test_pip_parse_vendored_ubuntu_min: + <<: *minimum_supported_version + <<: *reusable_build_test_all + name: pip_parse_vendored integration tests on Ubuntu using minimum supported Bazel version + working_directory: examples/pip_parse_vendored + platform: ubuntu2004 integration_test_pip_parse_vendored_ubuntu: <<: *reusable_build_test_all name: pip_parse_vendored integration tests on Ubuntu @@ -216,6 +279,12 @@ tasks: # We don't run pip_parse_vendored under Windows as the file checked in is # generated from a repository rule containing OS-specific rendered paths. + integration_test_py_proto_library_ubuntu_min: + <<: *minimum_supported_version + <<: *reusable_build_test_all + name: py_proto_library integration tests on Ubuntu using minimum supported Bazel version + working_directory: examples/py_proto_library + platform: ubuntu2004 integration_test_py_proto_library_ubuntu: <<: *reusable_build_test_all name: py_proto_library integration tests on Ubuntu @@ -238,6 +307,13 @@ tasks: platform: windows # Check the same using bzlmod as well + integration_test_py_proto_library_bzlmod_ubuntu_min: + <<: *minimum_supported_bzlmod_version + <<: *common_bzlmod_flags + <<: *reusable_build_test_all + name: py_proto_library bzlmod integration tests on Ubuntu using minimum supported Bazel version + working_directory: examples/py_proto_library + platform: ubuntu2004 integration_test_py_proto_library_bzlmod_ubuntu: <<: *reusable_build_test_all <<: *common_bzlmod_flags @@ -263,6 +339,12 @@ tasks: working_directory: examples/py_proto_library platform: windows + integration_test_pip_repository_annotations_ubuntu_min: + <<: *minimum_supported_version + <<: *reusable_build_test_all + name: pip_repository_annotations integration tests on Ubuntu using minimum supported Bazel version + working_directory: examples/pip_repository_annotations + platform: ubuntu2004 integration_test_pip_repository_annotations_ubuntu: <<: *reusable_build_test_all name: pip_repository_annotations integration tests on Ubuntu @@ -284,6 +366,12 @@ tasks: working_directory: examples/pip_repository_annotations platform: windows + integration_test_compile_pip_requirements_ubuntu_min: + <<: *minimum_supported_version + <<: *reusable_build_test_all + name: compile_pip_requirements integration tests on Ubuntu using minimum supported Bazel version + working_directory: tests/compile_pip_requirements + platform: ubuntu2004 integration_test_compile_pip_requirements_ubuntu: <<: *reusable_build_test_all name: compile_pip_requirements integration tests on Ubuntu @@ -333,6 +421,12 @@ tasks: - "bazel run //:requirements.update" - "git diff --exit-code" + integration_test_pip_repository_entry_points_ubuntu_min: + <<: *minimum_supported_version + <<: *reusable_build_test_all + name: pip_repository_entry_points integration tests on Ubuntu using minimum supported Bazel version + working_directory: tests/pip_repository_entry_points + platform: ubuntu2004 integration_test_pip_repository_entry_points_ubuntu: <<: *reusable_build_test_all name: pip_repository_entry_points integration tests on Ubuntu @@ -354,6 +448,12 @@ tasks: working_directory: tests/pip_repository_entry_points platform: windows + integration_test_ignore_root_user_error_ubuntu_min: + <<: *minimum_supported_version + <<: *reusable_build_test_all + name: ignore_root_user_error integration tests on Ubuntu using minimum supported Bazel version + working_directory: tests/ignore_root_user_error + platform: ubuntu2004 integration_test_ignore_root_user_error_ubuntu: <<: *reusable_build_test_all name: ignore_root_user_error integration tests on Ubuntu diff --git a/BUILD.bazel b/BUILD.bazel index fc95328a89..5b37fce29a 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -31,6 +31,7 @@ filegroup( "WORKSPACE", "internal_deps.bzl", "internal_setup.bzl", + "version.bzl", "//python:distribution", "//python/pip_install:distribution", "//tools:distribution", diff --git a/docs/BUILD.bazel b/docs/BUILD.bazel index 2afd0ad7c2..d2f0b04b56 100644 --- a/docs/BUILD.bazel +++ b/docs/BUILD.bazel @@ -67,6 +67,7 @@ bzl_library( ], deps = [ ":defs", + "//:version.bzl", ], ) diff --git a/examples/pip_parse_vendored/BUILD.bazel b/examples/pip_parse_vendored/BUILD.bazel index b5a85295e3..9585195f1b 100644 --- a/examples/pip_parse_vendored/BUILD.bazel +++ b/examples/pip_parse_vendored/BUILD.bazel @@ -17,6 +17,9 @@ genrule( "cat $<", # Insert our load statement after the existing one so we don't produce a file with buildifier warnings """sed -e '/^load.*/i\\'$$'\\n''load("@python39//:defs.bzl", "interpreter")'""", + # Replace the bazel 6.0.0 specific comment with something that bazel 5.4.0 would produce. + # This enables this example to be run as a test under bazel 5.4.0. + """sed -e 's#@//#//#'""", """tr "'" '"' """, """sed 's#"@python39_.*//:bin/python3"#interpreter#' >$@""", ]), diff --git a/examples/pip_parse_vendored/requirements.bzl b/examples/pip_parse_vendored/requirements.bzl index cc24aa63ca..e13503ac6c 100644 --- a/examples/pip_parse_vendored/requirements.bzl +++ b/examples/pip_parse_vendored/requirements.bzl @@ -1,7 +1,7 @@ """Starlark representation of locked requirements. @generated by rules_python pip_parse repository rule -from @//:requirements.txt +from //:requirements.txt """ load("@python39//:defs.bzl", "interpreter") diff --git a/python/pip_install/repositories.bzl b/python/pip_install/repositories.bzl index e5567c8c58..664556da12 100644 --- a/python/pip_install/repositories.bzl +++ b/python/pip_install/repositories.bzl @@ -17,6 +17,7 @@ load("@bazel_skylib//lib:versions.bzl", "versions") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") +load("//:version.bzl", "MINIMUM_BAZEL_VERSION") _RULE_DEPS = [ ( @@ -133,7 +134,7 @@ def pip_install_dependencies(): # Give the user an obvious error to upgrade rather than some obscure missing symbol later. # It's not guaranteed that users call this function, but it's used by all the pip fetch # repository rules so it's likely that most users get the right error. - versions.check("4.0.0") + versions.check(MINIMUM_BAZEL_VERSION) for (name, url, sha256) in _RULE_DEPS: maybe( diff --git a/version.bzl b/version.bzl index 91125c21bf..8c7f01cd19 100644 --- a/version.bzl +++ b/version.bzl @@ -19,14 +19,20 @@ # in .bazelversion. BAZEL_VERSION = "6.0.0" +# NOTE: Keep in sync with .bazelci/presubmit.yml +# This is the minimum supported bazel version, that we have some tests for. +MINIMUM_BAZEL_VERSION = "5.4.0" + # Versions of Bazel which users should be able to use. # Ensures we don't break backwards-compatibility, # accidentally forcing users to update their LTS-supported bazel. # These are the versions used when testing nested workspaces with # bazel_integration_test. SUPPORTED_BAZEL_VERSIONS = [ - # TODO: add LTS versions of bazel like 1.0.0, 2.0.0 BAZEL_VERSION, + # TODO @aignas 2023-02-15: the integration tests currently support + # only a single element in this array. + #MINIMUM_BAZEL_VERSION, ] def bazel_version_to_binary_label(version): From 2ab842d36ce2b13fec3a12dd7cc7158c33e8f8be Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius Date: Thu, 16 Feb 2023 14:04:54 +0900 Subject: [PATCH 173/234] refactor: starlark reimplementation of pip_repository (#1043) Previously we were using pip_parse python scripts. This has a few drawbacks: * Requires system python to be present. * Usage of a Python script makes it harder to reason as there is an extra layer of abstraction. * Extending/reusing code between multi_pip_parse and pip_parse is hard. Now we use Starlark to parse the requirements.txt into requirements.bzl. --- docs/pip.md | 3 +- docs/pip_repository.md | 29 +- examples/pip_parse_vendored/BUILD.bazel | 1 - examples/pip_parse_vendored/requirements.bzl | 11 +- python/extensions.bzl | 14 +- python/pip.bzl | 11 +- python/pip_install/BUILD.bazel | 2 - python/pip_install/pip_repository.bzl | 214 +++++++---- .../pip_repository_requirements.bzl.tmpl | 52 +++ ...ip_repository_requirements_bzlmod.bzl.tmpl | 24 ++ python/pip_install/private/srcs.bzl | 2 - .../tools/lock_file_generator/BUILD.bazel | 50 --- .../tools/lock_file_generator/__init__.py | 14 - .../lock_file_generator.py | 336 ------------------ .../lock_file_generator_test.py | 163 --------- 15 files changed, 257 insertions(+), 669 deletions(-) create mode 100644 python/pip_install/pip_repository_requirements.bzl.tmpl create mode 100644 python/pip_install/pip_repository_requirements_bzlmod.bzl.tmpl delete mode 100644 python/pip_install/tools/lock_file_generator/BUILD.bazel delete mode 100644 python/pip_install/tools/lock_file_generator/__init__.py delete mode 100644 python/pip_install/tools/lock_file_generator/lock_file_generator.py delete mode 100644 python/pip_install/tools/lock_file_generator/lock_file_generator_test.py diff --git a/docs/pip.md b/docs/pip.md index 2f5b92ebf1..528abf737d 100644 --- a/docs/pip.md +++ b/docs/pip.md @@ -168,7 +168,7 @@ install_deps() ## pip_parse
-pip_parse(requirements, requirements_lock, name, bzlmod, kwargs)
+pip_parse(requirements, requirements_lock, name, kwargs)
 
Accepts a locked/compiled requirements file and installs the dependencies listed within. @@ -264,7 +264,6 @@ See the example in rules_python/examples/pip_parse_vendored. | requirements | Deprecated. See requirements_lock. | None | | requirements_lock | A fully resolved 'requirements.txt' pip requirement file containing the transitive set of your dependencies. If this file is passed instead of 'requirements' no resolve will take place and pip_repository will create individual repositories for each of your dependencies so that wheels are fetched/built only for the targets specified by 'build/run/test'. Note that if your lockfile is platform-dependent, you can use the requirements_[platform] attributes. | None | | name | The name of the generated repository. The generated repositories containing each requirement will be of the form <name>_<requirement-name>. | "pip_parsed_deps" | -| bzlmod | Whether this rule is being run under a bzlmod module extension. | False | | kwargs | Additional arguments to the [pip_repository](./pip_repository.md) repository rule. | none | diff --git a/docs/pip_repository.md b/docs/pip_repository.md index 7abb503c78..2ccdc64854 100644 --- a/docs/pip_repository.md +++ b/docs/pip_repository.md @@ -7,8 +7,8 @@ ## pip_repository
-pip_repository(name, annotations, bzlmod, download_only, enable_implicit_namespace_pkgs,
-               environment, extra_pip_args, isolated, pip_data_exclude, python_interpreter,
+pip_repository(name, annotations, download_only, enable_implicit_namespace_pkgs, environment,
+               extra_pip_args, isolated, pip_data_exclude, python_interpreter,
                python_interpreter_target, quiet, repo_mapping, repo_prefix, requirements_darwin,
                requirements_linux, requirements_lock, requirements_windows, timeout)
 
@@ -60,7 +60,6 @@ py_binary( | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this repository. | Name | required | | | annotations | Optional annotations to apply to packages | Dictionary: String -> String | optional | {} | -| bzlmod | Whether this repository rule is invoked under bzlmod, in which case we do not create the install_deps() macro. | Boolean | optional | False | | download_only | Whether to use "pip download" instead of "pip wheel". Disables building wheels from source, but allows use of --platform, --python-version, --implementation, and --abi in --extra_pip_args to download wheels for a different platform from the host platform. | Boolean | optional | False | | enable_implicit_namespace_pkgs | If true, disables conversion of native namespace packages into pkg-util style namespace packages. When set all py_binary and py_test targets must specify either legacy_create_init=False or the global Bazel option --incompatible_default_to_explicit_init_py to prevent __init__.py being automatically generated in every directory.

This option is required to support some packages which cannot handle the conversion to pkg-util style. | Boolean | optional | False | | environment | Environment variables to set in the pip subprocess. Can be used to set common variables such as http_proxy, https_proxy and no_proxy Note that pip is run with "--isolated" on the CLI so PIP_<VAR>_<NAME> style env vars are ignored, but env vars that control requests and urllib3 can be passed. | Dictionary: String -> String | optional | {} | @@ -79,6 +78,30 @@ py_binary( | timeout | Timeout (in seconds) on the rule's execution duration. | Integer | optional | 600 | + + +## pip_repository_bzlmod + +
+pip_repository_bzlmod(name, repo_mapping, requirements_darwin, requirements_linux,
+                      requirements_lock, requirements_windows)
+
+ +A rule for bzlmod pip_repository creation. Intended for private use only. + +**ATTRIBUTES** + + +| Name | Description | Type | Mandatory | Default | +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this repository. | Name | required | | +| repo_mapping | A dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.<p>For example, an entry "@foo": "@bar" declares that, for any time this repository depends on @foo (such as a dependency on @foo//some:target, it should actually resolve that dependency within globally-declared @bar (@bar//some:target). | Dictionary: String -> String | required | | +| requirements_darwin | Override the requirements_lock attribute when the host platform is Mac OS | Label | optional | None | +| requirements_linux | Override the requirements_lock attribute when the host platform is Linux | Label | optional | None | +| requirements_lock | A fully resolved 'requirements.txt' pip requirement file containing the transitive set of your dependencies. If this file is passed instead of 'requirements' no resolve will take place and pip_repository will create individual repositories for each of your dependencies so that wheels are fetched/built only for the targets specified by 'build/run/test'. | Label | optional | None | +| requirements_windows | Override the requirements_lock attribute when the host platform is Windows | Label | optional | None | + + ## whl_library diff --git a/examples/pip_parse_vendored/BUILD.bazel b/examples/pip_parse_vendored/BUILD.bazel index 9585195f1b..56630e513d 100644 --- a/examples/pip_parse_vendored/BUILD.bazel +++ b/examples/pip_parse_vendored/BUILD.bazel @@ -20,7 +20,6 @@ genrule( # Replace the bazel 6.0.0 specific comment with something that bazel 5.4.0 would produce. # This enables this example to be run as a test under bazel 5.4.0. """sed -e 's#@//#//#'""", - """tr "'" '"' """, """sed 's#"@python39_.*//:bin/python3"#interpreter#' >$@""", ]), ) diff --git a/examples/pip_parse_vendored/requirements.bzl b/examples/pip_parse_vendored/requirements.bzl index e13503ac6c..015df9340a 100644 --- a/examples/pip_parse_vendored/requirements.bzl +++ b/examples/pip_parse_vendored/requirements.bzl @@ -14,29 +14,20 @@ all_whl_requirements = ["@pip_certifi//:whl", "@pip_charset_normalizer//:whl", " _packages = [("pip_certifi", "certifi==2022.12.7 --hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 --hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"), ("pip_charset_normalizer", "charset-normalizer==2.1.1 --hash=sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845 --hash=sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"), ("pip_idna", "idna==3.4 --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"), ("pip_requests", "requests==2.28.1 --hash=sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983 --hash=sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"), ("pip_urllib3", "urllib3==1.26.13 --hash=sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc --hash=sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8")] _config = {"download_only": False, "enable_implicit_namespace_pkgs": False, "environment": {}, "extra_pip_args": [], "isolated": True, "pip_data_exclude": [], "python_interpreter": "python3", "python_interpreter_target": interpreter, "quiet": True, "repo": "pip", "repo_prefix": "pip_", "timeout": 600} _annotations = {} -_bzlmod = False def _clean_name(name): return name.replace("-", "_").replace(".", "_").lower() def requirement(name): - if _bzlmod: - return "@@pip//:" + _clean_name(name) + "_pkg" return "@pip_" + _clean_name(name) + "//:pkg" def whl_requirement(name): - if _bzlmod: - return "@@pip//:" + _clean_name(name) + "_whl" return "@pip_" + _clean_name(name) + "//:whl" def data_requirement(name): - if _bzlmod: - return "@@pip//:" + _clean_name(name) + "_data" return "@pip_" + _clean_name(name) + "//:data" def dist_info_requirement(name): - if _bzlmod: - return "@@pip//:" + _clean_name(name) + "_dist_info" return "@pip_" + _clean_name(name) + "//:dist_info" def entry_point(pkg, script = None): @@ -46,7 +37,7 @@ def entry_point(pkg, script = None): def _get_annotation(requirement): # This expects to parse `setuptools==58.2.0 --hash=sha256:2551203ae6955b9876741a26ab3e767bb3242dafe86a32a749ea0d78b6792f11` - # down wo `setuptools`. + # down to `setuptools`. name = requirement.split(" ")[0].split("=")[0].split("[")[0] return _annotations.get(name) diff --git a/python/extensions.bzl b/python/extensions.bzl index bc0d570c52..01f731f14f 100644 --- a/python/extensions.bzl +++ b/python/extensions.bzl @@ -14,9 +14,8 @@ "Module extensions for use with bzlmod" -load("@rules_python//python:pip.bzl", "pip_parse") load("@rules_python//python:repositories.bzl", "python_register_toolchains") -load("@rules_python//python/pip_install:pip_repository.bzl", "locked_requirements_label", "pip_repository_attrs", "use_isolated", "whl_library") +load("@rules_python//python/pip_install:pip_repository.bzl", "locked_requirements_label", "pip_repository_attrs", "pip_repository_bzlmod", "use_isolated", "whl_library") load("@rules_python//python/pip_install:repositories.bzl", "pip_install_dependencies") load("@rules_python//python/pip_install:requirements_parser.bzl", parse_requirements = "parse") load("@rules_python//python/private:coverage_deps.bzl", "install_coverage_deps") @@ -68,7 +67,7 @@ def _pip_impl(module_ctx): # Parse the requirements file directly in starlark to get the information # needed for the whl_libary declarations below. This is needed to contain - # the pip_parse logic to a single module extension. + # the pip_repository logic to a single module extension. requirements_lock_content = module_ctx.read(requrements_lock) parse_result = parse_requirements(requirements_lock_content) requirements = parse_result.requirements @@ -76,14 +75,9 @@ def _pip_impl(module_ctx): # Create the repository where users load the `requirement` macro. Under bzlmod # this does not create the install_deps() macro. - pip_parse( + pip_repository_bzlmod( name = attr.name, requirements_lock = attr.requirements_lock, - bzlmod = True, - timeout = attr.timeout, - python_interpreter = attr.python_interpreter, - python_interpreter_target = attr.python_interpreter_target, - quiet = attr.quiet, ) for name, requirement_line in requirements: @@ -114,7 +108,7 @@ def _pip_parse_ext_attrs(): "name": attr.string(mandatory = True), }, **pip_repository_attrs) - # Like the pip_parse macro, we end up setting this manually so + # Like the pip_repository rule, we end up setting this manually so # don't allow users to override it. attrs.pop("repo_prefix") diff --git a/python/pip.bzl b/python/pip.bzl index 3d45aed61e..3c06301306 100644 --- a/python/pip.bzl +++ b/python/pip.bzl @@ -47,7 +47,7 @@ def pip_install(requirements = None, name = "pip", **kwargs): print("pip_install is deprecated. Please switch to pip_parse. pip_install will be removed in a future release.") pip_parse(requirements = requirements, name = name, **kwargs) -def pip_parse(requirements = None, requirements_lock = None, name = "pip_parsed_deps", bzlmod = False, **kwargs): +def pip_parse(requirements = None, requirements_lock = None, name = "pip_parsed_deps", **kwargs): """Accepts a locked/compiled requirements file and installs the dependencies listed within. Those dependencies become available in a generated `requirements.bzl` file. @@ -143,14 +143,9 @@ def pip_parse(requirements = None, requirements_lock = None, name = "pip_parsed_ requirements (Label): Deprecated. See requirements_lock. name (str, optional): The name of the generated repository. The generated repositories containing each requirement will be of the form `_`. - bzlmod (bool, optional): Whether this rule is being run under a bzlmod module extension. **kwargs (dict): Additional arguments to the [`pip_repository`](./pip_repository.md) repository rule. """ - - # Don't try to fetch dependencies under bzlmod because they are already fetched via the internal_deps - # module extention, and because the maybe-install pattern doesn't work under bzlmod. - if not bzlmod: - pip_install_dependencies() + pip_install_dependencies() # Temporary compatibility shim. # pip_install was previously document to use requirements while pip_parse was using requirements_lock. @@ -160,8 +155,6 @@ def pip_parse(requirements = None, requirements_lock = None, name = "pip_parsed_ pip_repository( name = name, requirements_lock = reqs_to_use, - repo_prefix = "{}_".format(name), - bzlmod = bzlmod, **kwargs ) diff --git a/python/pip_install/BUILD.bazel b/python/pip_install/BUILD.bazel index 451e7fab70..281ccba6a9 100644 --- a/python/pip_install/BUILD.bazel +++ b/python/pip_install/BUILD.bazel @@ -4,7 +4,6 @@ filegroup( "BUILD.bazel", "//python/pip_install/tools/dependency_resolver:distribution", "//python/pip_install/tools/lib:distribution", - "//python/pip_install/tools/lock_file_generator:distribution", "//python/pip_install/tools/wheel_installer:distribution", "//python/pip_install/private:distribution", ], @@ -24,7 +23,6 @@ filegroup( srcs = [ "//python/pip_install/tools/dependency_resolver:py_srcs", "//python/pip_install/tools/lib:py_srcs", - "//python/pip_install/tools/lock_file_generator:py_srcs", "//python/pip_install/tools/wheel_installer:py_srcs", ], visibility = ["//python/pip_install/private:__pkg__"], diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl index d5d93f3e9d..982d8536ba 100644 --- a/python/pip_install/pip_repository.bzl +++ b/python/pip_install/pip_repository.bzl @@ -257,110 +257,177 @@ A requirements_lock attribute must be specified, or a platform-specific lockfile """) return requirements_txt -# Keep in sync with `_clean_name` in generated requirements.bzl +# Keep in sync with `_clean_pkg_name` in generated bzlmod requirements.bzl def _clean_pkg_name(name): return name.replace("-", "_").replace(".", "_").lower() -def _bzlmod_pkg_aliases(rctx, requirements_txt): +def _bzlmod_pkg_aliases(repo_name, bzl_packages): """Create alias declarations for each python dependency. - The aliases should be appended to the pip_parse repo's BUILD.bazel file. These aliases + The aliases should be appended to the pip_repository BUILD.bazel file. These aliases allow users to use requirement() without needed a corresponding `use_repo()` for each dep when using bzlmod. Args: - rctx: the repository context - requirements_txt: label to the requirements lock file + repo_name: the repository name of the parent that is visible to the users. + bzl_packages: the list of packages to setup. """ - requirements = parse_requirements(rctx.read(requirements_txt)).requirements - build_content = "" - for requirement in requirements: + for name in bzl_packages: build_content += """\ alias( name = "{name}_pkg", - actual = "@{repo_prefix}{dep}//:pkg", + actual = "@{repo_name}_{dep}//:pkg", ) alias( name = "{name}_whl", - actual = "@{repo_prefix}{dep}//:whl", + actual = "@{repo_name}_{dep}//:whl", ) alias( name = "{name}_data", - actual = "@{repo_prefix}{dep}//:data", + actual = "@{repo_name}_{dep}//:data", ) alias( name = "{name}_dist_info", - actual = "@{repo_prefix}{dep}//:dist_info", + actual = "@{repo_name}_{dep}//:dist_info", ) """.format( - name = _clean_pkg_name(requirement[0]), - repo_prefix = rctx.attr.repo_prefix, - dep = _clean_pkg_name(requirement[0]), + name = name, + repo_name = repo_name, + dep = name, ) return build_content -def _pip_repository_impl(rctx): - python_interpreter = _resolve_python_interpreter(rctx) +def _pip_repository_bzlmod_impl(rctx): + requirements_txt = locked_requirements_label(rctx, rctx.attr) + content = rctx.read(requirements_txt) + parsed_requirements_txt = parse_requirements(content) - # Write the annotations file to pass to the wheel maker - annotations = {package: json.decode(data) for (package, data) in rctx.attr.annotations.items()} - annotations_file = rctx.path("annotations.json") - rctx.file(annotations_file, json.encode_indent(annotations, indent = " " * 4)) + packages = [(_clean_pkg_name(name), requirement) for name, requirement in parsed_requirements_txt.requirements] - requirements_txt = locked_requirements_label(rctx, rctx.attr) - args = [ - python_interpreter, - "-m", - "python.pip_install.tools.lock_file_generator.lock_file_generator", - "--requirements_lock", - rctx.path(requirements_txt), - "--requirements_lock_label", - str(requirements_txt), - # pass quiet and timeout args through to child repos. - "--quiet", - str(rctx.attr.quiet), - "--timeout", - str(rctx.attr.timeout), - "--annotations", - annotations_file, - "--bzlmod", - str(rctx.attr.bzlmod).lower(), - ] + bzl_packages = sorted([name for name, _ in packages]) - args += ["--python_interpreter", _get_python_interpreter_attr(rctx)] - if rctx.attr.python_interpreter_target: - args += ["--python_interpreter_target", str(rctx.attr.python_interpreter_target)] - progress_message = "Parsing requirements to starlark" + repo_name = rctx.attr.name.split("~")[-1] - args += ["--repo", rctx.attr.name, "--repo-prefix", rctx.attr.repo_prefix] - args = _parse_optional_attrs(rctx, args) + build_contents = _BUILD_FILE_CONTENTS + _bzlmod_pkg_aliases(repo_name, bzl_packages) - rctx.report_progress(progress_message) + rctx.file("BUILD.bazel", build_contents) + rctx.template("requirements.bzl", rctx.attr._template, substitutions = { + "%%ALL_REQUIREMENTS%%": _format_repr_list([ + "@{}//:{}_pkg".format(repo_name, p) + for p in bzl_packages + ]), + "%%ALL_WHL_REQUIREMENTS%%": _format_repr_list([ + "@{}//:{}_whl".format(repo_name, p) + for p in bzl_packages + ]), + "%%NAME%%": rctx.attr.name, + "%%REQUIREMENTS_LOCK%%": str(requirements_txt), + }) - result = rctx.execute( - args, - # Manually construct the PYTHONPATH since we cannot use the toolchain here - environment = _create_repository_execution_environment(rctx), - timeout = rctx.attr.timeout, - quiet = rctx.attr.quiet, - ) +pip_repository_bzlmod_attrs = { + "requirements_darwin": attr.label( + allow_single_file = True, + doc = "Override the requirements_lock attribute when the host platform is Mac OS", + ), + "requirements_linux": attr.label( + allow_single_file = True, + doc = "Override the requirements_lock attribute when the host platform is Linux", + ), + "requirements_lock": attr.label( + allow_single_file = True, + doc = """ +A fully resolved 'requirements.txt' pip requirement file containing the transitive set of your dependencies. If this file is passed instead +of 'requirements' no resolve will take place and pip_repository will create individual repositories for each of your dependencies so that +wheels are fetched/built only for the targets specified by 'build/run/test'. +""", + ), + "requirements_windows": attr.label( + allow_single_file = True, + doc = "Override the requirements_lock attribute when the host platform is Windows", + ), + "_template": attr.label( + default = ":pip_repository_requirements_bzlmod.bzl.tmpl", + ), +} - if result.return_code: - fail("rules_python failed: %s (%s)" % (result.stdout, result.stderr)) +pip_repository_bzlmod = repository_rule( + attrs = pip_repository_bzlmod_attrs, + doc = """A rule for bzlmod pip_repository creation. Intended for private use only.""", + implementation = _pip_repository_bzlmod_impl, +) + +def _pip_repository_impl(rctx): + requirements_txt = locked_requirements_label(rctx, rctx.attr) + content = rctx.read(requirements_txt) + parsed_requirements_txt = parse_requirements(content) + + packages = [(_clean_pkg_name(name), requirement) for name, requirement in parsed_requirements_txt.requirements] - # We need a BUILD file to load the generated requirements.bzl - build_contents = _BUILD_FILE_CONTENTS + bzl_packages = sorted([name for name, _ in packages]) - if rctx.attr.bzlmod: - build_contents += _bzlmod_pkg_aliases(rctx, requirements_txt) + imports = [ + 'load("@rules_python//python/pip_install:pip_repository.bzl", "whl_library")', + ] + + annotations = {} + for pkg, annotation in rctx.attr.annotations.items(): + filename = "{}.annotation.json".format(_clean_pkg_name(pkg)) + rctx.file(filename, json.encode_indent(json.decode(annotation))) + annotations[pkg] = "@{name}//:{filename}".format(name = rctx.attr.name, filename = filename) + + tokenized_options = [] + for opt in parsed_requirements_txt.options: + for p in opt.split(" "): + tokenized_options.append(p) + + options = tokenized_options + rctx.attr.extra_pip_args + + config = { + "download_only": rctx.attr.download_only, + "enable_implicit_namespace_pkgs": rctx.attr.enable_implicit_namespace_pkgs, + "environment": rctx.attr.environment, + "extra_pip_args": options, + "isolated": use_isolated(rctx, rctx.attr), + "pip_data_exclude": rctx.attr.pip_data_exclude, + "python_interpreter": _get_python_interpreter_attr(rctx), + "quiet": rctx.attr.quiet, + "repo": rctx.attr.name, + "repo_prefix": "{}_".format(rctx.attr.name), + "timeout": rctx.attr.timeout, + } - rctx.file("BUILD.bazel", build_contents + "\n# The requirements.bzl file was generated by running:\n# " + " ".join([str(a) for a in args])) + if rctx.attr.python_interpreter_target: + config["python_interpreter_target"] = str(rctx.attr.python_interpreter_target) + + rctx.file("BUILD.bazel", _BUILD_FILE_CONTENTS) + rctx.template("requirements.bzl", rctx.attr._template, substitutions = { + "%%ALL_REQUIREMENTS%%": _format_repr_list([ + "@{}_{}//:pkg".format(rctx.attr.name, p) + for p in bzl_packages + ]), + "%%ALL_WHL_REQUIREMENTS%%": _format_repr_list([ + "@{}_{}//:whl".format(rctx.attr.name, p) + for p in bzl_packages + ]), + "%%ANNOTATIONS%%": _format_dict(_repr_dict(annotations)), + "%%CONFIG%%": _format_dict(_repr_dict(config)), + "%%EXTRA_PIP_ARGS%%": json.encode(options), + "%%IMPORTS%%": "\n".join(sorted(imports)), + "%%NAME%%": rctx.attr.name, + "%%PACKAGES%%": _format_repr_list( + [ + ("{}_{}".format(rctx.attr.name, p), r) + for p, r in packages + ], + ), + "%%REQUIREMENTS_LOCK%%": str(requirements_txt), + }) return @@ -453,12 +520,6 @@ pip_repository_attrs = { "annotations": attr.string_dict( doc = "Optional annotations to apply to packages", ), - "bzlmod": attr.bool( - default = False, - doc = """Whether this repository rule is invoked under bzlmod, in which case -we do not create the install_deps() macro. -""", - ), "requirements_darwin": attr.label( allow_single_file = True, doc = "Override the requirements_lock attribute when the host platform is Mac OS", @@ -479,6 +540,9 @@ wheels are fetched/built only for the targets specified by 'build/run/test'. allow_single_file = True, doc = "Override the requirements_lock attribute when the host platform is Windows", ), + "_template": attr.label( + default = ":pip_repository_requirements.bzl.tmpl", + ), } pip_repository_attrs.update(**common_attrs) @@ -625,3 +689,19 @@ def package_annotation( data_exclude_glob = data_exclude_glob, srcs_exclude_glob = srcs_exclude_glob, )) + +# pip_repository implementation + +def _format_list(items): + return "[{}]".format(", ".join(items)) + +def _format_repr_list(strings): + return _format_list( + [repr(s) for s in strings], + ) + +def _repr_dict(items): + return {k: repr(v) for k, v in items.items()} + +def _format_dict(items): + return "{{{}}}".format(", ".join(sorted(['"{}": {}'.format(k, v) for k, v in items.items()]))) diff --git a/python/pip_install/pip_repository_requirements.bzl.tmpl b/python/pip_install/pip_repository_requirements.bzl.tmpl new file mode 100644 index 0000000000..bf6a053622 --- /dev/null +++ b/python/pip_install/pip_repository_requirements.bzl.tmpl @@ -0,0 +1,52 @@ +"""Starlark representation of locked requirements. + +@generated by rules_python pip_parse repository rule +from %%REQUIREMENTS_LOCK%% +""" + +%%IMPORTS%% + +all_requirements = %%ALL_REQUIREMENTS%% + +all_whl_requirements = %%ALL_WHL_REQUIREMENTS%% + +_packages = %%PACKAGES%% +_config = %%CONFIG%% +_annotations = %%ANNOTATIONS%% + +def _clean_name(name): + return name.replace("-", "_").replace(".", "_").lower() + +def requirement(name): + return "@%%NAME%%_" + _clean_name(name) + "//:pkg" + +def whl_requirement(name): + return "@%%NAME%%_" + _clean_name(name) + "//:whl" + +def data_requirement(name): + return "@%%NAME%%_" + _clean_name(name) + "//:data" + +def dist_info_requirement(name): + return "@%%NAME%%_" + _clean_name(name) + "//:dist_info" + +def entry_point(pkg, script = None): + if not script: + script = pkg + return "@%%NAME%%_" + _clean_name(pkg) + "//:rules_python_wheel_entry_point_" + script + +def _get_annotation(requirement): + # This expects to parse `setuptools==58.2.0 --hash=sha256:2551203ae6955b9876741a26ab3e767bb3242dafe86a32a749ea0d78b6792f11` + # down to `setuptools`. + name = requirement.split(" ")[0].split("=")[0].split("[")[0] + return _annotations.get(name) + +def install_deps(**whl_library_kwargs): + whl_config = dict(_config) + whl_config.update(whl_library_kwargs) + for name, requirement in _packages: + whl_library( + name = name, + requirement = requirement, + annotation = _get_annotation(requirement), + **whl_config + ) diff --git a/python/pip_install/pip_repository_requirements_bzlmod.bzl.tmpl b/python/pip_install/pip_repository_requirements_bzlmod.bzl.tmpl new file mode 100644 index 0000000000..462829d074 --- /dev/null +++ b/python/pip_install/pip_repository_requirements_bzlmod.bzl.tmpl @@ -0,0 +1,24 @@ +"""Starlark representation of locked requirements. + +@generated by rules_python pip_parse repository rule +from %%REQUIREMENTS_LOCK%%. +""" + +all_requirements = %%ALL_REQUIREMENTS%% + +all_whl_requirements = %%ALL_WHL_REQUIREMENTS%% + +def _clean_name(name): + return name.replace("-", "_").replace(".", "_").lower() + +def requirement(name): + return "@@%%NAME%%//:" + _clean_name(name) + "_pkg" + +def whl_requirement(name): + return "@@%%NAME%%//:" + _clean_name(name) + "_whl" + +def data_requirement(name): + return "@@%%NAME%%//:" + _clean_name(name) + "_data" + +def dist_info_requirement(name): + return "@@%%NAME%%//:" + _clean_name(name) + "_dist_info" diff --git a/python/pip_install/private/srcs.bzl b/python/pip_install/private/srcs.bzl index 57644f612f..f3064a3aec 100644 --- a/python/pip_install/private/srcs.bzl +++ b/python/pip_install/private/srcs.bzl @@ -13,8 +13,6 @@ PIP_INSTALL_PY_SRCS = [ "@rules_python//python/pip_install/tools/lib:annotation.py", "@rules_python//python/pip_install/tools/lib:arguments.py", "@rules_python//python/pip_install/tools/lib:bazel.py", - "@rules_python//python/pip_install/tools/lock_file_generator:__init__.py", - "@rules_python//python/pip_install/tools/lock_file_generator:lock_file_generator.py", "@rules_python//python/pip_install/tools/wheel_installer:namespace_pkgs.py", "@rules_python//python/pip_install/tools/wheel_installer:wheel.py", "@rules_python//python/pip_install/tools/wheel_installer:wheel_installer.py", diff --git a/python/pip_install/tools/lock_file_generator/BUILD.bazel b/python/pip_install/tools/lock_file_generator/BUILD.bazel deleted file mode 100644 index 804f36a946..0000000000 --- a/python/pip_install/tools/lock_file_generator/BUILD.bazel +++ /dev/null @@ -1,50 +0,0 @@ -load("//python:defs.bzl", "py_binary", "py_library", "py_test") -load("//python/pip_install:repositories.bzl", "requirement") - -py_library( - name = "lib", - srcs = [ - "lock_file_generator.py", - ], - deps = [ - "//python/pip_install/tools/lib", - requirement("pip"), - ], -) - -py_binary( - name = "lock_file_generator", - srcs = [ - "lock_file_generator.py", - ], - deps = [":lib"], -) - -py_test( - name = "lock_file_generator_test", - size = "small", - srcs = [ - "lock_file_generator_test.py", - ], - deps = [ - ":lib", - ], -) - -filegroup( - name = "distribution", - srcs = glob( - ["*"], - exclude = ["*_test.py"], - ), - visibility = ["//python/pip_install:__subpackages__"], -) - -filegroup( - name = "py_srcs", - srcs = glob( - include = ["**/*.py"], - exclude = ["**/*_test.py"], - ), - visibility = ["//python/pip_install:__subpackages__"], -) diff --git a/python/pip_install/tools/lock_file_generator/__init__.py b/python/pip_install/tools/lock_file_generator/__init__.py deleted file mode 100644 index bbdfb4c588..0000000000 --- a/python/pip_install/tools/lock_file_generator/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright 2023 The Bazel Authors. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - diff --git a/python/pip_install/tools/lock_file_generator/lock_file_generator.py b/python/pip_install/tools/lock_file_generator/lock_file_generator.py deleted file mode 100644 index ed1488dd45..0000000000 --- a/python/pip_install/tools/lock_file_generator/lock_file_generator.py +++ /dev/null @@ -1,336 +0,0 @@ -# Copyright 2023 The Bazel Authors. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import argparse -import json -import shlex -import sys -import textwrap -from pathlib import Path -from typing import Any, Dict, List, TextIO, Tuple - -from pip._internal.network.session import PipSession -from pip._internal.req import constructors -from pip._internal.req.req_file import ( - RequirementsFileParser, - get_file_content, - get_line_parser, - preprocess, -) -from pip._internal.req.req_install import InstallRequirement - -from python.pip_install.tools.lib import annotation, arguments, bazel - - -def parse_install_requirements( - requirements_lock: str, extra_pip_args: List[str] -) -> List[Tuple[InstallRequirement, str]]: - ps = PipSession() - # This is roughly taken from pip._internal.req.req_file.parse_requirements - # (https://github.com/pypa/pip/blob/21.0.1/src/pip/_internal/req/req_file.py#L127) in order to keep - # the original line (sort-of, its preprocessed) from the requirements_lock file around, to pass to sub repos - # as the requirement. - line_parser = get_line_parser(finder=None) - parser = RequirementsFileParser(ps, line_parser) - install_req_and_lines: List[Tuple[InstallRequirement, str]] = [] - _, content = get_file_content(requirements_lock, ps) - unpinned_reqs = [] - for parsed_line, (_, line) in zip( - parser.parse(requirements_lock, constraint=False), preprocess(content) - ): - if parsed_line.is_requirement: - install_req = constructors.install_req_from_line(parsed_line.requirement) - if ( - # PEP-440 direct references are considered pinned - # See: https://peps.python.org/pep-0440/#direct-references and https://peps.python.org/pep-0508/ - not install_req.link - and not install_req.is_pinned - ): - unpinned_reqs.append(str(install_req)) - install_req_and_lines.append((install_req, line)) - - else: - extra_pip_args.extend(shlex.split(line)) - - if len(unpinned_reqs) > 0: - unpinned_reqs_str = "\n".join(unpinned_reqs) - raise RuntimeError( - f"""\ -The `requirements_lock` file must be fully pinned. See `compile_pip_requirements`. -Alternatively, use `pip-tools` or a similar mechanism to produce a pinned lockfile. - -The following requirements were not pinned: -{unpinned_reqs_str}""" - ) - - return install_req_and_lines - - -def repo_names_and_requirements( - install_reqs: List[Tuple[InstallRequirement, str]], repo_prefix: str -) -> List[Tuple[str, str]]: - return [ - ( - bazel.sanitise_name(ir.name, prefix=repo_prefix), - line, - ) - for ir, line in install_reqs - ] - - -def parse_whl_library_args(args: argparse.Namespace) -> Dict[str, Any]: - whl_library_args = dict(vars(args)) - whl_library_args = arguments.deserialize_structured_args(whl_library_args) - whl_library_args.setdefault("python_interpreter", sys.executable) - - # These arguments are not used by `whl_library` - for arg in ( - "requirements_lock", - "requirements_lock_label", - "annotations", - "bzlmod", - ): - if arg in whl_library_args: - whl_library_args.pop(arg) - - return whl_library_args - - -def generate_parsed_requirements_contents( - requirements_lock: Path, - repo: str, - repo_prefix: str, - whl_library_args: Dict[str, Any], - annotations: Dict[str, str] = dict(), - bzlmod: bool = False, -) -> str: - """ - Parse each requirement from the requirements_lock file, and prepare arguments for each - repository rule, which will represent the individual requirements. - - Generates a requirements.bzl file containing a macro (install_deps()) which instantiates - a repository rule for each requirement in the lock file. - """ - install_req_and_lines = parse_install_requirements( - requirements_lock, whl_library_args["extra_pip_args"] - ) - repo_names_and_reqs = repo_names_and_requirements( - install_req_and_lines, repo_prefix - ) - - all_requirements = ", ".join( - [ - bazel.sanitised_repo_library_label(ir.name, repo_prefix=repo_prefix) - for ir, _ in install_req_and_lines - ] - ) - all_whl_requirements = ", ".join( - [ - bazel.sanitised_repo_file_label(ir.name, repo_prefix=repo_prefix) - for ir, _ in install_req_and_lines - ] - ) - - install_deps_macro = """ - def install_deps(**whl_library_kwargs): - whl_config = dict(_config) - whl_config.update(whl_library_kwargs) - for name, requirement in _packages: - whl_library( - name = name, - requirement = requirement, - annotation = _get_annotation(requirement), - **whl_config - ) -""" - return textwrap.dedent( - ( - """\ - - load("@rules_python//python/pip_install:pip_repository.bzl", "whl_library") - - all_requirements = [{all_requirements}] - - all_whl_requirements = [{all_whl_requirements}] - - _packages = {repo_names_and_reqs} - _config = {args} - _annotations = {annotations} - _bzlmod = {bzlmod} - - def _clean_name(name): - return name.replace("-", "_").replace(".", "_").lower() - - def requirement(name): - if _bzlmod: - return "@@{repo}//:" + _clean_name(name) + "_{py_library_label}" - return "@{repo_prefix}" + _clean_name(name) + "//:{py_library_label}" - - def whl_requirement(name): - if _bzlmod: - return "@@{repo}//:" + _clean_name(name) + "_{wheel_file_label}" - return "@{repo_prefix}" + _clean_name(name) + "//:{wheel_file_label}" - - def data_requirement(name): - if _bzlmod: - return "@@{repo}//:" + _clean_name(name) + "_{data_label}" - return "@{repo_prefix}" + _clean_name(name) + "//:{data_label}" - - def dist_info_requirement(name): - if _bzlmod: - return "@@{repo}//:" + _clean_name(name) + "_{dist_info_label}" - return "@{repo_prefix}" + _clean_name(name) + "//:{dist_info_label}" - - def entry_point(pkg, script = None): - if not script: - script = pkg - return "@{repo_prefix}" + _clean_name(pkg) + "//:{entry_point_prefix}_" + script - - def _get_annotation(requirement): - # This expects to parse `setuptools==58.2.0 --hash=sha256:2551203ae6955b9876741a26ab3e767bb3242dafe86a32a749ea0d78b6792f11` - # down wo `setuptools`. - name = requirement.split(" ")[0].split("=")[0].split("[")[0] - return _annotations.get(name) -""" - + (install_deps_macro if not bzlmod else "") - ).format( - all_requirements=all_requirements, - all_whl_requirements=all_whl_requirements, - annotations=json.dumps(annotations), - args=dict(sorted(whl_library_args.items())), - data_label=bazel.DATA_LABEL, - dist_info_label=bazel.DIST_INFO_LABEL, - entry_point_prefix=bazel.WHEEL_ENTRY_POINT_PREFIX, - py_library_label=bazel.PY_LIBRARY_LABEL, - repo_names_and_reqs=repo_names_and_reqs, - repo=repo, - repo_prefix=repo_prefix, - wheel_file_label=bazel.WHEEL_FILE_LABEL, - bzlmod=bzlmod, - ) - ) - - -def coerce_to_bool(option): - return str(option).lower() == "true" - - -def main(output: TextIO) -> None: - """Args: - - output: where to write the resulting starlark, such as sys.stdout or an open file - """ - parser = argparse.ArgumentParser( - description="Create rules to incrementally fetch needed \ -dependencies from a fully resolved requirements lock file." - ) - parser.add_argument( - "--requirements_lock", - action="store", - required=True, - help="Path to fully resolved requirements.txt to use as the source of repos.", - ) - parser.add_argument( - "--requirements_lock_label", - help="Label used to declare the requirements.lock, included in comments in the file.", - ) - parser.add_argument( - "--python_interpreter", - help="The python interpreter that will be used to download and unpack the wheels.", - ) - parser.add_argument( - "--python_interpreter_target", - help="Bazel target of a python interpreter.\ -It will be used in repository rules so it must be an already built interpreter.\ -If set, it will take precedence over python_interpreter.", - ) - parser.add_argument( - "--quiet", - type=coerce_to_bool, - default=True, - required=True, - help="Whether to print stdout / stderr from child repos.", - ) - parser.add_argument( - "--timeout", - type=int, - action="store", - required=True, - help="timeout to use for pip operation.", - ) - parser.add_argument( - "--annotations", - type=annotation.annotations_map_from_str_path, - help="A json encoded file containing annotations for rendered packages.", - ) - parser.add_argument( - "--bzlmod", - type=coerce_to_bool, - default=False, - help="Whether this script is run under bzlmod. Under bzlmod we don't generate the install_deps() macro as it isn't needed.", - ) - arguments.parse_common_args(parser) - args = parser.parse_args() - - whl_library_args = parse_whl_library_args(args) - - # Check for any annotations which match packages in the locked requirements file - install_requirements = parse_install_requirements( - args.requirements_lock, whl_library_args["extra_pip_args"] - ) - req_names = sorted([req.name for req, _ in install_requirements]) - annotations = args.annotations.collect(req_names) if args.annotations else {} - - # Write all rendered annotation files and generate a list of the labels to write to the requirements file - annotated_requirements = dict() - for name, content in annotations.items(): - annotation_path = Path(name + ".annotation.json") - annotation_path.write_text(json.dumps(content, indent=4)) - annotated_requirements.update( - { - name: "@{}//:{}.annotation.json".format( - args.repo, name - ) - } - ) - - output.write( - textwrap.dedent( - """\ - \"\"\"Starlark representation of locked requirements. - - @generated by rules_python pip_parse repository rule - from {} - \"\"\" - """.format( - args.requirements_lock_label - ) - ) - ) - - output.write( - generate_parsed_requirements_contents( - requirements_lock=args.requirements_lock, - repo=args.repo, - repo_prefix=args.repo_prefix, - whl_library_args=whl_library_args, - annotations=annotated_requirements, - bzlmod=args.bzlmod, - ) - ) - - -if __name__ == "__main__": - with open("requirements.bzl", "w") as requirement_file: - main(requirement_file) diff --git a/python/pip_install/tools/lock_file_generator/lock_file_generator_test.py b/python/pip_install/tools/lock_file_generator/lock_file_generator_test.py deleted file mode 100644 index be244b1c07..0000000000 --- a/python/pip_install/tools/lock_file_generator/lock_file_generator_test.py +++ /dev/null @@ -1,163 +0,0 @@ -# Copyright 2023 The Bazel Authors. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import argparse -import json -import tempfile -import unittest -from pathlib import Path -from textwrap import dedent - -from pip._internal.req.req_install import InstallRequirement - -from python.pip_install.tools.lock_file_generator import lock_file_generator - - -class TestParseRequirementsToBzl(unittest.TestCase): - maxDiff = None - - def test_generated_requirements_bzl(self) -> None: - with tempfile.TemporaryDirectory() as temp_dir: - requirements_lock = Path(temp_dir) / "requirements.txt" - comments_and_flags = "#comment\n--require-hashes True\n" - requirement_string = "foo==0.0.0 --hash=sha256:hashofFoowhl" - requirements_lock.write_bytes( - bytes(comments_and_flags + requirement_string, encoding="utf-8") - ) - args = argparse.Namespace() - args.requirements_lock = str(requirements_lock.resolve()) - args.repo = ("pip_parsed_deps_pypi__",) - args.repo_prefix = "pip_parsed_deps_pypi__" - extra_pip_args = ["--index-url=pypi.org/simple"] - pip_data_exclude = ["**.foo"] - args.extra_pip_args = json.dumps({"arg": extra_pip_args}) - args.pip_data_exclude = json.dumps({"arg": pip_data_exclude}) - args.python_interpreter = "/custom/python3" - args.python_interpreter_target = "@custom_python//:exec" - args.environment = json.dumps({"arg": {}}) - whl_library_args = lock_file_generator.parse_whl_library_args(args) - contents = lock_file_generator.generate_parsed_requirements_contents( - requirements_lock=args.requirements_lock, - repo=args.repo, - repo_prefix=args.repo_prefix, - whl_library_args=whl_library_args, - ) - library_target = "@pip_parsed_deps_pypi__foo//:pkg" - whl_target = "@pip_parsed_deps_pypi__foo//:whl" - all_requirements = 'all_requirements = ["{library_target}"]'.format( - library_target=library_target - ) - all_whl_requirements = 'all_whl_requirements = ["{whl_target}"]'.format( - whl_target=whl_target - ) - self.assertIn(all_requirements, contents, contents) - self.assertIn(all_whl_requirements, contents, contents) - self.assertIn(requirement_string, contents, contents) - all_flags = extra_pip_args + ["--require-hashes", "True"] - self.assertIn( - "'extra_pip_args': {}".format(repr(all_flags)), contents, contents - ) - self.assertIn( - "'pip_data_exclude': {}".format(repr(pip_data_exclude)), - contents, - contents, - ) - self.assertIn("'python_interpreter': '/custom/python3'", contents, contents) - self.assertIn( - "'python_interpreter_target': '@custom_python//:exec'", - contents, - contents, - ) - # Assert it gets set to an empty dict by default. - self.assertIn("'environment': {}", contents, contents) - - def test_parse_install_requirements_with_args(self): - # Test requirements files with varying arguments - for requirement_args in ("", "--index-url https://index.python.com"): - with tempfile.TemporaryDirectory() as temp_dir: - requirements_lock = Path(temp_dir) / "requirements.txt" - requirements_lock.write_text( - dedent( - """\ - {} - - wheel==0.37.1 \\ - --hash=sha256:4bdcd7d840138086126cd09254dc6195fb4fc6f01c050a1d7236f2630db1d22a \\ - --hash=sha256:e9a504e793efbca1b8e0e9cb979a249cf4a0a7b5b8c9e8b65a5e39d49529c1c4 - # via -r requirements.in - setuptools==58.2.0 \\ - --hash=sha256:2551203ae6955b9876741a26ab3e767bb3242dafe86a32a749ea0d78b6792f11 \ - --hash=sha256:2c55bdb85d5bb460bd2e3b12052b677879cffcf46c0c688f2e5bf51d36001145 - # via -r requirements.in - """.format( - requirement_args - ) - ) - ) - - install_req_and_lines = lock_file_generator.parse_install_requirements( - str(requirements_lock), ["-v"] - ) - - # There should only be two entries for the two requirements - self.assertEqual(len(install_req_and_lines), 2) - - # The first index in each tuple is expected to be an `InstallRequirement` object - self.assertIsInstance(install_req_and_lines[0][0], InstallRequirement) - self.assertIsInstance(install_req_and_lines[1][0], InstallRequirement) - - # Ensure the requirements text is correctly parsed with the trailing arguments - self.assertTupleEqual( - install_req_and_lines[0][1:], - ( - "wheel==0.37.1 --hash=sha256:4bdcd7d840138086126cd09254dc6195fb4fc6f01c050a1d7236f2630db1d22a --hash=sha256:e9a504e793efbca1b8e0e9cb979a249cf4a0a7b5b8c9e8b65a5e39d49529c1c4", - ), - ) - self.assertTupleEqual( - install_req_and_lines[1][1:], - ( - "setuptools==58.2.0 --hash=sha256:2551203ae6955b9876741a26ab3e767bb3242dafe86a32a749ea0d78b6792f11 --hash=sha256:2c55bdb85d5bb460bd2e3b12052b677879cffcf46c0c688f2e5bf51d36001145", - ), - ) - - def test_parse_install_requirements_pinned_direct_reference(self): - # Test PEP-440 direct references - with tempfile.TemporaryDirectory() as temp_dir: - requirements_lock = Path(temp_dir) / "requirements.txt" - requirements_lock.write_text( - dedent( - """\ - onnx @ https://files.pythonhosted.org/packages/24/93/f5b001dc0f5de84ce049a34ff382032cd9478e1080aa6ac48470fa810577/onnx-1.11.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl \ - --hash=sha256:67c6d2654c1c203e5c839a47900b51f588fd0de71bbd497fb193d30a0b3ec1e9 - """ - ) - ) - - install_req_and_lines = lock_file_generator.parse_install_requirements( - str(requirements_lock), ["-v"] - ) - - self.assertEqual(len(install_req_and_lines), 1) - self.assertEqual(install_req_and_lines[0][0].name, "onnx") - - self.assertTupleEqual( - install_req_and_lines[0][1:], - ( - "onnx @ https://files.pythonhosted.org/packages/24/93/f5b001dc0f5de84ce049a34ff382032cd9478e1080aa6ac48470fa810577/onnx-1.11.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl --hash=sha256:67c6d2654c1c203e5c839a47900b51f588fd0de71bbd497fb193d30a0b3ec1e9", - ), - ) - - -if __name__ == "__main__": - unittest.main() From 076d8746d970b05efc2199532564d9018b2c2313 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Thu, 16 Feb 2023 09:17:29 -0800 Subject: [PATCH 174/234] Add some docs about how to configure coverage. (#1074) * Add some docs about how to configure coverage. This is to replace the docs on bazel.build that talk about coverage support for Python. * Update docs/coverage.md --------- Co-authored-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- docs/coverage.md | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 docs/coverage.md diff --git a/docs/coverage.md b/docs/coverage.md new file mode 100644 index 0000000000..bc613f8295 --- /dev/null +++ b/docs/coverage.md @@ -0,0 +1,58 @@ +# Setting up coverage + +As of Bazel 6, the Python toolchains and bootstrap logic supports providing +coverage information using the `coverage` library. + +As of `rules_python` version `0.18.1`, builtin coverage support can be enabled +when configuring toolchains. + +## Enabling `rules_python` coverage support + +Enabling the coverage support bundled with `rules_python` just requires setting an +argument when registerting toolchains. + +For Bzlmod: + +```starlark +python.toolchain( + "@python3_9_toolchains//:all", + configure_coverage_tool = True, +) +``` + +For WORKSPACE configuration: + +```starlark +register_python_toolchains( + register_coverage_tool = True, +) +``` + +NOTE: This will implicitly add the version of `coverage` bundled with +`rules_python` to the dependencies of `py_test` rules when `bazel coverage` is +run. If a target already transitively depends on a different version of +`coverage`, then behavior is undefined -- it is undefined which version comes +first in the import path. If you find yourself in this situation, then you'll +need to manually configure coverage (see below). + +## Manually configuring coverage + +To manually configure coverage support, you'll need to set the +`py_runtime.coverage_tool` attribute. This attribute is a target that specifies +the coverage entry point file and, optionally, client libraries that are added +to `py_test` targets. Typically, this would be a `filegroup` that looked like: + +```starlark +filegroup( + name = "coverage", + srcs = ["coverage_main.py"], + data = ["coverage_lib1.py", ...] +) +``` + +Using `filegroup` isn't required, nor are including client libraries. The +important behaviors of the target are: + +* It provides a single output file OR it provides an executable output; this + output is treated as the coverage entry point. +* If it provides runfiles, then `runfiles.files` are included into `py_test`. From f4396956f16072c34748001baa17e9bcb89cad78 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Tue, 21 Feb 2023 16:11:28 -0800 Subject: [PATCH 175/234] Remove empty line between copyright and build file docstring. (#1084) This makes modifying it with buildozer easier. When the empty line is present, Buildozer gets confused and adds loads() before the intended doc string. --- python/BUILD.bazel | 1 - 1 file changed, 1 deletion(-) diff --git a/python/BUILD.bazel b/python/BUILD.bazel index dcdbee15af..2e275b6650 100644 --- a/python/BUILD.bazel +++ b/python/BUILD.bazel @@ -11,7 +11,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. - """This package contains two sets of rules: 1) the "core" Python rules, which were historically bundled with Bazel and From b9865470cc567eb780bf5c8f7823d0200d199e97 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Wed, 22 Feb 2023 19:21:18 -0800 Subject: [PATCH 176/234] cleanup: Remove license type comment; they're no longer required (#1078) cleanup: Remove license type comment; they're no longer required The `# License type` comments are no longer required. Removing it makes it easier to import the source into Google. --- BUILD.bazel | 2 +- python/private/BUILD.bazel | 2 +- tools/BUILD.bazel | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/BUILD.bazel b/BUILD.bazel index 5b37fce29a..dff608a1ca 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -16,7 +16,7 @@ load(":version.bzl", "BAZEL_VERSION") package(default_visibility = ["//visibility:public"]) -licenses(["notice"]) # Apache 2.0 +licenses(["notice"]) exports_files([ "LICENSE", diff --git a/python/private/BUILD.bazel b/python/private/BUILD.bazel index d56d31b27a..7d321ebbe7 100644 --- a/python/private/BUILD.bazel +++ b/python/private/BUILD.bazel @@ -15,7 +15,7 @@ load("//python:versions.bzl", "print_toolchains_checksums") load(":stamp.bzl", "stamp_build_setting") -licenses(["notice"]) # Apache 2.0 +licenses(["notice"]) filegroup( name = "distribution", diff --git a/tools/BUILD.bazel b/tools/BUILD.bazel index 7c9b492a3c..fd951d9086 100644 --- a/tools/BUILD.bazel +++ b/tools/BUILD.bazel @@ -15,7 +15,7 @@ load("//python:defs.bzl", "py_binary") package(default_visibility = ["//visibility:public"]) -licenses(["notice"]) # Apache 2.0 +licenses(["notice"]) # Implementation detail of py_wheel rule. py_binary( From 5419e235440f68c75756e6474d3fe41eda920575 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Fri, 24 Feb 2023 11:09:08 -0800 Subject: [PATCH 177/234] fix: Use GitHub download URL for BCR URL instead of archive URL. (#1093) This is to prevent the issue where the checksum of the auto-generated archive files may change due to GitHub internal changes. Fixes #1072 --- .bcr/source.template.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bcr/source.template.json b/.bcr/source.template.json index a3bd62f161..c23b7652e7 100644 --- a/.bcr/source.template.json +++ b/.bcr/source.template.json @@ -1,5 +1,5 @@ { "integrity": "", "strip_prefix": "{REPO}-{VERSION}", - "url": "https://github.com/{OWNER}/{REPO}/archive/refs/tags/{TAG}.tar.gz" + "url": "https://github.com/{OWNER}/{REPO}/releases/download/{TAG}/rules_python-{TAG}.tar.gz" } From 797c2d031018cfe68fb1ac475c0a599671885c57 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Fri, 24 Feb 2023 13:45:42 -0800 Subject: [PATCH 178/234] Add a script to add missing license headers (#1094) Work towards #916 --- addlicense.sh | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100755 addlicense.sh diff --git a/addlicense.sh b/addlicense.sh new file mode 100755 index 0000000000..8cc8fb33bc --- /dev/null +++ b/addlicense.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +if ! command -v addlicense @>&1 >/dev/null; then + echo "ERROR: addlicense not installed." + echo "Install using https://github.com/google/addlicense#install" + exit 1 +fi + +addlicense -v -l apache -c 'The Bazel Authors. All rights reserved.' "$@" From bce3ccd0f151efa72182a4d5377d14f3d297087d Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Fri, 24 Feb 2023 23:03:07 -0800 Subject: [PATCH 179/234] fix: Update pre-commit dependency versions so isort works. (#1096) This resolve an issue where an older isort version don't work with a newer poetry version. I think this problem occurs if you've upgraded isort (which upgrades poetry, I think), but then downgrade isort (which doesn't downgrade poetry, too). --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e4ae5d3e0a..9403dd5338 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,7 +26,7 @@ repos: - id: buildifier-lint args: *args - repo: https://github.com/pycqa/isort - rev: 5.10.1 + rev: 5.12.0 hooks: - id: isort name: isort (python) @@ -34,6 +34,6 @@ repos: - --profile - black - repo: https://github.com/psf/black - rev: 22.8.0 + rev: 23.1.0 hooks: - id: black From f97e00853666f1918ff58b7b2fd846791888a02d Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Sat, 25 Feb 2023 15:55:32 -0800 Subject: [PATCH 180/234] docs: doc that the Conventional Commit style should be used for merged commits and PRs (#1099) --- CONTRIBUTING.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7b80037244..54ecfb01e5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -114,6 +114,35 @@ information on using pull requests. [GitHub Help]: https://help.github.com/articles/about-pull-requests/ +### Commit messages + +Commit messages (upon merging) and PR messages should follow the [Conventional +Commits](https://www.conventionalcommits.org/) style: + +``` +type(scope)!: + + + +BREAKING CHANGE: +``` + +Where `(scope)` is optional, and `!` is only required if there is a breaking change. +If a breaking change is introduced, then `BREAKING CHANGE:` is required. + +Common `type`s: + +* `build:` means it affects the building or development workflow. +* `docs:` means only documentation is being added, updated, or fixed. +* `feat:` means a user-visible feature is being added. +* `fix:` means a user-visible behavior is being fixed. +* `refactor:` means some sort of code cleanup that doesn't change user-visible behavior. +* `revert:` means a prior change is being reverted in some way. +* `test:` means only tests are being added. + +For the full details of types, see +[Conventional Commits](https://www.conventionalcommits.org/). + ## Generated files Some checked-in files are generated and need to be updated when a new PR is From c504355672223144cefb2cbf3f69e2d38e7e2726 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Mon, 27 Feb 2023 15:38:55 -0800 Subject: [PATCH 181/234] test(core): Add analysis tests for base Python rules. (#1102) This is to provide some regression tests for the Starlark rewrite. These tests are approximately the same as Bazel's Java-implemented tests. Work towards #1069 --- internal_deps.bzl | 7 + tools/build_defs/python/BUILD.bazel | 13 + tools/build_defs/python/tests/BUILD.bazel | 79 +++++ tools/build_defs/python/tests/base_tests.bzl | 103 +++++++ .../python/tests/fake_cc_toolchain_config.bzl | 37 +++ .../python/tests/py_binary/BUILD.bazel | 17 ++ .../tests/py_binary/py_binary_tests.bzl | 28 ++ .../python/tests/py_executable_base_tests.bzl | 272 ++++++++++++++++++ .../python/tests/py_info_subject.bzl | 95 ++++++ .../python/tests/py_library/BUILD.bazel | 18 ++ .../tests/py_library/py_library_tests.bzl | 148 ++++++++++ .../python/tests/py_test/BUILD.bazel | 18 ++ .../python/tests/py_test/py_test_tests.bzl | 98 +++++++ tools/build_defs/python/tests/util.bzl | 78 +++++ 14 files changed, 1011 insertions(+) create mode 100644 tools/build_defs/python/BUILD.bazel create mode 100644 tools/build_defs/python/tests/BUILD.bazel create mode 100644 tools/build_defs/python/tests/base_tests.bzl create mode 100644 tools/build_defs/python/tests/fake_cc_toolchain_config.bzl create mode 100644 tools/build_defs/python/tests/py_binary/BUILD.bazel create mode 100644 tools/build_defs/python/tests/py_binary/py_binary_tests.bzl create mode 100644 tools/build_defs/python/tests/py_executable_base_tests.bzl create mode 100644 tools/build_defs/python/tests/py_info_subject.bzl create mode 100644 tools/build_defs/python/tests/py_library/BUILD.bazel create mode 100644 tools/build_defs/python/tests/py_library/py_library_tests.bzl create mode 100644 tools/build_defs/python/tests/py_test/BUILD.bazel create mode 100644 tools/build_defs/python/tests/py_test/py_test_tests.bzl create mode 100644 tools/build_defs/python/tests/util.bzl diff --git a/internal_deps.bzl b/internal_deps.bzl index 11c652a50d..8f52b0e7d7 100644 --- a/internal_deps.bzl +++ b/internal_deps.bzl @@ -39,6 +39,13 @@ def rules_python_internal_deps(): ], sha256 = "8a298e832762eda1830597d64fe7db58178aa84cd5926d76d5b744d6558941c2", ) + maybe( + http_archive, + name = "rules_testing", + url = "https://github.com/bazelbuild/rules_testing/releases/download/v0.0.1/rules_testing-v0.0.1.tar.gz", + sha256 = "47db8fc9c3c1837491333cdcedebf267285479bd709a1ff0a47b19a324817def", + strip_prefix = "rules_testing-0.0.1", + ) maybe( http_archive, diff --git a/tools/build_defs/python/BUILD.bazel b/tools/build_defs/python/BUILD.bazel new file mode 100644 index 0000000000..aa21042e25 --- /dev/null +++ b/tools/build_defs/python/BUILD.bazel @@ -0,0 +1,13 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/tools/build_defs/python/tests/BUILD.bazel b/tools/build_defs/python/tests/BUILD.bazel new file mode 100644 index 0000000000..92bdc5c396 --- /dev/null +++ b/tools/build_defs/python/tests/BUILD.bazel @@ -0,0 +1,79 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("@rules_cc//cc:defs.bzl", "cc_toolchain", "cc_toolchain_suite") +load(":fake_cc_toolchain_config.bzl", "fake_cc_toolchain_config") + +platform( + name = "mac", + constraint_values = [ + "@platforms//os:macos", + ], +) + +platform( + name = "linux", + constraint_values = [ + "@platforms//os:linux", + ], +) + +cc_toolchain_suite( + name = "cc_toolchain_suite", + tags = ["manual"], + toolchains = { + "darwin_x86_64": ":mac_toolchain", + "k8": ":linux_toolchain", + }, +) + +filegroup(name = "empty") + +cc_toolchain( + name = "mac_toolchain", + all_files = ":empty", + compiler_files = ":empty", + dwp_files = ":empty", + linker_files = ":empty", + objcopy_files = ":empty", + strip_files = ":empty", + supports_param_files = 0, + toolchain_config = ":mac_toolchain_config", + toolchain_identifier = "mac-toolchain", +) + +fake_cc_toolchain_config( + name = "mac_toolchain_config", + target_cpu = "darwin_x86_64", + toolchain_identifier = "mac-toolchain", +) + +cc_toolchain( + name = "linux_toolchain", + all_files = ":empty", + compiler_files = ":empty", + dwp_files = ":empty", + linker_files = ":empty", + objcopy_files = ":empty", + strip_files = ":empty", + supports_param_files = 0, + toolchain_config = ":linux_toolchain_config", + toolchain_identifier = "linux-toolchain", +) + +fake_cc_toolchain_config( + name = "linux_toolchain_config", + target_cpu = "k8", + toolchain_identifier = "linux-toolchain", +) diff --git a/tools/build_defs/python/tests/base_tests.bzl b/tools/build_defs/python/tests/base_tests.bzl new file mode 100644 index 0000000000..715aea7fde --- /dev/null +++ b/tools/build_defs/python/tests/base_tests.bzl @@ -0,0 +1,103 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Tests common to py_test, py_binary, and py_library rules.""" + +load("@rules_testing//lib:analysis_test.bzl", "analysis_test") +load("@rules_testing//lib:truth.bzl", "matching") +load("@rules_testing//lib:util.bzl", rt_util = "util") +load("//python:defs.bzl", "PyInfo") +load("//tools/build_defs/python/tests:py_info_subject.bzl", "py_info_subject") +load("//tools/build_defs/python/tests:util.bzl", pt_util = "util") + +_tests = [] + +def _produces_py_info_impl(ctx): + return [PyInfo(transitive_sources = depset(ctx.files.srcs))] + +_produces_py_info = rule( + implementation = _produces_py_info_impl, + attrs = {"srcs": attr.label_list(allow_files = True)}, +) + +def _test_consumes_provider(name, config): + rt_util.helper_target( + config.base_test_rule, + name = name + "_subject", + deps = [name + "_produces_py_info"], + ) + rt_util.helper_target( + _produces_py_info, + name = name + "_produces_py_info", + srcs = [rt_util.empty_file(name + "_produce.py")], + ) + analysis_test( + name = name, + target = name + "_subject", + impl = _test_consumes_provider_impl, + ) + +def _test_consumes_provider_impl(env, target): + env.expect.that_target(target).provider( + PyInfo, + factory = py_info_subject, + ).transitive_sources().contains("{package}/{test_name}_produce.py") + +_tests.append(_test_consumes_provider) + +def _test_requires_provider(name, config): + rt_util.helper_target( + config.base_test_rule, + name = name + "_subject", + deps = [name + "_nopyinfo"], + ) + rt_util.helper_target( + native.filegroup, + name = name + "_nopyinfo", + ) + analysis_test( + name = name, + target = name + "_subject", + impl = _test_requires_provider_impl, + expect_failure = True, + ) + +def _test_requires_provider_impl(env, target): + env.expect.that_target(target).failures().contains_predicate( + matching.str_matches("mandatory*PyInfo"), + ) + +_tests.append(_test_requires_provider) + +def _test_data_sets_uses_shared_library(name, config): + rt_util.helper_target( + config.base_test_rule, + name = name + "_subject", + data = [rt_util.empty_file(name + "_dso.so")], + ) + analysis_test( + name = name, + target = name + "_subject", + impl = _test_data_sets_uses_shared_library_impl, + ) + +def _test_data_sets_uses_shared_library_impl(env, target): + env.expect.that_target(target).provider( + PyInfo, + factory = py_info_subject, + ).uses_shared_libraries().equals(True) + +_tests.append(_test_data_sets_uses_shared_library) + +def create_base_tests(config): + return pt_util.create_tests(_tests, config = config) diff --git a/tools/build_defs/python/tests/fake_cc_toolchain_config.bzl b/tools/build_defs/python/tests/fake_cc_toolchain_config.bzl new file mode 100644 index 0000000000..b3214a61ba --- /dev/null +++ b/tools/build_defs/python/tests/fake_cc_toolchain_config.bzl @@ -0,0 +1,37 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Fake for providing CcToolchainConfigInfo.""" + +def _impl(ctx): + return cc_common.create_cc_toolchain_config_info( + ctx = ctx, + toolchain_identifier = ctx.attr.toolchain_identifier, + host_system_name = "local", + target_system_name = "local", + target_cpu = ctx.attr.target_cpu, + target_libc = "unknown", + compiler = "clang", + abi_version = "unknown", + abi_libc_version = "unknown", + ) + +fake_cc_toolchain_config = rule( + implementation = _impl, + attrs = { + "target_cpu": attr.string(), + "toolchain_identifier": attr.string(), + }, + provides = [CcToolchainConfigInfo], +) diff --git a/tools/build_defs/python/tests/py_binary/BUILD.bazel b/tools/build_defs/python/tests/py_binary/BUILD.bazel new file mode 100644 index 0000000000..17a6690b82 --- /dev/null +++ b/tools/build_defs/python/tests/py_binary/BUILD.bazel @@ -0,0 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load(":py_binary_tests.bzl", "py_binary_test_suite") + +py_binary_test_suite(name = "py_binary_tests") diff --git a/tools/build_defs/python/tests/py_binary/py_binary_tests.bzl b/tools/build_defs/python/tests/py_binary/py_binary_tests.bzl new file mode 100644 index 0000000000..8d32632610 --- /dev/null +++ b/tools/build_defs/python/tests/py_binary/py_binary_tests.bzl @@ -0,0 +1,28 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Tests for py_binary.""" + +load("//python:defs.bzl", "py_binary") +load( + "//tools/build_defs/python/tests:py_executable_base_tests.bzl", + "create_executable_tests", +) + +def py_binary_test_suite(name): + config = struct(rule = py_binary) + + native.test_suite( + name = name, + tests = create_executable_tests(config), + ) diff --git a/tools/build_defs/python/tests/py_executable_base_tests.bzl b/tools/build_defs/python/tests/py_executable_base_tests.bzl new file mode 100644 index 0000000000..c66ea11e00 --- /dev/null +++ b/tools/build_defs/python/tests/py_executable_base_tests.bzl @@ -0,0 +1,272 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Tests common to py_binary and py_test (executable rules).""" + +load("@rules_testing//lib:analysis_test.bzl", "analysis_test") +load("@rules_testing//lib:truth.bzl", "matching") +load("@rules_testing//lib:util.bzl", rt_util = "util") +load("//tools/build_defs/python/tests:base_tests.bzl", "create_base_tests") +load("//tools/build_defs/python/tests:util.bzl", "WINDOWS_ATTR", pt_util = "util") + +_tests = [] + +def _test_executable_in_runfiles(name, config): + rt_util.helper_target( + config.rule, + name = name + "_subject", + srcs = [name + "_subject.py"], + ) + analysis_test( + name = name, + impl = _test_executable_in_runfiles_impl, + target = name + "_subject", + attrs = WINDOWS_ATTR, + ) + +_tests.append(_test_executable_in_runfiles) + +def _test_executable_in_runfiles_impl(env, target): + if pt_util.is_windows(env): + exe = ".exe" + else: + exe = "" + + env.expect.that_target(target).runfiles().contains_at_least([ + "{workspace}/{package}/{test_name}_subject" + exe, + ]) + +def _test_default_main_can_be_generated(name, config): + rt_util.helper_target( + config.rule, + name = name + "_subject", + srcs = [rt_util.empty_file(name + "_subject.py")], + ) + analysis_test( + name = name, + impl = _test_default_main_can_be_generated_impl, + target = name + "_subject", + ) + +_tests.append(_test_default_main_can_be_generated) + +def _test_default_main_can_be_generated_impl(env, target): + env.expect.that_target(target).default_outputs().contains( + "{package}/{test_name}_subject.py", + ) + +def _test_default_main_can_have_multiple_path_segments(name, config): + rt_util.helper_target( + config.rule, + name = name + "/subject", + srcs = [name + "/subject.py"], + ) + analysis_test( + name = name, + impl = _test_default_main_can_have_multiple_path_segments_impl, + target = name + "/subject", + ) + +_tests.append(_test_default_main_can_have_multiple_path_segments) + +def _test_default_main_can_have_multiple_path_segments_impl(env, target): + env.expect.that_target(target).default_outputs().contains( + "{package}/{test_name}/subject.py", + ) + +def _test_default_main_must_be_in_srcs(name, config): + # Bazel 5 will crash with a Java stacktrace when the native Python + # rules have an error. + if not pt_util.is_bazel_6_or_higher(): + rt_util.skip_test(name = name) + return + rt_util.helper_target( + config.rule, + name = name + "_subject", + srcs = ["other.py"], + ) + analysis_test( + name = name, + impl = _test_default_main_must_be_in_srcs_impl, + target = name + "_subject", + expect_failure = True, + ) + +_tests.append(_test_default_main_must_be_in_srcs) + +def _test_default_main_must_be_in_srcs_impl(env, target): + env.expect.that_target(target).failures().contains_predicate( + matching.str_matches("default*does not appear in srcs"), + ) + +def _test_default_main_cannot_be_ambiguous(name, config): + # Bazel 5 will crash with a Java stacktrace when the native Python + # rules have an error. + if not pt_util.is_bazel_6_or_higher(): + rt_util.skip_test(name = name) + return + rt_util.helper_target( + config.rule, + name = name + "_subject", + srcs = [name + "_subject.py", "other/{}_subject.py".format(name)], + ) + analysis_test( + name = name, + impl = _test_default_main_cannot_be_ambiguous_impl, + target = name + "_subject", + expect_failure = True, + ) + +_tests.append(_test_default_main_cannot_be_ambiguous) + +def _test_default_main_cannot_be_ambiguous_impl(env, target): + env.expect.that_target(target).failures().contains_predicate( + matching.str_matches("default main*matches multiple files"), + ) + +def _test_explicit_main(name, config): + rt_util.helper_target( + config.rule, + name = name + "_subject", + srcs = ["custom.py"], + main = "custom.py", + ) + analysis_test( + name = name, + impl = _test_explicit_main_impl, + target = name + "_subject", + ) + +_tests.append(_test_explicit_main) + +def _test_explicit_main_impl(env, target): + # There isn't a direct way to ask what main file was selected, so we + # rely on it being in the default outputs. + env.expect.that_target(target).default_outputs().contains( + "{package}/custom.py", + ) + +def _test_explicit_main_cannot_be_ambiguous(name, config): + # Bazel 5 will crash with a Java stacktrace when the native Python + # rules have an error. + if not pt_util.is_bazel_6_or_higher(): + rt_util.skip_test(name = name) + return + rt_util.helper_target( + config.rule, + name = name + "_subject", + srcs = ["x/foo.py", "y/foo.py"], + main = "foo.py", + ) + analysis_test( + name = name, + impl = _test_explicit_main_cannot_be_ambiguous_impl, + target = name + "_subject", + expect_failure = True, + ) + +_tests.append(_test_explicit_main_cannot_be_ambiguous) + +def _test_explicit_main_cannot_be_ambiguous_impl(env, target): + env.expect.that_target(target).failures().contains_predicate( + matching.str_matches("foo.py*matches multiple"), + ) + +def _test_files_to_build(name, config): + rt_util.helper_target( + config.rule, + name = name + "_subject", + srcs = [name + "_subject.py"], + ) + analysis_test( + name = name, + impl = _test_files_to_build_impl, + target = name + "_subject", + attrs = WINDOWS_ATTR, + ) + +_tests.append(_test_files_to_build) + +def _test_files_to_build_impl(env, target): + default_outputs = env.expect.that_target(target).default_outputs() + if pt_util.is_windows(env): + default_outputs.contains("{package}/{test_name}_subject.exe") + else: + default_outputs.contains_exactly([ + "{package}/{test_name}_subject", + "{package}/{test_name}_subject.py", + ]) + +def _test_name_cannot_end_in_py(name, config): + # Bazel 5 will crash with a Java stacktrace when the native Python + # rules have an error. + if not pt_util.is_bazel_6_or_higher(): + rt_util.skip_test(name = name) + return + rt_util.helper_target( + config.rule, + name = name + "_subject.py", + srcs = ["main.py"], + ) + analysis_test( + name = name, + impl = _test_name_cannot_end_in_py_impl, + target = name + "_subject.py", + expect_failure = True, + ) + +_tests.append(_test_name_cannot_end_in_py) + +def _test_name_cannot_end_in_py_impl(env, target): + env.expect.that_target(target).failures().contains_predicate( + matching.str_matches("name must not end in*.py"), + ) + +# Can't test this -- mandatory validation happens before analysis test +# can intercept it +# TODO(#1069): Once re-implemented in Starlark, modify rule logic to make this +# testable. +# def _test_srcs_is_mandatory(name, config): +# rt_util.helper_target( +# config.rule, +# name = name + "_subject", +# ) +# analysis_test( +# name = name, +# impl = _test_srcs_is_mandatory, +# target = name + "_subject", +# expect_failure = True, +# ) +# +# _tests.append(_test_srcs_is_mandatory) +# +# def _test_srcs_is_mandatory_impl(env, target): +# env.expect.that_target(target).failures().contains_predicate( +# matching.str_matches("mandatory*srcs"), +# ) + +# ===== +# You were gonna add a test at the end, weren't you? +# Nope. Please keep them sorted; put it in its alphabetical location. +# Here's the alphabet so you don't have to sing that song in your head: +# A B C D E F G H I J K L M N O P Q R S T U V W X Y Z +# ===== + +def create_executable_tests(config): + def _executable_with_srcs_wrapper(name, **kwargs): + if not kwargs.get("srcs"): + kwargs["srcs"] = [name + ".py"] + config.rule(name = name, **kwargs) + + config = pt_util.struct_with(config, base_test_rule = _executable_with_srcs_wrapper) + return pt_util.create_tests(_tests, config = config) + create_base_tests(config = config) diff --git a/tools/build_defs/python/tests/py_info_subject.bzl b/tools/build_defs/python/tests/py_info_subject.bzl new file mode 100644 index 0000000000..20185e55e4 --- /dev/null +++ b/tools/build_defs/python/tests/py_info_subject.bzl @@ -0,0 +1,95 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""PyInfo testing subject.""" + +load("@rules_testing//lib:truth.bzl", "subjects") + +def py_info_subject(info, *, meta): + """Creates a new `PyInfoSubject` for a PyInfo provider instance. + + Method: PyInfoSubject.new + + Args: + info: The PyInfo object + meta: ExpectMeta object. + + Returns: + A `PyInfoSubject` struct + """ + + # buildifier: disable=uninitialized + public = struct( + # go/keep-sorted start + has_py2_only_sources = lambda *a, **k: _py_info_subject_has_py2_only_sources(self, *a, **k), + has_py3_only_sources = lambda *a, **k: _py_info_subject_has_py3_only_sources(self, *a, **k), + imports = lambda *a, **k: _py_info_subject_imports(self, *a, **k), + transitive_sources = lambda *a, **k: _py_info_subject_transitive_sources(self, *a, **k), + uses_shared_libraries = lambda *a, **k: _py_info_subject_uses_shared_libraries(self, *a, **k), + # go/keep-sorted end + ) + self = struct( + actual = info, + meta = meta, + ) + return public + +def _py_info_subject_has_py2_only_sources(self): + """Returns a `BoolSubject` for the `has_py2_only_sources` attribute. + + Method: PyInfoSubject.has_py2_only_sources + """ + return subjects.bool( + self.actual.has_py2_only_sources, + meta = self.meta.derive("has_py2_only_sources()"), + ) + +def _py_info_subject_has_py3_only_sources(self): + """Returns a `BoolSubject` for the `has_py3_only_sources` attribute. + + Method: PyInfoSubject.has_py3_only_sources + """ + return subjects.bool( + self.actual.has_py3_only_sources, + meta = self.meta.derive("has_py3_only_sources()"), + ) + +def _py_info_subject_imports(self): + """Returns a `CollectionSubject` for the `imports` attribute. + + Method: PyInfoSubject.imports + """ + return subjects.collection( + self.actual.imports, + meta = self.meta.derive("imports()"), + ) + +def _py_info_subject_transitive_sources(self): + """Returns a `DepsetFileSubject` for the `transitive_sources` attribute. + + Method: PyInfoSubject.transitive_sources + """ + return subjects.depset_file( + self.actual.transitive_sources, + meta = self.meta.derive("transitive_sources()"), + ) + +def _py_info_subject_uses_shared_libraries(self): + """Returns a `BoolSubject` for the `uses_shared_libraries` attribute. + + Method: PyInfoSubject.uses_shared_libraries + """ + return subjects.bool( + self.actual.uses_shared_libraries, + meta = self.meta.derive("uses_shared_libraries()"), + ) diff --git a/tools/build_defs/python/tests/py_library/BUILD.bazel b/tools/build_defs/python/tests/py_library/BUILD.bazel new file mode 100644 index 0000000000..9de414b31b --- /dev/null +++ b/tools/build_defs/python/tests/py_library/BUILD.bazel @@ -0,0 +1,18 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Tests for py_library.""" + +load(":py_library_tests.bzl", "py_library_test_suite") + +py_library_test_suite(name = "py_library_tests") diff --git a/tools/build_defs/python/tests/py_library/py_library_tests.bzl b/tools/build_defs/python/tests/py_library/py_library_tests.bzl new file mode 100644 index 0000000000..1fcb0c19b9 --- /dev/null +++ b/tools/build_defs/python/tests/py_library/py_library_tests.bzl @@ -0,0 +1,148 @@ +"""Test for py_library.""" + +load("@rules_testing//lib:analysis_test.bzl", "analysis_test") +load("@rules_testing//lib:truth.bzl", "matching") +load("@rules_testing//lib:util.bzl", rt_util = "util") +load("//python:defs.bzl", "PyRuntimeInfo", "py_library") +load("//tools/build_defs/python/tests:base_tests.bzl", "create_base_tests") +load("//tools/build_defs/python/tests:util.bzl", pt_util = "util") + +_tests = [] + +def _test_py_runtime_info_not_present(name, config): + rt_util.helper_target( + config.rule, + name = name + "_subject", + srcs = ["lib.py"], + ) + analysis_test( + name = name, + target = name + "_subject", + impl = _test_py_runtime_info_not_present_impl, + ) + +def _test_py_runtime_info_not_present_impl(env, target): + env.expect.that_bool(PyRuntimeInfo in target).equals(False) + +_tests.append(_test_py_runtime_info_not_present) + +def _test_files_to_build(name, config): + rt_util.helper_target( + config.rule, + name = name + "_subject", + srcs = ["lib.py"], + ) + analysis_test( + name = name, + target = name + "_subject", + impl = _test_files_to_build_impl, + ) + +def _test_files_to_build_impl(env, target): + env.expect.that_target(target).default_outputs().contains_exactly([ + "{package}/lib.py", + ]) + +_tests.append(_test_files_to_build) + +def _test_srcs_can_contain_rule_generating_py_and_nonpy_files(name, config): + rt_util.helper_target( + config.rule, + name = name + "_subject", + srcs = ["lib.py", name + "_gensrcs"], + ) + rt_util.helper_target( + native.genrule, + name = name + "_gensrcs", + cmd = "touch $(OUTS)", + outs = [name + "_gen.py", name + "_gen.cc"], + ) + analysis_test( + name = name, + target = name + "_subject", + impl = _test_srcs_can_contain_rule_generating_py_and_nonpy_files_impl, + ) + +def _test_srcs_can_contain_rule_generating_py_and_nonpy_files_impl(env, target): + env.expect.that_target(target).default_outputs().contains_exactly([ + "{package}/{test_name}_gen.py", + "{package}/lib.py", + ]) + +_tests.append(_test_srcs_can_contain_rule_generating_py_and_nonpy_files) + +def _test_srcs_generating_no_py_files_is_error(name, config): + rt_util.helper_target( + config.rule, + name = name + "_subject", + srcs = [name + "_gen"], + ) + rt_util.helper_target( + native.genrule, + name = name + "_gen", + cmd = "touch $(OUTS)", + outs = [name + "_gen.cc"], + ) + analysis_test( + name = name, + target = name + "_subject", + impl = _test_srcs_generating_no_py_files_is_error_impl, + expect_failure = True, + ) + +def _test_srcs_generating_no_py_files_is_error_impl(env, target): + env.expect.that_target(target).failures().contains_predicate( + matching.str_matches("does not produce*srcs files"), + ) + +_tests.append(_test_srcs_generating_no_py_files_is_error) + +def _test_files_to_compile(name, config): + rt_util.helper_target( + config.rule, + name = name + "_subject", + srcs = ["lib1.py"], + deps = [name + "_lib2"], + ) + rt_util.helper_target( + config.rule, + name = name + "_lib2", + srcs = ["lib2.py"], + deps = [name + "_lib3"], + ) + rt_util.helper_target( + config.rule, + name = name + "_lib3", + srcs = ["lib3.py"], + ) + analysis_test( + name = name, + target = name + "_subject", + impl = _test_files_to_compile_impl, + ) + +def _test_files_to_compile_impl(env, target): + target = env.expect.that_target(target) + target.output_group( + "compilation_prerequisites_INTERNAL_", + ).contains_exactly([ + "{package}/lib1.py", + "{package}/lib2.py", + "{package}/lib3.py", + ]) + target.output_group( + "compilation_outputs", + ).contains_exactly([ + "{package}/lib1.py", + "{package}/lib2.py", + "{package}/lib3.py", + ]) + +_tests.append(_test_files_to_compile) + +def py_library_test_suite(name): + config = struct(rule = py_library, base_test_rule = py_library) + native.test_suite( + name = name, + tests = pt_util.create_tests(_tests, config = config) + create_base_tests(config), + ) diff --git a/tools/build_defs/python/tests/py_test/BUILD.bazel b/tools/build_defs/python/tests/py_test/BUILD.bazel new file mode 100644 index 0000000000..2dc0e5b51d --- /dev/null +++ b/tools/build_defs/python/tests/py_test/BUILD.bazel @@ -0,0 +1,18 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Tests for py_test.""" + +load(":py_test_tests.bzl", "py_test_test_suite") + +py_test_test_suite(name = "py_test_tests") diff --git a/tools/build_defs/python/tests/py_test/py_test_tests.bzl b/tools/build_defs/python/tests/py_test/py_test_tests.bzl new file mode 100644 index 0000000000..f2b4875b15 --- /dev/null +++ b/tools/build_defs/python/tests/py_test/py_test_tests.bzl @@ -0,0 +1,98 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Tests for py_test.""" + +load("@rules_testing//lib:analysis_test.bzl", "analysis_test") +load("@rules_testing//lib:util.bzl", rt_util = "util") +load("//python:defs.bzl", "py_test") +load( + "//tools/build_defs/python/tests:py_executable_base_tests.bzl", + "create_executable_tests", +) +load("//tools/build_defs/python/tests:util.bzl", pt_util = "util") + +_tests = [] + +def _test_mac_requires_darwin_for_execution(name, config): + # Bazel 5.4 has a bug where every access of testing.ExecutionInfo is + # a different object that isn't equal to any other, which prevents + # rules_testing from detecting it properly and fails with an error. + # This is fixed in Bazel 6+. + if not pt_util.is_bazel_6_or_higher(): + rt_util.skip_test(name = name) + return + + rt_util.helper_target( + config.rule, + name = name + "_subject", + srcs = [name + "_subject.py"], + ) + analysis_test( + name = name, + impl = _test_mac_requires_darwin_for_execution_impl, + target = name + "_subject", + config_settings = { + "//command_line_option:cpu": "darwin_x86_64", + "//command_line_option:crosstool_top": "@rules_python//tools/build_defs/python/tests:cc_toolchain_suite", + #"//command_line_option:platforms": "@rules_python//tools/build_defs/python/tests:mac", + }, + ) + +def _test_mac_requires_darwin_for_execution_impl(env, target): + env.expect.that_target(target).provider( + testing.ExecutionInfo, + ).requirements().keys().contains("requires-darwin") + +_tests.append(_test_mac_requires_darwin_for_execution) + +def _test_non_mac_doesnt_require_darwin_for_execution(name, config): + # Bazel 5.4 has a bug where every access of testing.ExecutionInfo is + # a different object that isn't equal to any other, which prevents + # rules_testing from detecting it properly and fails with an error. + # This is fixed in Bazel 6+. + if not pt_util.is_bazel_6_or_higher(): + rt_util.skip_test(name = name) + return + rt_util.helper_target( + config.rule, + name = name + "_subject", + srcs = [name + "_subject.py"], + ) + analysis_test( + name = name, + impl = _test_non_mac_doesnt_require_darwin_for_execution_impl, + target = name + "_subject", + config_settings = { + "//command_line_option:cpu": "k8", + "//command_line_option:crosstool_top": "@rules_python//tools/build_defs/python/tests:cc_toolchain_suite", + #"//command_line_option:platforms": "@rules_python//tools/build_defs/python/tests:linux", + }, + ) + +def _test_non_mac_doesnt_require_darwin_for_execution_impl(env, target): + # Non-mac builds don't have the provider at all. + if testing.ExecutionInfo not in target: + return + env.expect.that_target(target).provider( + testing.ExecutionInfo, + ).requirements().keys().not_contains("requires-darwin") + +_tests.append(_test_non_mac_doesnt_require_darwin_for_execution) + +def py_test_test_suite(name): + config = struct(rule = py_test) + native.test_suite( + name = name, + tests = pt_util.create_tests(_tests, config = config) + create_executable_tests(config), + ) diff --git a/tools/build_defs/python/tests/util.bzl b/tools/build_defs/python/tests/util.bzl new file mode 100644 index 0000000000..9b386ca3bd --- /dev/null +++ b/tools/build_defs/python/tests/util.bzl @@ -0,0 +1,78 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Helpers and utilities multiple tests re-use.""" + +load("@bazel_skylib//lib:structs.bzl", "structs") + +# Use this with is_windows() +WINDOWS_ATTR = {"windows": attr.label(default = "@platforms//os:windows")} + +def _create_tests(tests, **kwargs): + test_names = [] + for func in tests: + test_name = _test_name_from_function(func) + func(name = test_name, **kwargs) + test_names.append(test_name) + return test_names + +def _test_name_from_function(func): + """Derives the name of the given rule implementation function. + + Args: + func: the function whose name to extract + + Returns: + The name of the given function. Note it will have leading and trailing + "_" stripped -- this allows passing a private function and having the + name of the test not start with "_". + """ + + # Starlark currently stringifies a function as "", so we use + # that knowledge to parse the "NAME" portion out. + # NOTE: This is relying on an implementation detail of Bazel + func_name = str(func) + func_name = func_name.partition("")[0] + func_name = func_name.partition(" ")[0] + return func_name.strip("_") + +def _struct_with(s, **kwargs): + struct_dict = structs.to_dict(s) + struct_dict.update(kwargs) + return struct(**struct_dict) + +def _is_bazel_6_or_higher(): + # Bazel 5.4 has a bug where every access of testing.ExecutionInfo is a + # different object that isn't equal to any other. This is fixed in bazel 6+. + return testing.ExecutionInfo == testing.ExecutionInfo + +def _is_windows(env): + """Tell if the target platform is windows. + + This assumes the `WINDOWS_ATTR` attribute was added. + + Args: + env: The test env struct + Returns: + True if the target is Windows, False if not. + """ + constraint = env.ctx.attr.windows[platform_common.ConstraintValueInfo] + return env.ctx.target_platform_has_constraint(constraint) + +util = struct( + create_tests = _create_tests, + struct_with = _struct_with, + is_bazel_6_or_higher = _is_bazel_6_or_higher, + is_windows = _is_windows, +) From 51458e88f7223d8d7db282018f085828e9a5a312 Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Sat, 4 Mar 2023 19:35:15 -0800 Subject: [PATCH 182/234] chore: fix some lingering GH archive URLs (#1108) This was pointed out in a thread on bazel-discuss@googlegroups.com --- .github/workflows/create_archive_and_notes.sh | 7 ++++ README.md | 3 +- examples/build_file_generation/WORKSPACE | 37 ++----------------- gazelle/README.md | 19 +--------- 4 files changed, 15 insertions(+), 51 deletions(-) diff --git a/.github/workflows/create_archive_and_notes.sh b/.github/workflows/create_archive_and_notes.sh index 549af074eb..0c0c4acf41 100755 --- a/.github/workflows/create_archive_and_notes.sh +++ b/.github/workflows/create_archive_and_notes.sh @@ -87,5 +87,12 @@ http_archive( strip_prefix = "${PREFIX}/gazelle", url = "https://github.com/bazelbuild/rules_python/releases/download/${TAG}/rules_python-${TAG}.tar.gz", ) + +# To compile the rules_python gazelle extension from source, +# we must fetch some third-party go dependencies that it uses. + +load("@rules_python_gazelle_plugin//:deps.bzl", _py_gazelle_deps = "gazelle_deps") + +_py_gazelle_deps() \`\`\` EOF diff --git a/README.md b/README.md index a509e28d7e..07acaf8e19 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,8 @@ rules_python_version = "740825b7f74930c62f44af95c9a4c1bd428d2c53" # Latest @ 202 http_archive( name = "rules_python", - sha256 = "3474c5815da4cb003ff22811a36a11894927eda1c2e64bf2dac63e914bfdf30f", + # Bazel will print the proper value to add here during the first build. + # sha256 = "FIXME", strip_prefix = "rules_python-{}".format(rules_python_version), url = "https://github.com/bazelbuild/rules_python/archive/{}.zip".format(rules_python_version), ) diff --git a/examples/build_file_generation/WORKSPACE b/examples/build_file_generation/WORKSPACE index 674b9eb7ea..9f1dae8aaf 100644 --- a/examples/build_file_generation/WORKSPACE +++ b/examples/build_file_generation/WORKSPACE @@ -55,49 +55,20 @@ gazelle_dependencies() # Remaining setup is for rules_python. -# You do not want to use the following command when you are using a WORKSPACE file -# that is outside of rules_python repository. -# This command allows targets from a local directory to be bound. -# Which allows bazel to use targets defined in base rules_python directory. -# If you are using this example outside of the rules_python git repo, -# use the http_archive command that is commented out below. -# https://bazel.build/reference/be/workspace#local_repository +# DON'T COPY_PASTE THIS. +# Our example uses `local_repository` to point to the HEAD version of rules_python. +# Users should instead use the installation instructions from the release they use. +# See https://github.com/bazelbuild/rules_python/releases local_repository( name = "rules_python", path = "../..", ) -# When not using this example in the rules_python git repo you would load the python -# ruleset using the following StarLark. -# See https://github.com/bazelbuild/rules_python#getting-started for the latest -# ruleset version. -# -# The following StarLark would replace the `local_repository` rule mentioned above. -# -# load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") -# http_archive( -# name = "rules_python", -# sha256 = "497ca47374f48c8b067d786b512ac10a276211810f4a580178ee9b9ad139323a", -# strip_prefix = "rules_python-0.16.1", -# url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/0.16.1.tar.gz", -# ) - -# We import the repository-local rules_python_gazelle_plugin version in order to -# be able to test development changes to the plugin. local_repository( name = "rules_python_gazelle_plugin", path = "../../gazelle", ) -# When loading the gazelle plugin outside this repo, use the http_archive rule as follows: -# -#http_archive( -# name = "rules_python_gazelle_plugin", -# sha256 = "497ca47374f48c8b067d786b512ac10a276211810f4a580178ee9b9ad139323a", -# strip_prefix = "rules_python-0.16.1/gazelle", -# url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/0.16.1.tar.gz", -#) - # Next we load the toolchain from rules_python. load("@rules_python//python:repositories.bzl", "python_register_toolchains") diff --git a/gazelle/README.md b/gazelle/README.md index a76ac59199..0081701241 100644 --- a/gazelle/README.md +++ b/gazelle/README.md @@ -14,23 +14,8 @@ Follow the instructions at https://github.com/bazelbuild/bazel-gazelle#running-g Next, we need to fetch the third-party Go libraries that the python extension depends on. -Add this to your `WORKSPACE`: - -```starlark -http_archive( - name = "rules_python_gazelle_plugin", - sha256 = "", - strip_prefix = "rules_python-0.17.0/gazelle", - url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/0.17.0.tar.gz", -) - -# To compile the rules_python gazelle extension from source, -# we must fetch some third-party go dependencies that it uses. - -load("@rules_python_gazelle_plugin//:deps.bzl", _py_gazelle_deps = "gazelle_deps") - -_py_gazelle_deps() -``` +See the installation `WORKSPACE` snippet on the Releases page: +https://github.com/bazelbuild/rules_python/releases Next, we'll fetch metadata about your Python dependencies, so that gazelle can determine which package a given import statement comes from. This is provided From 7d82f06e7ba1cf217c6d855cd5ffbb3b6598587c Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius Date: Mon, 6 Mar 2023 10:33:30 +0900 Subject: [PATCH 183/234] feat: add bzlmod support for gazelle plugin (#1077) * feat: add optional pkg alias generation to pip_repository * feat: support using aliases in gazelle * doc: migrate gazelle example to use user friendly aliases * feat: gazelle supports bzlmod * chore: update gazelle plugin deps * chore: bazel run //:gazelle * fix: remove deps that are imported as bazel deps See: bazelbuild/bazel-gazelle#1403 * ci: add build_file_generation to show that we support bzlmod --- .bazelci/presubmit.yml | 34 +++++++++ docs/pip_repository.md | 13 ++-- examples/build_file_generation/BUILD.bazel | 5 +- examples/build_file_generation/MODULE.bazel | 43 +++++++++++ examples/build_file_generation/WORKSPACE | 2 + .../build_file_generation/gazelle_python.yaml | 3 +- gazelle/MODULE.bazel | 20 ++++++ gazelle/deps.bzl | 57 ++++----------- gazelle/go.mod | 2 - gazelle/manifest/defs.bzl | 11 ++- gazelle/manifest/generate/generate.go | 23 ++++-- gazelle/manifest/manifest.go | 3 + gazelle/python/BUILD.bazel | 1 - gazelle/pythonconfig/pythonconfig.go | 10 ++- python/extensions.bzl | 1 + python/pip_install/pip_repository.bzl | 72 +++++++++++++++++-- 16 files changed, 231 insertions(+), 69 deletions(-) create mode 100644 examples/build_file_generation/MODULE.bazel create mode 100644 gazelle/MODULE.bazel diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index a1b16bbc66..a0d9a19047 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -73,6 +73,14 @@ tasks: build_targets: ["//..."] test_targets: ["//..."] working_directory: gazelle + gazelle_extension_bzlmod: + <<: *common_bzlmod_flags + name: Test the Gazelle extension under bzlmod + platform: ubuntu2004 + build_targets: ["//..."] + test_targets: ["//..."] + working_directory: gazelle + ubuntu_min: <<: *minimum_supported_version <<: *reusable_config @@ -138,6 +146,32 @@ tasks: working_directory: examples/build_file_generation platform: windows + integration_test_build_file_generation_bzlmod_ubuntu: + <<: *minimum_supported_bzlmod_version + <<: *common_bzlmod_flags + <<: *reusable_build_test_all + name: build_file_generation_bzlmod integration tests on Ubuntu + working_directory: examples/build_file_generation + platform: ubuntu2004 + integration_test_build_file_generation_bzlmod_debian: + <<: *common_bzlmod_flags + <<: *reusable_build_test_all + name: build_file_generation_bzlmod integration tests on Debian + working_directory: examples/build_file_generation + platform: debian11 + integration_test_build_file_generation_bzlmod_macos: + <<: *common_bzlmod_flags + <<: *reusable_build_test_all + name: build_file_generation_bzlmod integration tests on macOS + working_directory: examples/build_file_generation + platform: macos + integration_test_build_file_generation_bzlmod_windows: + <<: *common_bzlmod_flags + <<: *reusable_build_test_all + name: build_file_generation_bzlmod integration tests on Windows + working_directory: examples/build_file_generation + platform: windows + integration_test_bzlmod_ubuntu_min: <<: *minimum_supported_bzlmod_version <<: *reusable_build_test_all diff --git a/docs/pip_repository.md b/docs/pip_repository.md index 2ccdc64854..c02058e08d 100644 --- a/docs/pip_repository.md +++ b/docs/pip_repository.md @@ -8,9 +8,10 @@
 pip_repository(name, annotations, download_only, enable_implicit_namespace_pkgs, environment,
-               extra_pip_args, isolated, pip_data_exclude, python_interpreter,
-               python_interpreter_target, quiet, repo_mapping, repo_prefix, requirements_darwin,
-               requirements_linux, requirements_lock, requirements_windows, timeout)
+               extra_pip_args, incompatible_generate_aliases, isolated, pip_data_exclude,
+               python_interpreter, python_interpreter_target, quiet, repo_mapping, repo_prefix,
+               requirements_darwin, requirements_linux, requirements_lock, requirements_windows,
+               timeout)
 
A rule for importing `requirements.txt` dependencies into Bazel. @@ -64,6 +65,7 @@ py_binary( | enable_implicit_namespace_pkgs | If true, disables conversion of native namespace packages into pkg-util style namespace packages. When set all py_binary and py_test targets must specify either legacy_create_init=False or the global Bazel option --incompatible_default_to_explicit_init_py to prevent __init__.py being automatically generated in every directory.

This option is required to support some packages which cannot handle the conversion to pkg-util style. | Boolean | optional | False | | environment | Environment variables to set in the pip subprocess. Can be used to set common variables such as http_proxy, https_proxy and no_proxy Note that pip is run with "--isolated" on the CLI so PIP_<VAR>_<NAME> style env vars are ignored, but env vars that control requests and urllib3 can be passed. | Dictionary: String -> String | optional | {} | | extra_pip_args | Extra arguments to pass on to pip. Must not contain spaces. | List of strings | optional | [] | +| incompatible_generate_aliases | Allow generating aliases '@pip//<pkg>' -> '@pip_<pkg>//:pkg'. | Boolean | optional | False | | isolated | Whether or not to pass the [--isolated](https://pip.pypa.io/en/stable/cli/pip/#cmdoption-isolated) flag to the underlying pip command. Alternatively, the RULES_PYTHON_PIP_ISOLATED enviornment varaible can be used to control this flag. | Boolean | optional | True | | pip_data_exclude | Additional data exclusion parameters to add to the pip packages BUILD file. | List of strings | optional | [] | | python_interpreter | The python interpreter to use. This can either be an absolute path or the name of a binary found on the host's PATH environment variable. If no value is set python3 is defaulted for Unix systems and python.exe for Windows. | String | optional | "" | @@ -83,8 +85,8 @@ py_binary( ## pip_repository_bzlmod
-pip_repository_bzlmod(name, repo_mapping, requirements_darwin, requirements_linux,
-                      requirements_lock, requirements_windows)
+pip_repository_bzlmod(name, incompatible_generate_aliases, repo_mapping, requirements_darwin,
+                      requirements_linux, requirements_lock, requirements_windows)
 
A rule for bzlmod pip_repository creation. Intended for private use only. @@ -95,6 +97,7 @@ A rule for bzlmod pip_repository creation. Intended for private use only. | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this repository. | Name | required | | +| incompatible_generate_aliases | Allow generating aliases in '@pip//:<pkg>' -> '@pip_<pkg>//:pkg'. This replaces the aliases generated by the bzlmod tooling. | Boolean | optional | False | | repo_mapping | A dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.<p>For example, an entry "@foo": "@bar" declares that, for any time this repository depends on @foo (such as a dependency on @foo//some:target, it should actually resolve that dependency within globally-declared @bar (@bar//some:target). | Dictionary: String -> String | required | | | requirements_darwin | Override the requirements_lock attribute when the host platform is Mac OS | Label | optional | None | | requirements_linux | Override the requirements_lock attribute when the host platform is Linux | Label | optional | None | diff --git a/examples/build_file_generation/BUILD.bazel b/examples/build_file_generation/BUILD.bazel index 6419ef2c70..7c88d9203d 100644 --- a/examples/build_file_generation/BUILD.bazel +++ b/examples/build_file_generation/BUILD.bazel @@ -43,6 +43,9 @@ gazelle_python_manifest( modules_mapping = ":modules_map", pip_repository_name = "pip", requirements = "//:requirements_lock.txt", + # NOTE: we can use this flag in order to make our setup compatible with + # bzlmod. + use_pip_repository_aliases = True, ) # Our gazelle target points to the python gazelle binary. @@ -65,7 +68,7 @@ py_library( visibility = ["//:__subpackages__"], deps = [ "//random_number_generator", - "@pip_flask//:pkg", + "@pip//flask", ], ) diff --git a/examples/build_file_generation/MODULE.bazel b/examples/build_file_generation/MODULE.bazel new file mode 100644 index 0000000000..5f79fec486 --- /dev/null +++ b/examples/build_file_generation/MODULE.bazel @@ -0,0 +1,43 @@ +module( + name = "example_bzlmod", + version = "0.0.0", + compatibility_level = 1, +) + +bazel_dep(name = "rules_python", version = "0.19.0") +bazel_dep(name = "rules_python_gazelle_plugin", version = "0.19.0") +bazel_dep(name = "gazelle", version = "0.29.0", repo_name = "bazel_gazelle") + +# local overrides for the packages for CI purposes. +# for usual setups you should remove this block. +local_path_override( + module_name = "rules_python", + path = "../..", +) + +local_path_override( + module_name = "rules_python_gazelle_plugin", + path = "../../gazelle", +) + +# Register python toolchain +python = use_extension("@rules_python//python:extensions.bzl", "python") +python.toolchain( + name = "python3_9", + python_version = "3.9", +) +use_repo(python, "python3_9_toolchains") + +register_toolchains( + "@python3_9_toolchains//:all", +) + +pip = use_extension("@rules_python//python:extensions.bzl", "pip") +pip.parse( + name = "pip", + # Generate user friendly alias labels for each dependency that we have. + incompatible_generate_aliases = True, + requirements_lock = "//:requirements_lock.txt", + requirements_windows = "//:requirements_windows.txt", +) +use_repo(pip, "pip") diff --git a/examples/build_file_generation/WORKSPACE b/examples/build_file_generation/WORKSPACE index 9f1dae8aaf..65e0a6e5f3 100644 --- a/examples/build_file_generation/WORKSPACE +++ b/examples/build_file_generation/WORKSPACE @@ -90,6 +90,8 @@ load("@rules_python//python:pip.bzl", "pip_parse") # You can instead check this `requirements.bzl` file into your repo. pip_parse( name = "pip", + # Generate user friendly alias labels for each dependency that we have. + incompatible_generate_aliases = True, # (Optional) You can provide a python_interpreter (path) or a python_interpreter_target (a Bazel target, that # acts as an executable). The latter can be anything that could be used as Python interpreter. E.g.: # 1. Python interpreter that you compile in the build file. diff --git a/examples/build_file_generation/gazelle_python.yaml b/examples/build_file_generation/gazelle_python.yaml index 847d1ecc55..b57e9f02bc 100644 --- a/examples/build_file_generation/gazelle_python.yaml +++ b/examples/build_file_generation/gazelle_python.yaml @@ -114,4 +114,5 @@ manifest: zipp.py310compat: zipp pip_repository: name: pip -integrity: 2c84a3cabeaff134a1d045e5a173a3178086f236ab20f895ffbd7f3b7a6e5bb0 + use_pip_repository_aliases: true +integrity: 85f073e37e31339508aaaf5e0d5472adae5148fd5f054e9cc586343c026660e1 diff --git a/gazelle/MODULE.bazel b/gazelle/MODULE.bazel new file mode 100644 index 0000000000..bd634020f3 --- /dev/null +++ b/gazelle/MODULE.bazel @@ -0,0 +1,20 @@ +module( + name = "rules_python_gazelle_plugin", + version = "0.0.0", + compatibility_level = 1, +) + +bazel_dep(name = "rules_python", version = "0.18.0") +bazel_dep(name = "rules_go", version = "0.38.1", repo_name = "io_bazel_rules_go") +bazel_dep(name = "gazelle", version = "0.29.0", repo_name = "bazel_gazelle") + +go_deps = use_extension("@bazel_gazelle//:extensions.bzl", "go_deps") +go_deps.from_file(go_mod = "//:go.mod") +use_repo( + go_deps, + "com_github_bazelbuild_buildtools", + "com_github_bmatcuk_doublestar", + "com_github_emirpasic_gods", + "com_github_ghodss_yaml", + "in_gopkg_yaml_v2", +) diff --git a/gazelle/deps.bzl b/gazelle/deps.bzl index 357944302c..26f8c66aec 100644 --- a/gazelle/deps.bzl +++ b/gazelle/deps.bzl @@ -28,12 +28,7 @@ def gazelle_deps(): sum = "h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs=", version = "v0.0.0-20190523083050-ea95bdfd59fc", ) - go_repository( - name = "com_github_bazelbuild_bazel_gazelle", - importpath = "github.com/bazelbuild/bazel-gazelle", - sum = "h1:+/ZhUxlDy4XnyMIGeKkbRZoIGssy1eO51GijwIvvuwE=", - version = "v0.27.0", - ) + go_repository( name = "com_github_bazelbuild_buildtools", build_naming_convention = "go_default_library", @@ -41,24 +36,14 @@ def gazelle_deps(): sum = "h1:jhiMzJ+8unnLRtV8rpbWBFE9pFNzIqgUTyZU5aA++w8=", version = "v0.0.0-20221004120235-7186f635531b", ) - go_repository( - name = "com_github_bazelbuild_rules_go", - importpath = "github.com/bazelbuild/rules_go", - sum = "h1:ViPR65vOrg74JKntAUFY6qZkheBKGB6to7wFd8gCRU4=", - version = "v0.35.0", - ) + go_repository( name = "com_github_bmatcuk_doublestar", importpath = "github.com/bmatcuk/doublestar", sum = "h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0=", version = "v1.3.4", ) - go_repository( - name = "com_github_bmatcuk_doublestar_v4", - importpath = "github.com/bmatcuk/doublestar/v4", - sum = "h1:Qu+u9wR3Vd89LnlLMHvnZ5coJMWKQamqdz9/p5GNthA=", - version = "v4.2.0", - ) + go_repository( name = "com_github_burntsushi_toml", importpath = "github.com/BurntSushi/toml", @@ -113,12 +98,7 @@ def gazelle_deps(): sum = "h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=", version = "v0.1.0", ) - go_repository( - name = "com_github_fsnotify_fsnotify", - importpath = "github.com/fsnotify/fsnotify", - sum = "h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=", - version = "v1.5.4", - ) + go_repository( name = "com_github_ghodss_yaml", importpath = "github.com/ghodss/yaml", @@ -134,14 +114,14 @@ def gazelle_deps(): go_repository( name = "com_github_golang_mock", importpath = "github.com/golang/mock", - sum = "h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=", - version = "v1.6.0", + sum = "h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=", + version = "v1.1.1", ) go_repository( name = "com_github_golang_protobuf", importpath = "github.com/golang/protobuf", - sum = "h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=", - version = "v1.5.2", + sum = "h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=", + version = "v1.4.3", ) go_repository( name = "com_github_google_go_cmp", @@ -149,18 +129,7 @@ def gazelle_deps(): sum = "h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=", version = "v0.5.9", ) - go_repository( - name = "com_github_pelletier_go_toml", - importpath = "github.com/pelletier/go-toml", - sum = "h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=", - version = "v1.9.5", - ) - go_repository( - name = "com_github_pmezard_go_difflib", - importpath = "github.com/pmezard/go-difflib", - sum = "h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=", - version = "v1.0.0", - ) + go_repository( name = "com_github_prometheus_client_model", importpath = "github.com/prometheus/client_model", @@ -218,8 +187,8 @@ def gazelle_deps(): go_repository( name = "org_golang_google_protobuf", importpath = "google.golang.org/protobuf", - sum = "h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=", - version = "v1.28.0", + sum = "h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=", + version = "v1.25.0", ) go_repository( name = "org_golang_x_crypto", @@ -260,8 +229,8 @@ def gazelle_deps(): go_repository( name = "org_golang_x_sync", importpath = "golang.org/x/sync", - sum = "h1:0SH2R3f1b1VmIMG7BXbEZCBUu2dKmHschSmjqGUrW8A=", - version = "v0.0.0-20220907140024-f12130a52804", + sum = "h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=", + version = "v0.0.0-20220722155255-886fb9371eb4", ) go_repository( name = "org_golang_x_sys", diff --git a/gazelle/go.mod b/gazelle/go.mod index 6d6f0332a0..94f19e801f 100644 --- a/gazelle/go.mod +++ b/gazelle/go.mod @@ -3,9 +3,7 @@ module github.com/bazelbuild/rules_python/gazelle go 1.19 require ( - github.com/bazelbuild/bazel-gazelle v0.27.0 github.com/bazelbuild/buildtools v0.0.0-20221004120235-7186f635531b - github.com/bazelbuild/rules_go v0.35.0 github.com/bmatcuk/doublestar v1.3.4 github.com/emirpasic/gods v1.18.1 github.com/ghodss/yaml v1.0.0 diff --git a/gazelle/manifest/defs.bzl b/gazelle/manifest/defs.bzl index 78e0c272ac..05562a1583 100644 --- a/gazelle/manifest/defs.bzl +++ b/gazelle/manifest/defs.bzl @@ -24,13 +24,16 @@ def gazelle_python_manifest( modules_mapping, pip_repository_name = "", pip_deps_repository_name = "", - manifest = ":gazelle_python.yaml"): + manifest = ":gazelle_python.yaml", + use_pip_repository_aliases = False): """A macro for defining the updating and testing targets for the Gazelle manifest file. Args: name: the name used as a base for the targets. requirements: the target for the requirements.txt file. pip_repository_name: the name of the pip_install or pip_repository target. + use_pip_repository_aliases: boolean flag to enable using user-friendly + python package aliases. pip_deps_repository_name: deprecated - the old pip_install target name. modules_mapping: the target for the generated modules_mapping.json file. manifest: the target for the Gazelle manifest file. @@ -67,6 +70,12 @@ def gazelle_python_manifest( update_target_label, ] + if use_pip_repository_aliases: + update_args += [ + "--use-pip-repository-aliases", + "true", + ] + go_binary( name = update_target, embed = [Label("//manifest/generate:generate_lib")], diff --git a/gazelle/manifest/generate/generate.go b/gazelle/manifest/generate/generate.go index 0f429f8345..1f56e630cc 100644 --- a/gazelle/manifest/generate/generate.go +++ b/gazelle/manifest/generate/generate.go @@ -38,12 +38,15 @@ func init() { } func main() { - var manifestGeneratorHashPath string - var requirementsPath string - var pipRepositoryName string - var modulesMappingPath string - var outputPath string - var updateTarget string + var ( + manifestGeneratorHashPath string + requirementsPath string + pipRepositoryName string + usePipRepositoryAliases bool + modulesMappingPath string + outputPath string + updateTarget string + ) flag.StringVar( &manifestGeneratorHashPath, "manifest-generator-hash", @@ -60,6 +63,11 @@ func main() { "pip-repository-name", "", "The name of the pip_install or pip_repository target.") + flag.BoolVar( + &usePipRepositoryAliases, + "use-pip-repository-aliases", + false, + "Whether to use the pip-repository aliases, which are generated when passing 'incompatible_generate_aliases = True'.") flag.StringVar( &modulesMappingPath, "modules-mapping", @@ -103,7 +111,8 @@ func main() { manifestFile := manifest.NewFile(&manifest.Manifest{ ModulesMapping: modulesMapping, PipRepository: &manifest.PipRepository{ - Name: pipRepositoryName, + Name: pipRepositoryName, + UsePipRepositoryAliases: usePipRepositoryAliases, }, }) if err := writeOutput( diff --git a/gazelle/manifest/manifest.go b/gazelle/manifest/manifest.go index bb4826435f..c49951dd3e 100644 --- a/gazelle/manifest/manifest.go +++ b/gazelle/manifest/manifest.go @@ -144,4 +144,7 @@ type Manifest struct { type PipRepository struct { // The name of the pip_install or pip_repository target. Name string + // UsePipRepositoryAliases allows to use aliases generated pip_repository + // when passing incompatible_generate_aliases = True. + UsePipRepositoryAliases bool `yaml:"use_pip_repository_aliases,omitempty"` } diff --git a/gazelle/python/BUILD.bazel b/gazelle/python/BUILD.bazel index 3b5ded2139..ddcad2785d 100644 --- a/gazelle/python/BUILD.bazel +++ b/gazelle/python/BUILD.bazel @@ -61,7 +61,6 @@ go_test( ] + glob(["testdata/**"]), deps = [ "@bazel_gazelle//testtools:go_default_library", - "@com_github_emirpasic_gods//lists/singlylinkedlist", "@com_github_ghodss_yaml//:yaml", "@io_bazel_rules_go//go/tools/bazel:go_default_library", ], diff --git a/gazelle/pythonconfig/pythonconfig.go b/gazelle/pythonconfig/pythonconfig.go index a2fe7d51b2..ea2ae65c4c 100644 --- a/gazelle/pythonconfig/pythonconfig.go +++ b/gazelle/pythonconfig/pythonconfig.go @@ -220,10 +220,16 @@ func (c *Config) FindThirdPartyDependency(modName string) (string, bool) { } sanitizedDistribution := strings.ToLower(distributionName) sanitizedDistribution = strings.ReplaceAll(sanitizedDistribution, "-", "_") - var lbl label.Label + + if gazelleManifest.PipRepository != nil && gazelleManifest.PipRepository.UsePipRepositoryAliases { + // @// + lbl := label.New(distributionRepositoryName, sanitizedDistribution, sanitizedDistribution) + return lbl.String(), true + } + // @_//:pkg distributionRepositoryName = distributionRepositoryName + "_" + sanitizedDistribution - lbl = label.New(distributionRepositoryName, "", "pkg") + lbl := label.New(distributionRepositoryName, "", "pkg") return lbl.String(), true } } diff --git a/python/extensions.bzl b/python/extensions.bzl index 01f731f14f..75de4157bb 100644 --- a/python/extensions.bzl +++ b/python/extensions.bzl @@ -78,6 +78,7 @@ def _pip_impl(module_ctx): pip_repository_bzlmod( name = attr.name, requirements_lock = attr.requirements_lock, + incompatible_generate_aliases = attr.incompatible_generate_aliases, ) for name, requirement_line in requirements: diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl index 982d8536ba..733142ba92 100644 --- a/python/pip_install/pip_repository.bzl +++ b/python/pip_install/pip_repository.bzl @@ -261,6 +261,52 @@ A requirements_lock attribute must be specified, or a platform-specific lockfile def _clean_pkg_name(name): return name.replace("-", "_").replace(".", "_").lower() +def _pkg_aliases(rctx, repo_name, bzl_packages): + """Create alias declarations for each python dependency. + + The aliases should be appended to the pip_repository BUILD.bazel file. These aliases + allow users to use requirement() without needed a corresponding `use_repo()` for each dep + when using bzlmod. + + Args: + rctx: the repository context. + repo_name: the repository name of the parent that is visible to the users. + bzl_packages: the list of packages to setup. + """ + for name in bzl_packages: + build_content = """package(default_visibility = ["//visibility:public"]) + +alias( + name = "{name}", + actual = "@{repo_name}_{dep}//:pkg", +) + +alias( + name = "pkg", + actual = "@{repo_name}_{dep}//:pkg", +) + +alias( + name = "whl", + actual = "@{repo_name}_{dep}//:whl", +) + +alias( + name = "data", + actual = "@{repo_name}_{dep}//:data", +) + +alias( + name = "dist_info", + actual = "@{repo_name}_{dep}//:dist_info", +) +""".format( + name = name, + repo_name = repo_name, + dep = name, + ) + rctx.file("{}/BUILD.bazel".format(name), build_content) + def _bzlmod_pkg_aliases(repo_name, bzl_packages): """Create alias declarations for each python dependency. @@ -314,16 +360,21 @@ def _pip_repository_bzlmod_impl(rctx): repo_name = rctx.attr.name.split("~")[-1] - build_contents = _BUILD_FILE_CONTENTS + _bzlmod_pkg_aliases(repo_name, bzl_packages) + build_contents = _BUILD_FILE_CONTENTS + + if rctx.attr.incompatible_generate_aliases: + _pkg_aliases(rctx, repo_name, bzl_packages) + else: + build_contents += _bzlmod_pkg_aliases(repo_name, bzl_packages) rctx.file("BUILD.bazel", build_contents) rctx.template("requirements.bzl", rctx.attr._template, substitutions = { "%%ALL_REQUIREMENTS%%": _format_repr_list([ - "@{}//:{}_pkg".format(repo_name, p) + "@@{}//{}".format(repo_name, p) if rctx.attr.incompatible_generate_aliases else "@{}_{}//:pkg".format(rctx.attr.name, p) for p in bzl_packages ]), "%%ALL_WHL_REQUIREMENTS%%": _format_repr_list([ - "@{}//:{}_whl".format(repo_name, p) + "@@{}//{}:whl".format(repo_name, p) if rctx.attr.incompatible_generate_aliases else "@{}_{}//:whl".format(rctx.attr.name, p) for p in bzl_packages ]), "%%NAME%%": rctx.attr.name, @@ -331,6 +382,10 @@ def _pip_repository_bzlmod_impl(rctx): }) pip_repository_bzlmod_attrs = { + "incompatible_generate_aliases": attr.bool( + default = False, + doc = "Allow generating aliases in '@pip//:' -> '@pip_//:pkg'. This replaces the aliases generated by the `bzlmod` tooling.", + ), "requirements_darwin": attr.label( allow_single_file = True, doc = "Override the requirements_lock attribute when the host platform is Mac OS", @@ -405,14 +460,17 @@ def _pip_repository_impl(rctx): if rctx.attr.python_interpreter_target: config["python_interpreter_target"] = str(rctx.attr.python_interpreter_target) + if rctx.attr.incompatible_generate_aliases: + _pkg_aliases(rctx, rctx.attr.name, bzl_packages) + rctx.file("BUILD.bazel", _BUILD_FILE_CONTENTS) rctx.template("requirements.bzl", rctx.attr._template, substitutions = { "%%ALL_REQUIREMENTS%%": _format_repr_list([ - "@{}_{}//:pkg".format(rctx.attr.name, p) + "@{}//{}".format(rctx.attr.name, p) if rctx.attr.incompatible_generate_aliases else "@{}_{}//:pkg".format(rctx.attr.name, p) for p in bzl_packages ]), "%%ALL_WHL_REQUIREMENTS%%": _format_repr_list([ - "@{}_{}//:whl".format(rctx.attr.name, p) + "@{}//{}:whl".format(rctx.attr.name, p) if rctx.attr.incompatible_generate_aliases else "@{}_{}//:whl".format(rctx.attr.name, p) for p in bzl_packages ]), "%%ANNOTATIONS%%": _format_dict(_repr_dict(annotations)), @@ -520,6 +578,10 @@ pip_repository_attrs = { "annotations": attr.string_dict( doc = "Optional annotations to apply to packages", ), + "incompatible_generate_aliases": attr.bool( + default = False, + doc = "Allow generating aliases '@pip//' -> '@pip_//:pkg'.", + ), "requirements_darwin": attr.label( allow_single_file = True, doc = "Override the requirements_lock attribute when the host platform is Mac OS", From de8f428f4a73f39c875d1e03ba5d0be07790f534 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Sun, 5 Mar 2023 17:34:53 -0800 Subject: [PATCH 184/234] docs: Simplify pull request template (#1100) The existing template is very verbose with many of the lines not being applicable to any given PR. This also makes the PR description poorly suitable for a commit description. By having a cleaner PR description that is commit message friendly, whoever merges the PR can more easily create a meaningful commit message. It also allows other maintainer's to clean up the description prior to it being merged. --- .github/PULL_REQUEST_TEMPLATE.md | 55 +++++++------------------------- 1 file changed, 11 insertions(+), 44 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 38e0658e44..0d305b8816 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,44 +1,11 @@ -## PR Checklist - -Please check if your PR fulfills the following requirements: - -- [ ] Tests for the changes have been added (for bug fixes / features) -- [ ] Docs have been added / updated (for bug fixes / features) - - -## PR Type - -What kind of change does this PR introduce? - - - -- [ ] Bugfix -- [ ] Feature (please, look at the "Scope of the project" section in the README.md file) -- [ ] Code style update (formatting, local variables) -- [ ] Refactoring (no functional changes, no api changes) -- [ ] Build related changes -- [ ] CI related changes -- [ ] Documentation content changes -- [ ] Other... Please describe: - - -## What is the current behavior? - - -Issue Number: N/A - - -## What is the new behavior? - - -## Does this PR introduce a breaking change? - -- [ ] Yes -- [ ] No - - - - - -## Other information - +PR Instructions/requirements +* Title uses `type: description` format. See CONTRIBUTING.md for types. +* Common types are: build, docs, feat, fix, refactor, revert, test +* Breaking changes include "!" after the type and a "BREAKING CHANGES:" + section at the bottom. +* Body text describes: + * Why this change is being made, briefly. + * Before and after behavior, as applicable + * References issue number, as applicable +* Update docs and tests, as applicable +* Delete these instructions prior to sending the PR From c73dc0c4d92d9e794dc197cbc66158476e1b528a Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Mon, 6 Mar 2023 14:42:39 -0800 Subject: [PATCH 185/234] chore: fix syntax that stardoc misunderstands as HTML (#1110) Update requirements.bzl --- docs/pip.md | 4 ++-- python/pip_install/requirements.bzl | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/pip.md b/docs/pip.md index 528abf737d..e4c3f21b79 100644 --- a/docs/pip.md +++ b/docs/pip.md @@ -42,8 +42,8 @@ of some other compile_pip_requirements rule that references these requirements It also generates two targets for running pip-compile: -- validate with `bazel test <name>_test` -- update with `bazel run <name>.update` +- validate with `bazel test [name]_test` +- update with `bazel run [name].update` **PARAMETERS** diff --git a/python/pip_install/requirements.bzl b/python/pip_install/requirements.bzl index af3c194d18..dd38c9df5b 100644 --- a/python/pip_install/requirements.bzl +++ b/python/pip_install/requirements.bzl @@ -39,8 +39,8 @@ def compile_pip_requirements( It also generates two targets for running pip-compile: - - validate with `bazel test _test` - - update with `bazel run .update` + - validate with `bazel test [name]_test` + - update with `bazel run [name].update` Args: name: base name for generated targets, typically "requirements". From 244c6064f5f4e72432ec056c2ad1a0b068468a93 Mon Sep 17 00:00:00 2001 From: Mathieu Sabourin Date: Mon, 6 Mar 2023 16:22:00 -0800 Subject: [PATCH 186/234] fix: update gazelle to properly handle dot in package name. (#1083) --- gazelle/pythonconfig/BUILD.bazel | 8 ++++++- gazelle/pythonconfig/pythonconfig.go | 11 +++++++-- gazelle/pythonconfig/pythonconfig_test.go | 28 +++++++++++++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 gazelle/pythonconfig/pythonconfig_test.go diff --git a/gazelle/pythonconfig/BUILD.bazel b/gazelle/pythonconfig/BUILD.bazel index 79b512163d..d0f1690d94 100644 --- a/gazelle/pythonconfig/BUILD.bazel +++ b/gazelle/pythonconfig/BUILD.bazel @@ -1,4 +1,4 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "pythonconfig", @@ -15,6 +15,12 @@ go_library( ], ) +go_test( + name = "pythonconfig_test", + srcs = ["pythonconfig_test.go"], + deps = [":pythonconfig"], +) + filegroup( name = "distribution", srcs = glob(["**"]), diff --git a/gazelle/pythonconfig/pythonconfig.go b/gazelle/pythonconfig/pythonconfig.go index ea2ae65c4c..c7cd7c1a28 100644 --- a/gazelle/pythonconfig/pythonconfig.go +++ b/gazelle/pythonconfig/pythonconfig.go @@ -90,6 +90,14 @@ var defaultIgnoreFiles = map[string]struct{}{ "setup.py": {}, } +func SanitizeDistribution(distributionName string) string { + sanitizedDistribution := strings.ToLower(distributionName) + sanitizedDistribution = strings.ReplaceAll(sanitizedDistribution, "-", "_") + sanitizedDistribution = strings.ReplaceAll(sanitizedDistribution, ".", "_") + + return sanitizedDistribution +} + // Configs is an extension of map[string]*Config. It provides finding methods // on top of the mapping. type Configs map[string]*Config @@ -218,8 +226,7 @@ func (c *Config) FindThirdPartyDependency(modName string) (string, bool) { } else if gazelleManifest.PipRepository != nil { distributionRepositoryName = gazelleManifest.PipRepository.Name } - sanitizedDistribution := strings.ToLower(distributionName) - sanitizedDistribution = strings.ReplaceAll(sanitizedDistribution, "-", "_") + sanitizedDistribution := SanitizeDistribution(distributionName) if gazelleManifest.PipRepository != nil && gazelleManifest.PipRepository.UsePipRepositoryAliases { // @// diff --git a/gazelle/pythonconfig/pythonconfig_test.go b/gazelle/pythonconfig/pythonconfig_test.go new file mode 100644 index 0000000000..1512eb97ae --- /dev/null +++ b/gazelle/pythonconfig/pythonconfig_test.go @@ -0,0 +1,28 @@ +package pythonconfig + +import ( + "testing" + + "github.com/bazelbuild/rules_python/gazelle/pythonconfig" +) + +func TestDistributionSanitizing(t *testing.T) { + tests := map[string]struct { + input string + want string + }{ + "upper case": {input: "DistWithUpperCase", want: "distwithuppercase"}, + "dashes": {input: "dist-with-dashes", want: "dist_with_dashes"}, + "dots": {input: "dist.with.dots", want: "dist_with_dots"}, + "mixed": {input: "To-be.sanitized", want: "to_be_sanitized"}, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + got := pythonconfig.SanitizeDistribution(tc.input) + if tc.want != got { + t.Fatalf("expected %q, got %q", tc.want, got) + } + }) + } +} From 0ba98a6e3bc529af57d871e8b7e3e9a14c5d707c Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Tue, 7 Mar 2023 11:11:08 -0800 Subject: [PATCH 187/234] fix(bzlmod): expose ignore_root_user_error attribute from python_register_toolchains (#1114) --- python/extensions.bzl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/extensions.bzl b/python/extensions.bzl index 75de4157bb..42f0b58226 100644 --- a/python/extensions.bzl +++ b/python/extensions.bzl @@ -30,6 +30,7 @@ def _python_impl(module_ctx): # Toolchain registration in bzlmod is done in MODULE file register_toolchains = False, register_coverage_tool = attr.configure_coverage_tool, + ignore_root_user_error = attr.ignore_root_user_error, ) python = module_extension( @@ -41,6 +42,7 @@ python = module_extension( mandatory = False, doc = "Whether or not to configure the default coverage tool for the toolchains.", ), + "ignore_root_user_error": attr.bool(), "name": attr.string(mandatory = True), "python_version": attr.string(mandatory = True), }, From 7ffe2f7f03737448e3dc7564e80b256bc54e653c Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Tue, 7 Mar 2023 19:55:52 -0800 Subject: [PATCH 188/234] feat: add bzl_library for defs.bzl and its dependencies (#1115) This is so that the transitive dependencies of defs.bzl can be easily found and validated; some Google internal tooling does this validation. The old comment indicated bzl_library wasn't used to avoid a dependency on skylib, however, we've since added a dependency on skylib. Work towards #1069 --- python/BUILD.bazel | 14 +++++++++++++- python/private/BUILD.bazel | 20 +++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/python/BUILD.bazel b/python/BUILD.bazel index 2e275b6650..e5be3e8a53 100644 --- a/python/BUILD.bazel +++ b/python/BUILD.bazel @@ -23,6 +23,7 @@ In an ideal renaming, we'd move the packaging rules to a different package so that @rules_python//python is only concerned with the core rules. """ +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") load(":defs.bzl", "current_py_toolchain") package(default_visibility = ["//visibility:public"]) @@ -40,8 +41,19 @@ filegroup( visibility = ["//:__pkg__"], ) +bzl_library( + name = "defs_bzl", + srcs = [ + "defs.bzl", + ], + visibility = ["//visibility:public"], + deps = [ + "//python/private:bazel_tools_bzl", + "//python/private:reexports_bzl", + ], +) + # Filegroup of bzl files that can be used by downstream rules for documentation generation -# Using a filegroup rather than bzl_library to not give a transitive dependency on Skylib filegroup( name = "bzl", srcs = [ diff --git a/python/private/BUILD.bazel b/python/private/BUILD.bazel index 7d321ebbe7..f3278478b8 100644 --- a/python/private/BUILD.bazel +++ b/python/private/BUILD.bazel @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") load("//python:versions.bzl", "print_toolchains_checksums") load(":stamp.bzl", "stamp_build_setting") @@ -24,13 +25,30 @@ filegroup( ) # Filegroup of bzl files that can be used by downstream rules for documentation generation -# Using a filegroup rather than bzl_library to not give a transitive dependency on Skylib filegroup( name = "bzl", srcs = glob(["**/*.bzl"]), visibility = ["//python:__pkg__"], ) +bzl_library( + name = "reexports_bzl", + srcs = ["reexports.bzl"], + visibility = ["//python:__pkg__"], + deps = [":bazel_tools_bzl"], +) + +# @bazel_tools can't define bzl_library itself, so we just put a wrapper around it. +bzl_library( + name = "bazel_tools_bzl", + srcs = [ + "@bazel_tools//tools/python:srcs_version.bzl", + "@bazel_tools//tools/python:toolchain.bzl", + "@bazel_tools//tools/python:utils.bzl", + ], + visibility = ["//python:__pkg__"], +) + # Needed to define bzl_library targets for docgen. (We don't define the # bzl_library target here because it'd give our users a transitive dependency # on Skylib.) From 8400610298056e9ab69cf927424a39ae93dfb31f Mon Sep 17 00:00:00 2001 From: Daniel Stonier Date: Tue, 7 Mar 2023 21:51:51 -0800 Subject: [PATCH 189/234] fix: docs for ignore_root_user_error at the module level (#1112) --- python/extensions.bzl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/python/extensions.bzl b/python/extensions.bzl index 42f0b58226..2b0c188554 100644 --- a/python/extensions.bzl +++ b/python/extensions.bzl @@ -42,7 +42,11 @@ python = module_extension( mandatory = False, doc = "Whether or not to configure the default coverage tool for the toolchains.", ), - "ignore_root_user_error": attr.bool(), + "ignore_root_user_error": attr.bool( + default = False, + doc = "Whether the check for root should be ignored or not. This causes cache misses with .pyc files.", + mandatory = False, + ), "name": attr.string(mandatory = True), "python_version": attr.string(mandatory = True), }, From 5ff514ab84c0486b432340e6a04de5beb9f2fd1f Mon Sep 17 00:00:00 2001 From: Michael Krasnyk Date: Wed, 8 Mar 2023 20:16:02 +0100 Subject: [PATCH 190/234] fix: generation of toolchain aliases //:defs.bzl file. (#1088) ## PR Checklist Please check if your PR fulfills the following requirements: - [ ] Tests for the changes have been added (for bug fixes / features) - [ ] Docs have been added / updated (for bug fixes / features) ## PR Type What kind of change does this PR introduce? - [X] Bugfix - [ ] Feature (please, look at the "Scope of the project" section in the README.md file) - [ ] Code style update (formatting, local variables) - [ ] Refactoring (no functional changes, no api changes) - [ ] Build related changes - [ ] CI related changes - [ ] Documentation content changes - [ ] Other... Please describe: ## What is the current behavior? With `common --experimental_enable_bzlmod` option defs.bzl is generated as ``` load("@rules_python~override//python/config_settings:transition.bzl", _py_binary = "py_binary", _py_test = "py_test") load("@rules_python~override//python:pip.bzl", _compile_pip_requirements = "compile_pip_requirements") ``` and these lines cause a problem at ``` load("@python3_9//:defs.bzl", "interpreter") ``` as ``` ERROR: .../BUILD:25:11: error loading package 'src': at .../external/rules_python~override~python~python3_9/defs.bzl:4:6: Unable to find package for @[unknown repo 'rules_python~override' requested from @rules_python~override~python~python3_9]//python:pip.bzl: The repository '@[unknown repo 'rules_python~override' requested from @rules_python~override~python~python3_9]' could not be resolved: No repository visible as '@rules_python~override' from repository '@rules_python~override~python~python3_9'. and referenced by '...' ``` Issue Number: N/A ## What is the new behavior? Generated load statements ``` load("@@rules_python~override//python/config_settings:transition.bzl", _py_binary = "py_binary", _py_test = "py_test") load("@@rules_python~override//python:pip.bzl", _compile_pip_requirements = "compile_pip_requirements") ``` ## Does this PR introduce a breaking change? - [ ] Yes - [X] No ## Other information --- examples/bzlmod/BUILD.bazel | 8 ++++++++ examples/bzlmod/MODULE.bazel | 1 + python/private/toolchains_repo.bzl | 17 +++++++++-------- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/examples/bzlmod/BUILD.bazel b/examples/bzlmod/BUILD.bazel index 7b7566bd5a..7ecc035853 100644 --- a/examples/bzlmod/BUILD.bazel +++ b/examples/bzlmod/BUILD.bazel @@ -1,4 +1,5 @@ load("@pip//:requirements.bzl", "requirement") +load("@python3_9//:defs.bzl", py_test_with_transition = "py_test") load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test") load("@rules_python//python:pip.bzl", "compile_pip_requirements") @@ -35,3 +36,10 @@ py_test( srcs = ["test.py"], deps = [":lib"], ) + +py_test_with_transition( + name = "test_with_transition", + srcs = ["test.py"], + main = "test.py", + deps = [":lib"], +) diff --git a/examples/bzlmod/MODULE.bazel b/examples/bzlmod/MODULE.bazel index 5f984c39df..ce9122810c 100644 --- a/examples/bzlmod/MODULE.bazel +++ b/examples/bzlmod/MODULE.bazel @@ -16,6 +16,7 @@ python.toolchain( configure_coverage_tool = True, python_version = "3.9", ) +use_repo(python, "python3_9") use_repo(python, "python3_9_toolchains") register_toolchains( diff --git a/python/private/toolchains_repo.bzl b/python/private/toolchains_repo.bzl index 4b832d941a..9bed73e55c 100644 --- a/python/private/toolchains_repo.bzl +++ b/python/private/toolchains_repo.bzl @@ -31,10 +31,13 @@ load( "WINDOWS_NAME", ) +def get_repository_name(repository_workspace): + dummy_label = "//:_" + return str(repository_workspace.relative(dummy_label))[:-len(dummy_label)] or "@" + def _toolchains_repo_impl(rctx): - rules_python_repository_name = rctx.attr._rules_python_workspace.workspace_name - python_version_constraint = "@{rules_python}//python/config_settings:is_python_{python_version}".format( - rules_python = rules_python_repository_name, + python_version_constraint = "{rules_python}//python/config_settings:is_python_{python_version}".format( + rules_python = get_repository_name(rctx.attr._rules_python_workspace), python_version = rctx.attr.python_version, ) @@ -90,8 +93,6 @@ def _toolchain_aliases_impl(rctx): is_windows = (os_name == WINDOWS_NAME) python3_binary_path = "python.exe" if is_windows else "bin/python3" - rules_python_repository_name = rctx.attr._rules_python_workspace.workspace_name - # Base BUILD file for this repository. build_contents = """\ # Generated by python/private/toolchains_repo.bzl @@ -123,8 +124,8 @@ alias(name = "pip", actual = select({{":" + item: "@{py_repository}_ rctx.file("defs.bzl", content = """\ # Generated by python/private/toolchains_repo.bzl -load("@{rules_python}//python/config_settings:transition.bzl", _py_binary = "py_binary", _py_test = "py_test") -load("@{rules_python}//python:pip.bzl", _compile_pip_requirements = "compile_pip_requirements") +load("{rules_python}//python/config_settings:transition.bzl", _py_binary = "py_binary", _py_test = "py_test") +load("{rules_python}//python:pip.bzl", _compile_pip_requirements = "compile_pip_requirements") host_platform = "{host_platform}" interpreter = "@{py_repository}_{host_platform}//:{python3_binary_path}" @@ -156,7 +157,7 @@ def compile_pip_requirements(name, **kwargs): py_repository = rctx.attr.user_repository_name, python_version = rctx.attr.python_version, python3_binary_path = python3_binary_path, - rules_python = rules_python_repository_name, + rules_python = get_repository_name(rctx.attr._rules_python_workspace), )) toolchain_aliases = repository_rule( From 1c5b92b279481ddcdfbd71058857e5eb3ebac724 Mon Sep 17 00:00:00 2001 From: Daniel Stonier Date: Wed, 8 Mar 2023 16:46:55 -0800 Subject: [PATCH 191/234] feat: make variable substitution for py_wheel abi, python_tag args (#1113) Expands make variables in to `abi` and `python_tag` attributes --------- Co-authored-by: Richard Levasseur --- examples/wheel/BUILD.bazel | 25 ++++++++++++++++++++++++- examples/wheel/private/wheel_utils.bzl | 17 +++++++++++++++++ python/private/py_wheel.bzl | 11 +++++++---- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/examples/wheel/BUILD.bazel b/examples/wheel/BUILD.bazel index 4124a826d1..61a43ae6cf 100644 --- a/examples/wheel/BUILD.bazel +++ b/examples/wheel/BUILD.bazel @@ -13,7 +13,7 @@ # limitations under the License. load("@bazel_skylib//rules:build_test.bzl", "build_test") -load("//examples/wheel/private:wheel_utils.bzl", "directory_writer") +load("//examples/wheel/private:wheel_utils.bzl", "directory_writer", "make_variable_tags") load("//python:defs.bzl", "py_library", "py_test") load("//python:packaging.bzl", "py_package", "py_wheel") load("//python:versions.bzl", "gen_python_config_settings") @@ -62,6 +62,29 @@ py_wheel( ], ) +# Populate a rule with "Make Variable" arguments for +# abi, python_tag and version. You might want to do this +# for the following use cases: +# - abi, python_tag: introspect a toolchain to map to appropriate cpython tags +# - version: populate given this or a dependent module's version +make_variable_tags( + name = "make_variable_tags", +) + +py_wheel( + name = "minimal_with_py_library_with_make_variables", + testonly = True, + abi = "$(ABI)", + distribution = "example_minimal_library", + python_tag = "$(PYTHON_TAG)", + toolchains = ["//examples/wheel:make_variable_tags"], + version = "$(VERSION)", + deps = [ + "//examples/wheel/lib:module_with_data", + "//examples/wheel/lib:simple_module", + ], +) + build_test( name = "dist_build_tests", targets = [":minimal_with_py_library.dist"], diff --git a/examples/wheel/private/wheel_utils.bzl b/examples/wheel/private/wheel_utils.bzl index af4fa1958b..037fed0175 100644 --- a/examples/wheel/private/wheel_utils.bzl +++ b/examples/wheel/private/wheel_utils.bzl @@ -54,3 +54,20 @@ directory_writer = rule( ), }, ) + +def _make_variable_tags_impl(ctx): # buildifier: disable=unused-variable + # This example is contrived. In a real usage, this rule would + # look at flags or dependencies to determine what values to use. + # If all you're doing is setting constant values, then you can simply + # set them in the py_wheel() call. + vars = {} + vars["ABI"] = "cp38" + vars["PYTHON_TAG"] = "cp38" + vars["VERSION"] = "0.99.0" + return [platform_common.TemplateVariableInfo(vars)] + +make_variable_tags = rule( + attrs = {}, + doc = """Make variable tags to pass to a py_wheel rule.""", + implementation = _make_variable_tags_impl, +) diff --git a/python/private/py_wheel.bzl b/python/private/py_wheel.bzl index 77690edc65..b6f2bfae56 100644 --- a/python/private/py_wheel.bzl +++ b/python/private/py_wheel.bzl @@ -207,12 +207,15 @@ def _input_file_to_arg(input_file): return "%s;%s" % (py_package_lib.path_inside_wheel(input_file), input_file.path) def _py_wheel_impl(ctx): + abi = _replace_make_variables(ctx.attr.abi, ctx) + python_tag = _replace_make_variables(ctx.attr.python_tag, ctx) version = _replace_make_variables(ctx.attr.version, ctx) + outfile = ctx.actions.declare_file("-".join([ _escape_filename_segment(ctx.attr.distribution), _escape_filename_segment(version), - _escape_filename_segment(ctx.attr.python_tag), - _escape_filename_segment(ctx.attr.abi), + _escape_filename_segment(python_tag), + _escape_filename_segment(abi), _escape_filename_segment(ctx.attr.platform), ]) + ".whl") @@ -237,8 +240,8 @@ def _py_wheel_impl(ctx): args = ctx.actions.args() args.add("--name", ctx.attr.distribution) args.add("--version", version) - args.add("--python_tag", ctx.attr.python_tag) - args.add("--abi", ctx.attr.abi) + args.add("--python_tag", python_tag) + args.add("--abi", abi) args.add("--platform", ctx.attr.platform) args.add("--out", outfile) args.add("--name_file", name_file) From 3aa221f82edec3ea2c7b80462e6e609b7aa1276a Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Wed, 8 Mar 2023 16:50:55 -0800 Subject: [PATCH 192/234] feat: add bzl_library for proto.bzl (#1116) This is mostly so Google internal tooling can find the complete deps, but also as a best practice for consumption by other rules and tools. --- python/BUILD.bazel | 11 +++++++++++ python/private/proto/BUILD | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/python/BUILD.bazel b/python/BUILD.bazel index e5be3e8a53..d30f0db24a 100644 --- a/python/BUILD.bazel +++ b/python/BUILD.bazel @@ -53,6 +53,17 @@ bzl_library( ], ) +bzl_library( + name = "proto_bzl", + srcs = [ + "proto.bzl", + ], + visibility = ["//visibility:public"], + deps = [ + "//python/private/proto:py_proto_library_bzl", + ], +) + # Filegroup of bzl files that can be used by downstream rules for documentation generation filegroup( name = "bzl", diff --git a/python/private/proto/BUILD b/python/private/proto/BUILD index 8483d19c2f..139696cde2 100644 --- a/python/private/proto/BUILD +++ b/python/private/proto/BUILD @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") load("@rules_proto//proto:defs.bzl", "proto_lang_toolchain") package(default_visibility = ["//visibility:public"]) @@ -24,6 +25,16 @@ filegroup( visibility = ["//python/private:__pkg__"], ) +bzl_library( + name = "py_proto_library_bzl", + srcs = ["py_proto_library.bzl"], + visibility = ["//python:__pkg__"], + deps = [ + "//python:defs_bzl", + "@rules_proto//proto:defs", + ], +) + proto_lang_toolchain( name = "python_toolchain", command_line = "--python_out=%s", From 25e4175abc994d8942a41d5ac60a0603dc033f3c Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Thu, 9 Mar 2023 13:06:23 -0800 Subject: [PATCH 193/234] cleanup: Remove license comment in proto build file (#1118) The license comments aren't necessary anymore. --- python/private/proto/BUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/private/proto/BUILD b/python/private/proto/BUILD index 139696cde2..971b354e34 100644 --- a/python/private/proto/BUILD +++ b/python/private/proto/BUILD @@ -17,7 +17,7 @@ load("@rules_proto//proto:defs.bzl", "proto_lang_toolchain") package(default_visibility = ["//visibility:public"]) -licenses(["notice"]) # Apache 2.0 +licenses(["notice"]) filegroup( name = "distribution", From 9ef11b9fabea5fb2d2068141eaa7513486965f75 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Thu, 9 Mar 2023 13:06:43 -0800 Subject: [PATCH 194/234] fix: restrict proto package visibility to private (#1117) This is to prevent accidentally leaking targets that shouldn't be accessible. The `:python_toolchain` target is public because it's an implicit dependency of `py_proto_library`. --- python/private/proto/BUILD | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python/private/proto/BUILD b/python/private/proto/BUILD index 971b354e34..65c09444f7 100644 --- a/python/private/proto/BUILD +++ b/python/private/proto/BUILD @@ -15,7 +15,7 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library") load("@rules_proto//proto:defs.bzl", "proto_lang_toolchain") -package(default_visibility = ["//visibility:public"]) +package(default_visibility = ["//visibility:private"]) licenses(["notice"]) @@ -40,4 +40,7 @@ proto_lang_toolchain( command_line = "--python_out=%s", progress_message = "Generating Python proto_library %{label}", runtime = "@com_google_protobuf//:protobuf_python", + # NOTE: This isn't *actually* public. It's an implicit dependency of py_proto_library, + # so must be public so user usages of the rule can reference it. + visibility = ["//visibility:public"], ) From 31d0efd69e27c93d57f8b2b5664867e1e21828c6 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Thu, 9 Mar 2023 13:40:32 -0800 Subject: [PATCH 195/234] cleanup: rename proto BUILD -> BUILD.bazel (#1119) The rest of the project uses BUILD.bazel --- python/private/proto/{BUILD => BUILD.bazel} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename python/private/proto/{BUILD => BUILD.bazel} (100%) diff --git a/python/private/proto/BUILD b/python/private/proto/BUILD.bazel similarity index 100% rename from python/private/proto/BUILD rename to python/private/proto/BUILD.bazel From 756264aa526eba8eeb4badfa8109050a1f6e0966 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Thu, 9 Mar 2023 14:38:05 -0800 Subject: [PATCH 196/234] feat: bzl file per rule/provider (#1122) This is basically a performance optimization. Bazel can only see that a bzl file changed, not the particular contents. This means that any downstream bzl file loading it is invalidated, even if it doesn't load any of the affected code. As an example, if a package only loads `py_library.bzl`, then changing `py_test.bzl` doesn't need to invalidate all libraries. * Also removes some more extraneous license comments Work towards #1069 --- docs/BUILD.bazel | 6 ++- python/BUILD.bazel | 64 +++++++++++++++++++++- python/current_py_toolchain.bzl | 58 ++++++++++++++++++++ python/defs.bzl | 95 ++------------------------------- python/private/BUILD.bazel | 5 +- python/py_binary.bzl | 19 +++++++ python/py_import.bzl | 67 +++++++++++++++++++++++ python/py_info.bzl | 19 +++++++ python/py_library.bzl | 19 +++++++ python/py_runtime.bzl | 19 +++++++ python/py_runtime_info.bzl | 19 +++++++ python/py_runtime_pair.bzl | 19 +++++++ python/py_test.bzl | 19 +++++++ tests/BUILD.bazel | 21 +++++++- 14 files changed, 353 insertions(+), 96 deletions(-) create mode 100644 python/current_py_toolchain.bzl create mode 100644 python/py_binary.bzl create mode 100644 python/py_import.bzl create mode 100644 python/py_info.bzl create mode 100644 python/py_library.bzl create mode 100644 python/py_runtime.bzl create mode 100644 python/py_runtime_info.bzl create mode 100644 python/py_runtime_pair.bzl create mode 100644 python/py_test.bzl diff --git a/docs/BUILD.bazel b/docs/BUILD.bazel index d2f0b04b56..e1163d9d0e 100644 --- a/docs/BUILD.bazel +++ b/docs/BUILD.bazel @@ -56,7 +56,11 @@ bzl_library( "//python:defs.bzl", "//python/private:reexports.bzl", ], - deps = [":bazel_python_tools"], + deps = [ + ":bazel_python_tools", + "//python:defs_bzl", + "//python/private:reexports_bzl", + ], ) bzl_library( diff --git a/python/BUILD.bazel b/python/BUILD.bazel index d30f0db24a..4d75b781ba 100644 --- a/python/BUILD.bazel +++ b/python/BUILD.bazel @@ -24,11 +24,11 @@ that @rules_python//python is only concerned with the core rules. """ load("@bazel_skylib//:bzl_library.bzl", "bzl_library") -load(":defs.bzl", "current_py_toolchain") +load(":current_py_toolchain.bzl", "current_py_toolchain") package(default_visibility = ["//visibility:public"]) -licenses(["notice"]) # Apache 2.0 +licenses(["notice"]) filegroup( name = "distribution", @@ -41,6 +41,13 @@ filegroup( visibility = ["//:__pkg__"], ) +# ========= bzl_library targets end ========= + +bzl_library( + name = "current_py_toolchain_bzl", + srcs = ["current_py_toolchain.bzl"], +) + bzl_library( name = "defs_bzl", srcs = [ @@ -48,6 +55,8 @@ bzl_library( ], visibility = ["//visibility:public"], deps = [ + ":current_py_toolchain_bzl", + ":py_import_bzl", "//python/private:bazel_tools_bzl", "//python/private:reexports_bzl", ], @@ -64,6 +73,57 @@ bzl_library( ], ) +bzl_library( + name = "py_binary_bzl", + srcs = ["py_binary.bzl"], + deps = ["//python/private:reexports_bzl"], +) + +bzl_library( + name = "py_import_bzl", + srcs = ["py_import.bzl"], + deps = [":py_info_bzl"], +) + +bzl_library( + name = "py_info_bzl", + srcs = ["py_info.bzl"], + deps = ["//python/private:reexports_bzl"], +) + +bzl_library( + name = "py_library_bzl", + srcs = ["py_library.bzl"], + deps = ["//python/private:reexports_bzl"], +) + +bzl_library( + name = "py_runtime_bzl", + srcs = ["py_runtime.bzl"], + deps = ["//python/private:reexports_bzl"], +) + +bzl_library( + name = "py_runtime_pair_bzl", + srcs = ["py_runtime_pair.bzl"], + deps = ["//python/private:reexports_bzl"], +) + +bzl_library( + name = "py_runtime_info_bzl", + srcs = ["py_runtime_info.bzl"], + deps = ["//python/private:reexports_bzl"], +) + +bzl_library( + name = "py_test_bzl", + srcs = ["py_test.bzl"], + deps = ["//python/private:reexports_bzl"], +) + +# NOTE: Remember to add bzl_library targets to //tests:bzl_libraries +# ========= bzl_library targets end ========= + # Filegroup of bzl files that can be used by downstream rules for documentation generation filegroup( name = "bzl", diff --git a/python/current_py_toolchain.bzl b/python/current_py_toolchain.bzl new file mode 100644 index 0000000000..e3345cb646 --- /dev/null +++ b/python/current_py_toolchain.bzl @@ -0,0 +1,58 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Public entry point for current_py_toolchain rule.""" + +def _current_py_toolchain_impl(ctx): + toolchain = ctx.toolchains[ctx.attr._toolchain] + + direct = [] + transitive = [] + vars = {} + + if toolchain.py3_runtime and toolchain.py3_runtime.interpreter: + direct.append(toolchain.py3_runtime.interpreter) + transitive.append(toolchain.py3_runtime.files) + vars["PYTHON3"] = toolchain.py3_runtime.interpreter.path + + if toolchain.py2_runtime and toolchain.py2_runtime.interpreter: + direct.append(toolchain.py2_runtime.interpreter) + transitive.append(toolchain.py2_runtime.files) + vars["PYTHON2"] = toolchain.py2_runtime.interpreter.path + + files = depset(direct, transitive = transitive) + return [ + toolchain, + platform_common.TemplateVariableInfo(vars), + DefaultInfo( + runfiles = ctx.runfiles(transitive_files = files), + files = files, + ), + ] + +current_py_toolchain = rule( + doc = """ + This rule exists so that the current python toolchain can be used in the `toolchains` attribute of + other rules, such as genrule. It allows exposing a python toolchain after toolchain resolution has + happened, to a rule which expects a concrete implementation of a toolchain, rather than a + toolchain_type which could be resolved to that toolchain. + """, + implementation = _current_py_toolchain_impl, + attrs = { + "_toolchain": attr.string(default = str(Label("@bazel_tools//tools/python:toolchain_type"))), + }, + toolchains = [ + str(Label("@bazel_tools//tools/python:toolchain_type")), + ], +) diff --git a/python/defs.bzl b/python/defs.bzl index 7b60c6513b..e106166f03 100644 --- a/python/defs.bzl +++ b/python/defs.bzl @@ -27,6 +27,8 @@ load( _py_runtime_pair = "py_runtime_pair", _py_test = "py_test", ) +load(":current_py_toolchain.bzl", _current_py_toolchain = "current_py_toolchain") +load(":py_import.bzl", _py_import = "py_import") # Exports of native-defined providers. @@ -34,98 +36,9 @@ PyInfo = internal_PyInfo PyRuntimeInfo = internal_PyRuntimeInfo -def _current_py_toolchain_impl(ctx): - toolchain = ctx.toolchains[ctx.attr._toolchain] +current_py_toolchain = _current_py_toolchain - direct = [] - transitive = [] - vars = {} - - if toolchain.py3_runtime and toolchain.py3_runtime.interpreter: - direct.append(toolchain.py3_runtime.interpreter) - transitive.append(toolchain.py3_runtime.files) - vars["PYTHON3"] = toolchain.py3_runtime.interpreter.path - - if toolchain.py2_runtime and toolchain.py2_runtime.interpreter: - direct.append(toolchain.py2_runtime.interpreter) - transitive.append(toolchain.py2_runtime.files) - vars["PYTHON2"] = toolchain.py2_runtime.interpreter.path - - files = depset(direct, transitive = transitive) - return [ - toolchain, - platform_common.TemplateVariableInfo(vars), - DefaultInfo( - runfiles = ctx.runfiles(transitive_files = files), - files = files, - ), - ] - -current_py_toolchain = rule( - doc = """ - This rule exists so that the current python toolchain can be used in the `toolchains` attribute of - other rules, such as genrule. It allows exposing a python toolchain after toolchain resolution has - happened, to a rule which expects a concrete implementation of a toolchain, rather than a - toolchain_type which could be resolved to that toolchain. - """, - implementation = _current_py_toolchain_impl, - attrs = { - "_toolchain": attr.string(default = str(Label("@bazel_tools//tools/python:toolchain_type"))), - }, - toolchains = [ - str(Label("@bazel_tools//tools/python:toolchain_type")), - ], -) - -def _py_import_impl(ctx): - # See https://github.com/bazelbuild/bazel/blob/0.24.0/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonSemantics.java#L104 . - import_paths = [ - "/".join([ctx.workspace_name, x.short_path]) - for x in ctx.files.srcs - ] - - return [ - DefaultInfo( - default_runfiles = ctx.runfiles(ctx.files.srcs, collect_default = True), - ), - PyInfo( - transitive_sources = depset(transitive = [ - dep[PyInfo].transitive_sources - for dep in ctx.attr.deps - ]), - imports = depset(direct = import_paths, transitive = [ - dep[PyInfo].imports - for dep in ctx.attr.deps - ]), - ), - ] - -py_import = rule( - doc = """This rule allows the use of Python packages as dependencies. - - It imports the given `.egg` file(s), which might be checked in source files, - fetched externally as with `http_file`, or produced as outputs of other rules. - - It may be used like a `py_library`, in the `deps` of other Python rules. - - This is similar to [java_import](https://docs.bazel.build/versions/master/be/java.html#java_import). - """, - implementation = _py_import_impl, - attrs = { - "deps": attr.label_list( - doc = "The list of other libraries to be linked in to the " + - "binary target.", - providers = [PyInfo], - ), - "srcs": attr.label_list( - doc = "The list of Python package files provided to Python targets " + - "that depend on this target. Note that currently only the .egg " + - "format is accepted. For .whl files, try the whl_library rule. " + - "We accept contributions to extend py_import to handle .whl.", - allow_files = [".egg"], - ), - }, -) +py_import = _py_import # Re-exports of Starlark-defined symbols in @bazel_tools//tools/python. diff --git a/python/private/BUILD.bazel b/python/private/BUILD.bazel index f3278478b8..21e3c1623f 100644 --- a/python/private/BUILD.bazel +++ b/python/private/BUILD.bazel @@ -34,7 +34,10 @@ filegroup( bzl_library( name = "reexports_bzl", srcs = ["reexports.bzl"], - visibility = ["//python:__pkg__"], + visibility = [ + "//docs:__pkg__", + "//python:__pkg__", + ], deps = [":bazel_tools_bzl"], ) diff --git a/python/py_binary.bzl b/python/py_binary.bzl new file mode 100644 index 0000000000..9d145d8fa6 --- /dev/null +++ b/python/py_binary.bzl @@ -0,0 +1,19 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Public entry point for py_binary.""" + +load("//python/private:reexports.bzl", _py_binary = "py_binary") + +py_binary = _py_binary diff --git a/python/py_import.bzl b/python/py_import.bzl new file mode 100644 index 0000000000..c9284121d6 --- /dev/null +++ b/python/py_import.bzl @@ -0,0 +1,67 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Public entry point for py_import rule.""" + +load(":py_info.bzl", "PyInfo") + +def _py_import_impl(ctx): + # See https://github.com/bazelbuild/bazel/blob/0.24.0/src/main/java/com/google/devtools/build/lib/bazel/rules/python/BazelPythonSemantics.java#L104 . + import_paths = [ + "/".join([ctx.workspace_name, x.short_path]) + for x in ctx.files.srcs + ] + + return [ + DefaultInfo( + default_runfiles = ctx.runfiles(ctx.files.srcs, collect_default = True), + ), + PyInfo( + transitive_sources = depset(transitive = [ + dep[PyInfo].transitive_sources + for dep in ctx.attr.deps + ]), + imports = depset(direct = import_paths, transitive = [ + dep[PyInfo].imports + for dep in ctx.attr.deps + ]), + ), + ] + +py_import = rule( + doc = """This rule allows the use of Python packages as dependencies. + + It imports the given `.egg` file(s), which might be checked in source files, + fetched externally as with `http_file`, or produced as outputs of other rules. + + It may be used like a `py_library`, in the `deps` of other Python rules. + + This is similar to [java_import](https://docs.bazel.build/versions/master/be/java.html#java_import). + """, + implementation = _py_import_impl, + attrs = { + "deps": attr.label_list( + doc = "The list of other libraries to be linked in to the " + + "binary target.", + providers = [PyInfo], + ), + "srcs": attr.label_list( + doc = "The list of Python package files provided to Python targets " + + "that depend on this target. Note that currently only the .egg " + + "format is accepted. For .whl files, try the whl_library rule. " + + "We accept contributions to extend py_import to handle .whl.", + allow_files = [".egg"], + ), + }, +) diff --git a/python/py_info.bzl b/python/py_info.bzl new file mode 100644 index 0000000000..2c3997dee2 --- /dev/null +++ b/python/py_info.bzl @@ -0,0 +1,19 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Public entry point for PyInfo.""" + +load("//python/private:reexports.bzl", "internal_PyInfo") + +PyInfo = internal_PyInfo diff --git a/python/py_library.bzl b/python/py_library.bzl new file mode 100644 index 0000000000..1aff68c100 --- /dev/null +++ b/python/py_library.bzl @@ -0,0 +1,19 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Public entry point for py_library.""" + +load("//python/private:reexports.bzl", _py_library = "py_library") + +py_library = _py_library diff --git a/python/py_runtime.bzl b/python/py_runtime.bzl new file mode 100644 index 0000000000..5e80308176 --- /dev/null +++ b/python/py_runtime.bzl @@ -0,0 +1,19 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Public entry point for py_runtime.""" + +load("//python/private:reexports.bzl", _py_runtime = "py_runtime") + +py_runtime = _py_runtime diff --git a/python/py_runtime_info.bzl b/python/py_runtime_info.bzl new file mode 100644 index 0000000000..15598ee903 --- /dev/null +++ b/python/py_runtime_info.bzl @@ -0,0 +1,19 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Public entry point for PyRuntimeInfo.""" + +load("//python/private:reexports.bzl", "internal_PyRuntimeInfo") + +PyRuntimeInfo = internal_PyRuntimeInfo diff --git a/python/py_runtime_pair.bzl b/python/py_runtime_pair.bzl new file mode 100644 index 0000000000..3f3ecf443b --- /dev/null +++ b/python/py_runtime_pair.bzl @@ -0,0 +1,19 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Public entry point for py_runtime_pair.""" + +load("//python/private:reexports.bzl", _py_runtime_pair = "py_runtime_pair") + +py_runtime_pair = _py_runtime_pair diff --git a/python/py_test.bzl b/python/py_test.bzl new file mode 100644 index 0000000000..84470bc3af --- /dev/null +++ b/python/py_test.bzl @@ -0,0 +1,19 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Public entry point for py_test.""" + +load("//python/private:reexports.bzl", _py_test = "py_test") + +py_test = _py_test diff --git a/tests/BUILD.bazel b/tests/BUILD.bazel index ee9c5550e8..f5133c4e65 100644 --- a/tests/BUILD.bazel +++ b/tests/BUILD.bazel @@ -1,8 +1,9 @@ +load("@bazel_skylib//rules:build_test.bzl", "build_test") load("//tools/bazel_integration_test:bazel_integration_test.bzl", "bazel_integration_test") package(default_visibility = ["//visibility:public"]) -licenses(["notice"]) # Apache 2.0 +licenses(["notice"]) bazel_integration_test( name = "pip_repository_entry_points_example", @@ -10,3 +11,21 @@ bazel_integration_test( # The dependencies needed for this test are not cross-platform: https://github.com/bazelbuild/rules_python/issues/260 tags = ["fix-windows"], ) + +build_test( + name = "bzl_libaries_build_test", + targets = [ + # keep sorted + "//python:current_py_toolchain_bzl", + "//python:defs_bzl", + "//python:proto_bzl", + "//python:py_binary_bzl", + "//python:py_import_bzl", + "//python:py_info_bzl", + "//python:py_library_bzl", + "//python:py_runtime_bzl", + "//python:py_runtime_info_bzl", + "//python:py_runtime_pair_bzl", + "//python:py_test_bzl", + ], +) From c0c08a33a1c5d63cb4454fe430ade3a4eb7f04df Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Fri, 10 Mar 2023 16:21:24 -0800 Subject: [PATCH 197/234] cleanup: fix typo: libraries, not libaries (#1127) Silent r's are tricky. --- tests/BUILD.bazel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/BUILD.bazel b/tests/BUILD.bazel index f5133c4e65..a196d2af7f 100644 --- a/tests/BUILD.bazel +++ b/tests/BUILD.bazel @@ -13,7 +13,7 @@ bazel_integration_test( ) build_test( - name = "bzl_libaries_build_test", + name = "bzl_libraries_build_test", targets = [ # keep sorted "//python:current_py_toolchain_bzl", From 4e3d01c9f6a6cda0fb34b7c2961d6b1ef5313218 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Fri, 10 Mar 2023 18:13:12 -0800 Subject: [PATCH 198/234] feat: add public entry point for PyCcLinkParamsInfo (#1128) This provides a public entry point for loading the underlying `PyCcLinkParamsProvider` provider that is built into Bazel. This provider isn't yet usable from Bazel, but adding a loadable way for it to migrate off the built-in rules is the first step. Work towards #1069 --- python/BUILD.bazel | 5 +++++ python/py_cc_link_params_info.bzl | 3 +++ tests/BUILD.bazel | 1 + 3 files changed, 9 insertions(+) create mode 100644 python/py_cc_link_params_info.bzl diff --git a/python/BUILD.bazel b/python/BUILD.bazel index 4d75b781ba..a524d2ff94 100644 --- a/python/BUILD.bazel +++ b/python/BUILD.bazel @@ -79,6 +79,11 @@ bzl_library( deps = ["//python/private:reexports_bzl"], ) +bzl_library( + name = "py_cc_link_params_info_bzl", + srcs = ["py_cc_link_params_info.bzl"], +) + bzl_library( name = "py_import_bzl", srcs = ["py_import.bzl"], diff --git a/python/py_cc_link_params_info.bzl b/python/py_cc_link_params_info.bzl new file mode 100644 index 0000000000..0ebd64b208 --- /dev/null +++ b/python/py_cc_link_params_info.bzl @@ -0,0 +1,3 @@ +"""Public entry point for PyCcLinkParamsInfo.""" + +PyCcLinkParamsInfo = PyCcLinkParamsProvider diff --git a/tests/BUILD.bazel b/tests/BUILD.bazel index a196d2af7f..abbe62ddff 100644 --- a/tests/BUILD.bazel +++ b/tests/BUILD.bazel @@ -20,6 +20,7 @@ build_test( "//python:defs_bzl", "//python:proto_bzl", "//python:py_binary_bzl", + "//python:py_cc_link_params_info_bzl", "//python:py_import_bzl", "//python:py_info_bzl", "//python:py_library_bzl", From 31bc04bf93d555f8a9842c0ba2d3d243c4ac6cd4 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Mon, 13 Mar 2023 13:29:30 -0700 Subject: [PATCH 199/234] cleanup: reformat defs.bzl doc string. (#1126) The extraneous newlines were bothering me. --- docs/python.md | 2 -- python/defs.bzl | 5 +---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/docs/python.md b/docs/python.md index 6682e48bd1..e42375ad60 100755 --- a/docs/python.md +++ b/docs/python.md @@ -1,9 +1,7 @@ - Core rules for building Python projects. - ## current_py_toolchain diff --git a/python/defs.bzl b/python/defs.bzl index e106166f03..ec70c1bf86 100644 --- a/python/defs.bzl +++ b/python/defs.bzl @@ -11,10 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. - -""" -Core rules for building Python projects. -""" +"""Core rules for building Python projects.""" load("@bazel_tools//tools/python:srcs_version.bzl", _find_requirements = "find_requirements") load( From c394c46fc1b21853bc68a7a47c1fe2db828d1dd0 Mon Sep 17 00:00:00 2001 From: John Laxson Date: Thu, 16 Mar 2023 12:34:27 -0700 Subject: [PATCH 200/234] fix: Include filename when parsing imports for gazelle (#1133) --- gazelle/python/parse.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gazelle/python/parse.py b/gazelle/python/parse.py index 5cf0b89868..6c0ef69598 100644 --- a/gazelle/python/parse.py +++ b/gazelle/python/parse.py @@ -27,7 +27,7 @@ def parse_import_statements(content, filepath): modules = list() - tree = ast.parse(content) + tree = ast.parse(content, filename=filepath) for node in ast.walk(tree): if isinstance(node, ast.Import): for subnode in node.names: From 3b9c85e7a466f5f904929ecfcfb11f0c444fef16 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Thu, 23 Mar 2023 12:59:58 -0700 Subject: [PATCH 201/234] cleanup: factor reexports.bzl into the respective implementation files (#1137) This helps avoid loading one rule requiring loading everything. Within Google, this makes some Starlark testing frameworks avoid having to mock far away dependencies of dependencies. --- python/BUILD.bazel | 18 +++-- python/defs.bzl | 17 ++--- python/private/BUILD.bazel | 6 ++ python/private/reexports.bzl | 136 ----------------------------------- python/private/util.bzl | 12 ++++ python/py_binary.bzl | 16 ++++- python/py_library.bzl | 14 +++- python/py_runtime.bzl | 14 +++- python/py_runtime_pair.bzl | 72 ++++++++++++++++++- python/py_test.bzl | 16 ++++- 10 files changed, 159 insertions(+), 162 deletions(-) diff --git a/python/BUILD.bazel b/python/BUILD.bazel index a524d2ff94..2582d73751 100644 --- a/python/BUILD.bazel +++ b/python/BUILD.bazel @@ -56,9 +56,15 @@ bzl_library( visibility = ["//visibility:public"], deps = [ ":current_py_toolchain_bzl", + ":py_binary_bzl", ":py_import_bzl", + ":py_info_bzl", + ":py_library_bzl", + ":py_runtime_bzl", + ":py_runtime_info_bzl", + ":py_runtime_pair_bzl", + ":py_test_bzl", "//python/private:bazel_tools_bzl", - "//python/private:reexports_bzl", ], ) @@ -76,7 +82,7 @@ bzl_library( bzl_library( name = "py_binary_bzl", srcs = ["py_binary.bzl"], - deps = ["//python/private:reexports_bzl"], + deps = ["//python/private:util_bzl"], ) bzl_library( @@ -99,19 +105,19 @@ bzl_library( bzl_library( name = "py_library_bzl", srcs = ["py_library.bzl"], - deps = ["//python/private:reexports_bzl"], + deps = ["//python/private:util_bzl"], ) bzl_library( name = "py_runtime_bzl", srcs = ["py_runtime.bzl"], - deps = ["//python/private:reexports_bzl"], + deps = ["//python/private:util_bzl"], ) bzl_library( name = "py_runtime_pair_bzl", srcs = ["py_runtime_pair.bzl"], - deps = ["//python/private:reexports_bzl"], + deps = ["//python/private:bazel_tools_bzl"], ) bzl_library( @@ -123,7 +129,7 @@ bzl_library( bzl_library( name = "py_test_bzl", srcs = ["py_test.bzl"], - deps = ["//python/private:reexports_bzl"], + deps = ["//python/private:util_bzl"], ) # NOTE: Remember to add bzl_library targets to //tests:bzl_libraries diff --git a/python/defs.bzl b/python/defs.bzl index ec70c1bf86..6ded66a568 100644 --- a/python/defs.bzl +++ b/python/defs.bzl @@ -14,16 +14,13 @@ """Core rules for building Python projects.""" load("@bazel_tools//tools/python:srcs_version.bzl", _find_requirements = "find_requirements") -load( - "//python/private:reexports.bzl", - "internal_PyInfo", - "internal_PyRuntimeInfo", - _py_binary = "py_binary", - _py_library = "py_library", - _py_runtime = "py_runtime", - _py_runtime_pair = "py_runtime_pair", - _py_test = "py_test", -) +load("//python:py_binary.bzl", _py_binary = "py_binary") +load("//python:py_info.bzl", internal_PyInfo = "PyInfo") +load("//python:py_library.bzl", _py_library = "py_library") +load("//python:py_runtime.bzl", _py_runtime = "py_runtime") +load("//python:py_runtime_info.bzl", internal_PyRuntimeInfo = "PyRuntimeInfo") +load("//python:py_runtime_pair.bzl", _py_runtime_pair = "py_runtime_pair") +load("//python:py_test.bzl", _py_test = "py_test") load(":current_py_toolchain.bzl", _current_py_toolchain = "current_py_toolchain") load(":py_import.bzl", _py_import = "py_import") diff --git a/python/private/BUILD.bazel b/python/private/BUILD.bazel index 21e3c1623f..4068ea480b 100644 --- a/python/private/BUILD.bazel +++ b/python/private/BUILD.bazel @@ -41,6 +41,12 @@ bzl_library( deps = [":bazel_tools_bzl"], ) +bzl_library( + name = "util_bzl", + srcs = ["util.bzl"], + visibility = ["//python:__subpackages__"], +) + # @bazel_tools can't define bzl_library itself, so we just put a wrapper around it. bzl_library( name = "bazel_tools_bzl", diff --git a/python/private/reexports.bzl b/python/private/reexports.bzl index 987187c155..a300a20365 100644 --- a/python/private/reexports.bzl +++ b/python/private/reexports.bzl @@ -37,20 +37,6 @@ different name. Then we can load it from defs.bzl and export it there under the original name. """ -load("@bazel_tools//tools/python:toolchain.bzl", _py_runtime_pair = "py_runtime_pair") - -# The implementation of the macros and tagging mechanism follows the example -# set by rules_cc and rules_java. - -_MIGRATION_TAG = "__PYTHON_RULES_MIGRATION_DO_NOT_USE_WILL_BREAK__" - -def _add_tags(attrs): - if "tags" in attrs and attrs["tags"] != None: - attrs["tags"] = attrs["tags"] + [_MIGRATION_TAG] - else: - attrs["tags"] = [_MIGRATION_TAG] - return attrs - # Don't use underscore prefix, since that would make the symbol local to this # file only. Use a non-conventional name to emphasize that this is not a public # symbol. @@ -59,125 +45,3 @@ internal_PyInfo = PyInfo # buildifier: disable=name-conventions internal_PyRuntimeInfo = PyRuntimeInfo - -def py_library(**attrs): - """See the Bazel core [py_library](https://docs.bazel.build/versions/master/be/python.html#py_library) documentation. - - Args: - **attrs: Rule attributes - """ - if attrs.get("srcs_version") in ("PY2", "PY2ONLY"): - fail("Python 2 is no longer supported: https://github.com/bazelbuild/rules_python/issues/886") - - # buildifier: disable=native-python - native.py_library(**_add_tags(attrs)) - -def py_binary(**attrs): - """See the Bazel core [py_binary](https://docs.bazel.build/versions/master/be/python.html#py_binary) documentation. - - Args: - **attrs: Rule attributes - """ - if attrs.get("python_version") == "PY2": - fail("Python 2 is no longer supported: https://github.com/bazelbuild/rules_python/issues/886") - if attrs.get("srcs_version") in ("PY2", "PY2ONLY"): - fail("Python 2 is no longer supported: https://github.com/bazelbuild/rules_python/issues/886") - - # buildifier: disable=native-python - native.py_binary(**_add_tags(attrs)) - -def py_test(**attrs): - """See the Bazel core [py_test](https://docs.bazel.build/versions/master/be/python.html#py_test) documentation. - - Args: - **attrs: Rule attributes - """ - if attrs.get("python_version") == "PY2": - fail("Python 2 is no longer supported: https://github.com/bazelbuild/rules_python/issues/886") - if attrs.get("srcs_version") in ("PY2", "PY2ONLY"): - fail("Python 2 is no longer supported: https://github.com/bazelbuild/rules_python/issues/886") - - # buildifier: disable=native-python - native.py_test(**_add_tags(attrs)) - -def py_runtime(**attrs): - """See the Bazel core [py_runtime](https://docs.bazel.build/versions/master/be/python.html#py_runtime) documentation. - - Args: - **attrs: Rule attributes - """ - if attrs.get("python_version") == "PY2": - fail("Python 2 is no longer supported: see https://github.com/bazelbuild/rules_python/issues/886") - - # buildifier: disable=native-python - native.py_runtime(**_add_tags(attrs)) - -# NOTE: This doc is copy/pasted from the builtin py_runtime_pair rule so our -# doc generator gives useful API docs. -def py_runtime_pair(name, py2_runtime = None, py3_runtime = None, **attrs): - """A toolchain rule for Python. - - This used to wrap up to two Python runtimes, one for Python 2 and one for Python 3. - However, Python 2 is no longer supported, so it now only wraps a single Python 3 - runtime. - - Usually the wrapped runtimes are declared using the `py_runtime` rule, but any - rule returning a `PyRuntimeInfo` provider may be used. - - This rule returns a `platform_common.ToolchainInfo` provider with the following - schema: - - ```python - platform_common.ToolchainInfo( - py2_runtime = None, - py3_runtime = , - ) - ``` - - Example usage: - - ```python - # In your BUILD file... - - load("@rules_python//python:defs.bzl", "py_runtime_pair") - - py_runtime( - name = "my_py3_runtime", - interpreter_path = "/system/python3", - python_version = "PY3", - ) - - py_runtime_pair( - name = "my_py_runtime_pair", - py3_runtime = ":my_py3_runtime", - ) - - toolchain( - name = "my_toolchain", - target_compatible_with = <...>, - toolchain = ":my_py_runtime_pair", - toolchain_type = "@rules_python//python:toolchain_type", - ) - ``` - - ```python - # In your WORKSPACE... - - register_toolchains("//my_pkg:my_toolchain") - ``` - - Args: - name: str, the name of the target - py2_runtime: optional Label; must be unset or None; an error is raised - otherwise. - py3_runtime: Label; a target with `PyRuntimeInfo` for Python 3. - **attrs: Extra attrs passed onto the native rule - """ - if attrs.get("py2_runtime"): - fail("PYthon 2 is no longer supported: see https://github.com/bazelbuild/rules_python/issues/886") - _py_runtime_pair( - name = name, - py2_runtime = py2_runtime, - py3_runtime = py3_runtime, - **attrs - ) diff --git a/python/private/util.bzl b/python/private/util.bzl index 8ea1f493f5..25a50aac6a 100644 --- a/python/private/util.bzl +++ b/python/private/util.bzl @@ -29,3 +29,15 @@ def copy_propagating_kwargs(from_kwargs, into_kwargs = None): if attr in from_kwargs and attr not in into_kwargs: into_kwargs[attr] = from_kwargs[attr] return into_kwargs + +# The implementation of the macros and tagging mechanism follows the example +# set by rules_cc and rules_java. + +_MIGRATION_TAG = "__PYTHON_RULES_MIGRATION_DO_NOT_USE_WILL_BREAK__" + +def add_migration_tag(attrs): + if "tags" in attrs and attrs["tags"] != None: + attrs["tags"] = attrs["tags"] + [_MIGRATION_TAG] + else: + attrs["tags"] = [_MIGRATION_TAG] + return attrs diff --git a/python/py_binary.bzl b/python/py_binary.bzl index 9d145d8fa6..6b6f7e0f8a 100644 --- a/python/py_binary.bzl +++ b/python/py_binary.bzl @@ -14,6 +14,18 @@ """Public entry point for py_binary.""" -load("//python/private:reexports.bzl", _py_binary = "py_binary") +load("//python/private:util.bzl", "add_migration_tag") -py_binary = _py_binary +def py_binary(**attrs): + """See the Bazel core [py_binary](https://docs.bazel.build/versions/master/be/python.html#py_binary) documentation. + + Args: + **attrs: Rule attributes + """ + if attrs.get("python_version") == "PY2": + fail("Python 2 is no longer supported: https://github.com/bazelbuild/rules_python/issues/886") + if attrs.get("srcs_version") in ("PY2", "PY2ONLY"): + fail("Python 2 is no longer supported: https://github.com/bazelbuild/rules_python/issues/886") + + # buildifier: disable=native-python + native.py_binary(**add_migration_tag(attrs)) diff --git a/python/py_library.bzl b/python/py_library.bzl index 1aff68c100..d54cbb2958 100644 --- a/python/py_library.bzl +++ b/python/py_library.bzl @@ -14,6 +14,16 @@ """Public entry point for py_library.""" -load("//python/private:reexports.bzl", _py_library = "py_library") +load("//python/private:util.bzl", "add_migration_tag") -py_library = _py_library +def py_library(**attrs): + """See the Bazel core [py_library](https://docs.bazel.build/versions/master/be/python.html#py_library) documentation. + + Args: + **attrs: Rule attributes + """ + if attrs.get("srcs_version") in ("PY2", "PY2ONLY"): + fail("Python 2 is no longer supported: https://github.com/bazelbuild/rules_python/issues/886") + + # buildifier: disable=native-python + native.py_library(**add_migration_tag(attrs)) diff --git a/python/py_runtime.bzl b/python/py_runtime.bzl index 5e80308176..b70f9d4ec4 100644 --- a/python/py_runtime.bzl +++ b/python/py_runtime.bzl @@ -14,6 +14,16 @@ """Public entry point for py_runtime.""" -load("//python/private:reexports.bzl", _py_runtime = "py_runtime") +load("//python/private:util.bzl", "add_migration_tag") -py_runtime = _py_runtime +def py_runtime(**attrs): + """See the Bazel core [py_runtime](https://docs.bazel.build/versions/master/be/python.html#py_runtime) documentation. + + Args: + **attrs: Rule attributes + """ + if attrs.get("python_version") == "PY2": + fail("Python 2 is no longer supported: see https://github.com/bazelbuild/rules_python/issues/886") + + # buildifier: disable=native-python + native.py_runtime(**add_migration_tag(attrs)) diff --git a/python/py_runtime_pair.bzl b/python/py_runtime_pair.bzl index 3f3ecf443b..951c606f4a 100644 --- a/python/py_runtime_pair.bzl +++ b/python/py_runtime_pair.bzl @@ -14,6 +14,74 @@ """Public entry point for py_runtime_pair.""" -load("//python/private:reexports.bzl", _py_runtime_pair = "py_runtime_pair") +load("@bazel_tools//tools/python:toolchain.bzl", _py_runtime_pair = "py_runtime_pair") -py_runtime_pair = _py_runtime_pair +# NOTE: This doc is copy/pasted from the builtin py_runtime_pair rule so our +# doc generator gives useful API docs. +def py_runtime_pair(name, py2_runtime = None, py3_runtime = None, **attrs): + """A toolchain rule for Python. + + This used to wrap up to two Python runtimes, one for Python 2 and one for Python 3. + However, Python 2 is no longer supported, so it now only wraps a single Python 3 + runtime. + + Usually the wrapped runtimes are declared using the `py_runtime` rule, but any + rule returning a `PyRuntimeInfo` provider may be used. + + This rule returns a `platform_common.ToolchainInfo` provider with the following + schema: + + ```python + platform_common.ToolchainInfo( + py2_runtime = None, + py3_runtime = , + ) + ``` + + Example usage: + + ```python + # In your BUILD file... + + load("@rules_python//python:defs.bzl", "py_runtime_pair") + + py_runtime( + name = "my_py3_runtime", + interpreter_path = "/system/python3", + python_version = "PY3", + ) + + py_runtime_pair( + name = "my_py_runtime_pair", + py3_runtime = ":my_py3_runtime", + ) + + toolchain( + name = "my_toolchain", + target_compatible_with = <...>, + toolchain = ":my_py_runtime_pair", + toolchain_type = "@rules_python//python:toolchain_type", + ) + ``` + + ```python + # In your WORKSPACE... + + register_toolchains("//my_pkg:my_toolchain") + ``` + + Args: + name: str, the name of the target + py2_runtime: optional Label; must be unset or None; an error is raised + otherwise. + py3_runtime: Label; a target with `PyRuntimeInfo` for Python 3. + **attrs: Extra attrs passed onto the native rule + """ + if attrs.get("py2_runtime"): + fail("PYthon 2 is no longer supported: see https://github.com/bazelbuild/rules_python/issues/886") + _py_runtime_pair( + name = name, + py2_runtime = py2_runtime, + py3_runtime = py3_runtime, + **attrs + ) diff --git a/python/py_test.bzl b/python/py_test.bzl index 84470bc3af..09580c01c4 100644 --- a/python/py_test.bzl +++ b/python/py_test.bzl @@ -14,6 +14,18 @@ """Public entry point for py_test.""" -load("//python/private:reexports.bzl", _py_test = "py_test") +load("//python/private:util.bzl", "add_migration_tag") -py_test = _py_test +def py_test(**attrs): + """See the Bazel core [py_test](https://docs.bazel.build/versions/master/be/python.html#py_test) documentation. + + Args: + **attrs: Rule attributes + """ + if attrs.get("python_version") == "PY2": + fail("Python 2 is no longer supported: https://github.com/bazelbuild/rules_python/issues/886") + if attrs.get("srcs_version") in ("PY2", "PY2ONLY"): + fail("Python 2 is no longer supported: https://github.com/bazelbuild/rules_python/issues/886") + + # buildifier: disable=native-python + native.py_test(**add_migration_tag(attrs)) From 260a08b9f4d0572f154f04d9a2add967fc24ecc1 Mon Sep 17 00:00:00 2001 From: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> Date: Thu, 23 Mar 2023 15:34:00 -0700 Subject: [PATCH 202/234] fix: bump installer to handle windows better (#1138) Fixes https://github.com/bazelbuild/rules_python/issues/1121. Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com> --- python/pip_install/repositories.bzl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/pip_install/repositories.bzl b/python/pip_install/repositories.bzl index 664556da12..2dd4a3724b 100644 --- a/python/pip_install/repositories.bzl +++ b/python/pip_install/repositories.bzl @@ -37,8 +37,8 @@ _RULE_DEPS = [ ), ( "pypi__installer", - "https://files.pythonhosted.org/packages/bf/42/fe5f10fd0d58d5d8231a0bc39e664de09992f960597e9fbd3753f84423a3/installer-0.6.0-py3-none-any.whl", - "ae7c62d1d6158b5c096419102ad0d01fdccebf857e784cee57f94165635fe038", + "https://files.pythonhosted.org/packages/e5/ca/1172b6638d52f2d6caa2dd262ec4c811ba59eee96d54a7701930726bce18/installer-0.7.0-py3-none-any.whl", + "05d1933f0a5ba7d8d6296bb6d5018e7c94fa473ceb10cf198a92ccea19c27b53", ), ( "pypi__packaging", From 64684ae0498576ad2a09fa528fed07afa5e7307d Mon Sep 17 00:00:00 2001 From: Chris Love <335402+chrislovecnm@users.noreply.github.com> Date: Mon, 3 Apr 2023 11:42:53 -0600 Subject: [PATCH 203/234] build: Fixing buildifier (#1148) We have some changes with buildifier 6.1.0, and this commit fixes two files to allow ci to pass. --- python/BUILD.bazel | 2 +- python/pip_install/BUILD.bazel | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/BUILD.bazel b/python/BUILD.bazel index 2582d73751..d75889d188 100644 --- a/python/BUILD.bazel +++ b/python/BUILD.bazel @@ -33,8 +33,8 @@ licenses(["notice"]) filegroup( name = "distribution", srcs = glob(["**"]) + [ - "//python/constraints:distribution", "//python/config_settings:distribution", + "//python/constraints:distribution", "//python/private:distribution", "//python/runfiles:distribution", ], diff --git a/python/pip_install/BUILD.bazel b/python/pip_install/BUILD.bazel index 281ccba6a9..e8e8633137 100644 --- a/python/pip_install/BUILD.bazel +++ b/python/pip_install/BUILD.bazel @@ -2,10 +2,10 @@ filegroup( name = "distribution", srcs = glob(["*.bzl"]) + [ "BUILD.bazel", + "//python/pip_install/private:distribution", "//python/pip_install/tools/dependency_resolver:distribution", "//python/pip_install/tools/lib:distribution", "//python/pip_install/tools/wheel_installer:distribution", - "//python/pip_install/private:distribution", ], visibility = ["//:__pkg__"], ) From 03ebeb71e80e6d59dc589d1f7a0242cf913d2861 Mon Sep 17 00:00:00 2001 From: Chris Love <335402+chrislovecnm@users.noreply.github.com> Date: Mon, 3 Apr 2023 15:28:07 -0600 Subject: [PATCH 204/234] docs: Updating documentation for bzlmod (#1149) - Updated primary README.md to include documentation for using bzlmod or a WORKSPACE file. - Updated gazelle/README.md to include documentation for only using bzlmod and provided a link to the older docs. - Included other general updates for the gazelle documentation. --- README.md | 64 +++++++++++++++++++++++++++++++-- gazelle/README.md | 91 +++++++++++++++++++++++++++++++++++------------ 2 files changed, 130 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 07acaf8e19..089837de7d 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,47 @@ contribute](CONTRIBUTING.md) page for information on our development workflow. ## Getting started +The next two sections cover using `rules_python` with bzlmod and +the older way of configuring bazel with a `WORKSPACE` file. + +### Using bzlmod + +To import rules_python in your project, you first need to add it to your +`MODULES.bazel` file, using the snippet provided in the +[release you choose](https://github.com/bazelbuild/rules_python/releases). + +#### Toolchain registration with bzlmod + +To register a hermetic Python toolchain rather than rely on a system-installed interpreter for runtime execution, you can add to the `MODULES.bazel` file: + +```python +# Find the latest version number here: https://github.com/bazelbuild/rules_python/releases +# and change the version number if needed in the line below. +bazel_dep(name = "rules_python", version = "0.20.0") + +# You do not have to use pip for the toolchain, but most people +# will use it for the dependency management. +pip = use_extension("@rules_python//python:extensions.bzl", "pip") + +pip.parse( + name = "pip", + requirements_lock = "//:requirements_lock.txt", +) + +use_repo(pip, "pip") + +# Register a specific python toolchain instead of using the host version +python = use_extension("@rules_python//python:extensions.bzl", "python") + +use_repo(python, "python3_10_toolchains") + +register_toolchains( + "@python3_10_toolchains//:all", +) +``` + +### Using a WORKSPACE file + To import rules_python in your project, you first need to add it to your `WORKSPACE` file, using the snippet provided in the [release you choose](https://github.com/bazelbuild/rules_python/releases) @@ -53,7 +94,7 @@ http_archive( ) ``` -### Toolchain registration +#### Toolchain registration To register a hermetic Python toolchain rather than rely on a system-installed interpreter for runtime execution, you can add to the `WORKSPACE` file: @@ -118,6 +159,22 @@ target in the appropriate wheel repo. ### Installing third_party packages +#### Using bzlmod + +To add pip dependencies to your `MODULES.bazel` file, use the `pip.parse` extension, and call it to create the +central external repo and individual wheel external repos. + +```python +pip.parse( + name = "my_deps", + requirements_lock = "//:requirements_lock.txt", +) + +use_repo(pip, "my_deps") +``` + +#### Using a WORKSPACE file + To add pip dependencies to your `WORKSPACE`, load the `pip_parse` function, and call it to create the central external repo and individual wheel external repos. @@ -137,14 +194,15 @@ load("@my_deps//:requirements.bzl", "install_deps") install_deps() ``` +#### pip rules + Note that since `pip_parse` is a repository rule and therefore executes pip at WORKSPACE-evaluation time, Bazel has no information about the Python toolchain and cannot enforce that the interpreter used to invoke pip matches the interpreter used to run `py_binary` targets. By default, `pip_parse` uses the system command `"python3"`. This can be overridden by passing the `python_interpreter` attribute or `python_interpreter_target` attribute to `pip_parse`. -You can have multiple `pip_parse`s in the same workspace. This will create multiple external repos that have no relation to -one another, and may result in downloading the same wheels multiple times. +You can have multiple `pip_parse`s in the same workspace. This will create multiple external repos that have no relation to one another, and may result in downloading the same wheels multiple times. As with any repository rule, if you would like to ensure that `pip_parse` is re-executed in order to pick up a non-hermetic change to your environment (e.g., diff --git a/gazelle/README.md b/gazelle/README.md index 0081701241..e9a8052353 100644 --- a/gazelle/README.md +++ b/gazelle/README.md @@ -1,21 +1,48 @@ # Python Gazelle plugin +[Gazelle](https://github.com/bazelbuild/bazel-gazelle) +is a build file generator for Bazel projects. It can create new BUILD.bazel files for a project that follows language conventions, and it can update existing build files to include new sources, dependencies, and options. + +Gazelle may be run by Bazel using the gazelle rule, or it may be installed and run as a command line tool. + This directory contains a plugin for [Gazelle](https://github.com/bazelbuild/bazel-gazelle) -that generates BUILD file content for Python code. +that generates BUILD files content for Python code. + +The following instructions are for when you use [bzlmod](https://docs.bazel.build/versions/5.0.0/bzlmod.html). +Please refer to older documentation that includes instructions on how to use Gazelle +without using bzlmod as your dependency manager. + +## Example -It requires Go 1.16+ to compile. +We have an example of using Gazelle with Python located [here](https://github.com/bazelbuild/rules_python/tree/main/examples/build_file_generation). -## Installation +## Adding Gazelle to your project -First, you'll need to add Gazelle to your `WORKSPACE` file. -Follow the instructions at https://github.com/bazelbuild/bazel-gazelle#running-gazelle-with-bazel +First, you'll need to add Gazelle to your `MODULES.bazel` file. +Get the current version of Gazelle from there releases here: https://github.com/bazelbuild/bazel-gazelle/releases/. -Next, we need to fetch the third-party Go libraries that the python extension -depends on. -See the installation `WORKSPACE` snippet on the Releases page: -https://github.com/bazelbuild/rules_python/releases +See the installation `MODULE.bazel` snippet on the Releases page: +https://github.com/bazelbuild/rules_python/releases in order to configure rules_python. + +You will also need to add the `bazel_dep` for configuration for `rules_python_gazelle_plugin`. + +Here is a snippet of a `MODULE.bazel` file. + +```starlark +# The following stanza defines the dependency rules_python. +bazel_dep(name = "rules_python", version = "0.20.0") + +# The following stanza defines the dependency rules_python. +# For typical setups you set the version. +bazel_dep(name = "rules_python_gazelle_plugin", version = "0.20.0") + +# The following stanza defines the dependency rules_python. +bazel_dep(name = "gazelle", version = "0.30.0", repo_name = "bazel_gazelle") +``` +You will also need to do the other usual configuration for `rules_python` in your +`MODULE.bazel` file. Next, we'll fetch metadata about your Python dependencies, so that gazelle can determine which package a given import statement comes from. This is provided @@ -157,11 +184,29 @@ Next, all source files are collected into the `srcs` of the `py_library`. Finally, the `import` statements in the source files are parsed, and dependencies are added to the `deps` attribute. -### Tests +### 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. -Python test files are those ending in `_test.py`. +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"], +) +``` -A `py_test` target is added containing all test files as `srcs`. +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 @@ -170,16 +215,18 @@ of a Python program. A `py_binary` target will be created, named `[package]_bin`. -## Developing on the extension +## Developer Notes -Gazelle extensions are written in Go. Ours is a hybrid, which also spawns -a Python interpreter as a subprocess to parse python files. +Gazelle extensions are written in Go. This gazelle plugin is a hybrid, as it uses Go to execute a +Python interpreter as a subprocess to parse Python source files. +See the gazelle documentation https://github.com/bazelbuild/bazel-gazelle/blob/master/extend.md +for more information on extending Gazelle. -The Go dependencies are managed by the go.mod file. -After changing that file, run `go mod tidy` to get a `go.sum` file, -then run `bazel run //:update_go_deps` to convert that to the `gazelle/deps.bzl` file. -The latter is loaded in our `/WORKSPACE` to define the external repos -that we can load Go dependencies from. +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 //:update_go_deps` 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 -go_* rules in the BUILD.bazel files in our repo. +Then after editing Go code, run `bazel run //:gazelle` to generate/update the rules in the +BUILD.bazel files in our repo. From 00dd72dd5f8c2416600ecbcca1f4a9498223fa91 Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius Date: Tue, 4 Apr 2023 09:52:20 +0900 Subject: [PATCH 205/234] fix: use a consistent buildifier version for CI and pre-commit (#1151) The CI may be broken because it is using the latest version of buildifier (`6.1.0`) and the pre-commit hooks are using `6.0.0`. `6.1.0` added extra sorting, so it is now not enough to just run `pre-commit run -a buildifier` to fix the errors. I have submitted a PR to update the pre-commit hooks in https://github.com/keith/pre-commit-buildifier/pull/14 and until it is merged and a new version is tagged we should use an older version of the buildifier to ensure the build is green. --------- Co-authored-by: Richard Levasseur --- .bazelci/presubmit.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index a0d9a19047..f10a6487c3 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -14,8 +14,9 @@ --- buildifier: - version: latest - # keep this argument in sync with .pre-commit-config.yaml + # keep these arguments in sync with .pre-commit-config.yaml + # Use a specific version to avoid skew issues when new versions are released. + version: 6.0.0 warnings: "all" .minimum_supported_version: &minimum_supported_version # For testing minimum supported version. From ee8cecfdc210cda71b0d43a5170f47a741721643 Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius Date: Wed, 5 Apr 2023 00:47:53 +0900 Subject: [PATCH 206/234] chore: bump buildifier to 6.1.0 (#1152) Bump the buildifier to the latest version in pre-commit and CI at the same time. Related to #1148 and #1151. --- .bazelci/presubmit.yml | 2 +- .pre-commit-config.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index f10a6487c3..0e9feab093 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -16,7 +16,7 @@ buildifier: # keep these arguments in sync with .pre-commit-config.yaml # Use a specific version to avoid skew issues when new versions are released. - version: 6.0.0 + version: 6.1.0 warnings: "all" .minimum_supported_version: &minimum_supported_version # For testing minimum supported version. diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9403dd5338..be5f47fc45 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,7 +17,7 @@ # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/keith/pre-commit-buildifier - rev: 6.0.0 + rev: 6.1.0 hooks: - id: buildifier args: &args From 52e14b78307a62aedb69694a222decf48d54a09b Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius Date: Thu, 6 Apr 2023 01:34:11 +0900 Subject: [PATCH 207/234] fix: correct the labels returned by all_requirements lists (#1146) This apparently was not working to begin with, but the CI running the example did not catch it because we did not have an empty `WORKSPACE.bzlmod` file. Tested with the CI and with a clean cache on the local laptop. --- examples/build_file_generation/WORKSPACE.bzlmod | 2 ++ python/pip_install/pip_repository.bzl | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 examples/build_file_generation/WORKSPACE.bzlmod diff --git a/examples/build_file_generation/WORKSPACE.bzlmod b/examples/build_file_generation/WORKSPACE.bzlmod new file mode 100644 index 0000000000..721e065154 --- /dev/null +++ b/examples/build_file_generation/WORKSPACE.bzlmod @@ -0,0 +1,2 @@ +# This file will be used when bzlmod is enabled, keep it empty +# to ensure that all of the setup is done in MODULE.bazel diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl index 733142ba92..fce0dcdd47 100644 --- a/python/pip_install/pip_repository.bzl +++ b/python/pip_install/pip_repository.bzl @@ -370,11 +370,11 @@ def _pip_repository_bzlmod_impl(rctx): rctx.file("BUILD.bazel", build_contents) rctx.template("requirements.bzl", rctx.attr._template, substitutions = { "%%ALL_REQUIREMENTS%%": _format_repr_list([ - "@@{}//{}".format(repo_name, p) if rctx.attr.incompatible_generate_aliases else "@{}_{}//:pkg".format(rctx.attr.name, p) + "@{}//{}".format(repo_name, p) if rctx.attr.incompatible_generate_aliases else "@{}_{}//:pkg".format(rctx.attr.name, p) for p in bzl_packages ]), "%%ALL_WHL_REQUIREMENTS%%": _format_repr_list([ - "@@{}//{}:whl".format(repo_name, p) if rctx.attr.incompatible_generate_aliases else "@{}_{}//:whl".format(rctx.attr.name, p) + "@{}//{}:whl".format(repo_name, p) if rctx.attr.incompatible_generate_aliases else "@{}_{}//:whl".format(rctx.attr.name, p) for p in bzl_packages ]), "%%NAME%%": rctx.attr.name, From 86eadf1ecf89f346476354f42d4d5bc861acab1b Mon Sep 17 00:00:00 2001 From: Alex Martani Date: Fri, 7 Apr 2023 23:05:38 -0700 Subject: [PATCH 208/234] fix: gazelle correctly adds new py_test rules (#1143) Since https://github.com/bazelbuild/rules_python/pull/999, gazelle can generate multiple `py_test` rules in a single package (when it finds multiple `*_test.py` or `test_*.py` files and no `__test__.py` file). In this case, adding new test files to a package with pre-existing `py_test` rules is not handled properly due to the `MatchAny` property on the `py_test` kind - it will match the existing `py_test` rule and edit it instead of adding a new test rule. This PR disables the matching so that new `py_test` rules are properly generated. --- gazelle/python/kinds.go | 2 +- .../python/testdata/multiple_tests/BUILD.in | 12 ++++++++++ .../python/testdata/multiple_tests/BUILD.out | 17 +++++++++++++ .../python/testdata/multiple_tests/README.md | 3 +++ .../python/testdata/multiple_tests/WORKSPACE | 1 + .../testdata/multiple_tests/__init__.py | 0 .../testdata/multiple_tests/bar_test.py | 24 +++++++++++++++++++ .../testdata/multiple_tests/foo_test.py | 24 +++++++++++++++++++ .../python/testdata/multiple_tests/test.yaml | 17 +++++++++++++ 9 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 gazelle/python/testdata/multiple_tests/BUILD.in create mode 100644 gazelle/python/testdata/multiple_tests/BUILD.out create mode 100644 gazelle/python/testdata/multiple_tests/README.md create mode 100644 gazelle/python/testdata/multiple_tests/WORKSPACE create mode 100644 gazelle/python/testdata/multiple_tests/__init__.py create mode 100644 gazelle/python/testdata/multiple_tests/bar_test.py create mode 100644 gazelle/python/testdata/multiple_tests/foo_test.py create mode 100644 gazelle/python/testdata/multiple_tests/test.yaml diff --git a/gazelle/python/kinds.go b/gazelle/python/kinds.go index 0fdc6bc3e9..ab1afb7d55 100644 --- a/gazelle/python/kinds.go +++ b/gazelle/python/kinds.go @@ -65,7 +65,7 @@ var pyKinds = map[string]rule.KindInfo{ }, }, pyTestKind: { - MatchAny: true, + MatchAny: false, NonEmptyAttrs: map[string]bool{ "deps": true, "main": true, diff --git a/gazelle/python/testdata/multiple_tests/BUILD.in b/gazelle/python/testdata/multiple_tests/BUILD.in new file mode 100644 index 0000000000..9e84e5dc32 --- /dev/null +++ b/gazelle/python/testdata/multiple_tests/BUILD.in @@ -0,0 +1,12 @@ +load("@rules_python//python:defs.bzl", "py_library", "py_test") + +py_library( + name = "multiple_tests", + srcs = ["__init__.py"], + visibility = ["//:__subpackages__"], +) + +py_test( + name = "bar_test", + srcs = ["bar_test.py"], +) diff --git a/gazelle/python/testdata/multiple_tests/BUILD.out b/gazelle/python/testdata/multiple_tests/BUILD.out new file mode 100644 index 0000000000..fd67724e3b --- /dev/null +++ b/gazelle/python/testdata/multiple_tests/BUILD.out @@ -0,0 +1,17 @@ +load("@rules_python//python:defs.bzl", "py_library", "py_test") + +py_library( + name = "multiple_tests", + srcs = ["__init__.py"], + visibility = ["//:__subpackages__"], +) + +py_test( + name = "bar_test", + srcs = ["bar_test.py"], +) + +py_test( + name = "foo_test", + srcs = ["foo_test.py"], +) diff --git a/gazelle/python/testdata/multiple_tests/README.md b/gazelle/python/testdata/multiple_tests/README.md new file mode 100644 index 0000000000..8220f6112d --- /dev/null +++ b/gazelle/python/testdata/multiple_tests/README.md @@ -0,0 +1,3 @@ +# Multiple tests + +This test case asserts that a second `py_test` rule is correctly created when a second `*_test.py` file is added to a package with an existing `py_test` rule. diff --git a/gazelle/python/testdata/multiple_tests/WORKSPACE b/gazelle/python/testdata/multiple_tests/WORKSPACE new file mode 100644 index 0000000000..faff6af87a --- /dev/null +++ b/gazelle/python/testdata/multiple_tests/WORKSPACE @@ -0,0 +1 @@ +# This is a Bazel workspace for the Gazelle test data. diff --git a/gazelle/python/testdata/multiple_tests/__init__.py b/gazelle/python/testdata/multiple_tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/python/testdata/multiple_tests/bar_test.py b/gazelle/python/testdata/multiple_tests/bar_test.py new file mode 100644 index 0000000000..9948f1ccd4 --- /dev/null +++ b/gazelle/python/testdata/multiple_tests/bar_test.py @@ -0,0 +1,24 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest + + +class BarTest(unittest.TestCase): + def test_foo(self): + pass + + +if __name__ == "__main__": + unittest.main() diff --git a/gazelle/python/testdata/multiple_tests/foo_test.py b/gazelle/python/testdata/multiple_tests/foo_test.py new file mode 100644 index 0000000000..a128adf67f --- /dev/null +++ b/gazelle/python/testdata/multiple_tests/foo_test.py @@ -0,0 +1,24 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest + + +class FooTest(unittest.TestCase): + def test_foo(self): + pass + + +if __name__ == "__main__": + unittest.main() diff --git a/gazelle/python/testdata/multiple_tests/test.yaml b/gazelle/python/testdata/multiple_tests/test.yaml new file mode 100644 index 0000000000..2410223e59 --- /dev/null +++ b/gazelle/python/testdata/multiple_tests/test.yaml @@ -0,0 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +expect: + exit_code: 0 From b80b8fde601f3bee9a4174c4aef03a3811912b93 Mon Sep 17 00:00:00 2001 From: Mathieu Sabourin Date: Fri, 7 Apr 2023 23:52:41 -0700 Subject: [PATCH 209/234] fix: respect kind mapping (#1158) When using the kind `gazelle:map_kind` directive, `gazelle` will correctly generate the buildfile on the first pass (or if no target of that type / name are present). However, when running gazelle a second time (or if a target of the mapped kind with the same name is present), `gazelle` will error out saying that it kind create a target of the original kind because a target of mapped kind is present and has the same name. Ex: Given the directive `# gazelle:map_kind py_test py_pytest_test //src/bazel/rules/python:py_pytest_test.bzl`, `gazelle` will correctly generate a `py_pytest_test` target where it would have generated a `py_test` target. But on a second invocation of `gazelle` (and subsequent invocations) it will error our with: ``` gazelle: ERROR: failed to generate target "//test/python/common:common_test" of kind "py_test": a target of kind "py_pytest_test" with the same name already exists. Use the '# gazelle:python_test_naming_convention' directive to change the naming convention. ``` --- gazelle/python/generate.go | 27 +++++++++++++------ .../testdata/respect_kind_mapping/BUILD.in | 15 +++++++++++ .../testdata/respect_kind_mapping/BUILD.out | 20 ++++++++++++++ .../testdata/respect_kind_mapping/README.md | 3 +++ .../testdata/respect_kind_mapping/WORKSPACE | 1 + .../testdata/respect_kind_mapping/__init__.py | 17 ++++++++++++ .../testdata/respect_kind_mapping/__test__.py | 26 ++++++++++++++++++ .../testdata/respect_kind_mapping/foo.py | 16 +++++++++++ .../testdata/respect_kind_mapping/test.yaml | 17 ++++++++++++ 9 files changed, 134 insertions(+), 8 deletions(-) create mode 100644 gazelle/python/testdata/respect_kind_mapping/BUILD.in create mode 100644 gazelle/python/testdata/respect_kind_mapping/BUILD.out create mode 100644 gazelle/python/testdata/respect_kind_mapping/README.md create mode 100644 gazelle/python/testdata/respect_kind_mapping/WORKSPACE create mode 100644 gazelle/python/testdata/respect_kind_mapping/__init__.py create mode 100644 gazelle/python/testdata/respect_kind_mapping/__test__.py create mode 100644 gazelle/python/testdata/respect_kind_mapping/foo.py create mode 100644 gazelle/python/testdata/respect_kind_mapping/test.yaml diff --git a/gazelle/python/generate.go b/gazelle/python/generate.go index 26ffedaca2..fb41324fd6 100644 --- a/gazelle/python/generate.go +++ b/gazelle/python/generate.go @@ -46,6 +46,13 @@ var ( buildFilenames = []string{"BUILD", "BUILD.bazel"} ) +func GetActualKindName(kind string, args language.GenerateArgs) string { + if kindOverride, ok := args.Config.KindMap[kind]; ok { + return kindOverride.KindName + } + return kind +} + // GenerateRules extracts build metadata from source files in a directory. // GenerateRules is called in each directory where an update is requested // in depth-first post-order. @@ -70,6 +77,10 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } } + actualPyBinaryKind := GetActualKindName(pyBinaryKind, args) + actualPyLibraryKind := GetActualKindName(pyLibraryKind, args) + actualPyTestKind := GetActualKindName(pyTestKind, args) + pythonProjectRoot := cfg.PythonProjectRoot() packageName := filepath.Base(args.Dir) @@ -217,12 +228,12 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes // generate it correctly. if args.File != nil { for _, t := range args.File.Rules { - if t.Name() == pyLibraryTargetName && t.Kind() != pyLibraryKind { + if t.Name() == pyLibraryTargetName && t.Kind() != actualPyLibraryKind { fqTarget := label.New("", args.Rel, pyLibraryTargetName) err := fmt.Errorf("failed to generate target %q of kind %q: "+ "a target of kind %q with the same name already exists. "+ "Use the '# gazelle:%s' directive to change the naming convention.", - fqTarget.String(), pyLibraryKind, t.Kind(), pythonconfig.LibraryNamingConvention) + fqTarget.String(), actualPyLibraryKind, t.Kind(), pythonconfig.LibraryNamingConvention) collisionErrors.Add(err) } } @@ -253,12 +264,12 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes // generate it correctly. if args.File != nil { for _, t := range args.File.Rules { - if t.Name() == pyBinaryTargetName && t.Kind() != pyBinaryKind { + if t.Name() == pyBinaryTargetName && t.Kind() != actualPyBinaryKind { fqTarget := label.New("", args.Rel, pyBinaryTargetName) err := fmt.Errorf("failed to generate target %q of kind %q: "+ "a target of kind %q with the same name already exists. "+ "Use the '# gazelle:%s' directive to change the naming convention.", - fqTarget.String(), pyBinaryKind, t.Kind(), pythonconfig.BinaryNamingConvention) + fqTarget.String(), actualPyBinaryKind, t.Kind(), pythonconfig.BinaryNamingConvention) collisionErrors.Add(err) } } @@ -290,11 +301,11 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes // generate it correctly. if args.File != nil { for _, t := range args.File.Rules { - if t.Name() == conftestTargetname && t.Kind() != pyLibraryKind { + if t.Name() == conftestTargetname && t.Kind() != actualPyLibraryKind { fqTarget := label.New("", args.Rel, conftestTargetname) err := fmt.Errorf("failed to generate target %q of kind %q: "+ "a target of kind %q with the same name already exists.", - fqTarget.String(), pyLibraryKind, t.Kind()) + fqTarget.String(), actualPyLibraryKind, t.Kind()) collisionErrors.Add(err) } } @@ -325,12 +336,12 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes // generate it correctly. if args.File != nil { for _, t := range args.File.Rules { - if t.Name() == pyTestTargetName && t.Kind() != pyTestKind { + if t.Name() == pyTestTargetName && t.Kind() != actualPyTestKind { fqTarget := label.New("", args.Rel, pyTestTargetName) err := fmt.Errorf("failed to generate target %q of kind %q: "+ "a target of kind %q with the same name already exists. "+ "Use the '# gazelle:%s' directive to change the naming convention.", - fqTarget.String(), pyTestKind, t.Kind(), pythonconfig.TestNamingConvention) + fqTarget.String(), actualPyTestKind, t.Kind(), pythonconfig.TestNamingConvention) collisionErrors.Add(err) } } diff --git a/gazelle/python/testdata/respect_kind_mapping/BUILD.in b/gazelle/python/testdata/respect_kind_mapping/BUILD.in new file mode 100644 index 0000000000..6a06737623 --- /dev/null +++ b/gazelle/python/testdata/respect_kind_mapping/BUILD.in @@ -0,0 +1,15 @@ +load("@rules_python//python:defs.bzl", "py_library") + +# gazelle:map_kind py_test my_test :mytest.bzl + +py_library( + name = "respect_kind_mapping", + srcs = ["__init__.py"], +) + +my_test( + name = "respect_kind_mapping_test", + srcs = ["__test__.py"], + main = "__test__.py", + deps = [":respect_kind_mapping"], +) diff --git a/gazelle/python/testdata/respect_kind_mapping/BUILD.out b/gazelle/python/testdata/respect_kind_mapping/BUILD.out new file mode 100644 index 0000000000..7c5fb0bd20 --- /dev/null +++ b/gazelle/python/testdata/respect_kind_mapping/BUILD.out @@ -0,0 +1,20 @@ +load(":mytest.bzl", "my_test") +load("@rules_python//python:defs.bzl", "py_library") + +# gazelle:map_kind py_test my_test :mytest.bzl + +py_library( + name = "respect_kind_mapping", + srcs = [ + "__init__.py", + "foo.py", + ], + visibility = ["//:__subpackages__"], +) + +my_test( + name = "respect_kind_mapping_test", + srcs = ["__test__.py"], + main = "__test__.py", + deps = [":respect_kind_mapping"], +) diff --git a/gazelle/python/testdata/respect_kind_mapping/README.md b/gazelle/python/testdata/respect_kind_mapping/README.md new file mode 100644 index 0000000000..9f0fa6cf39 --- /dev/null +++ b/gazelle/python/testdata/respect_kind_mapping/README.md @@ -0,0 +1,3 @@ +# Respect Kind Mapping + +This test case asserts that when using a kind mapping, gazelle will respect that mapping when parsing a BUILD file containing a mapped kind. diff --git a/gazelle/python/testdata/respect_kind_mapping/WORKSPACE b/gazelle/python/testdata/respect_kind_mapping/WORKSPACE new file mode 100644 index 0000000000..faff6af87a --- /dev/null +++ b/gazelle/python/testdata/respect_kind_mapping/WORKSPACE @@ -0,0 +1 @@ +# This is a Bazel workspace for the Gazelle test data. diff --git a/gazelle/python/testdata/respect_kind_mapping/__init__.py b/gazelle/python/testdata/respect_kind_mapping/__init__.py new file mode 100644 index 0000000000..b274b0d921 --- /dev/null +++ b/gazelle/python/testdata/respect_kind_mapping/__init__.py @@ -0,0 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from foo import foo + +_ = foo diff --git a/gazelle/python/testdata/respect_kind_mapping/__test__.py b/gazelle/python/testdata/respect_kind_mapping/__test__.py new file mode 100644 index 0000000000..2b180a5f53 --- /dev/null +++ b/gazelle/python/testdata/respect_kind_mapping/__test__.py @@ -0,0 +1,26 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest + +from __init__ import foo + + +class FooTest(unittest.TestCase): + def test_foo(self): + self.assertEqual("foo", foo()) + + +if __name__ == "__main__": + unittest.main() diff --git a/gazelle/python/testdata/respect_kind_mapping/foo.py b/gazelle/python/testdata/respect_kind_mapping/foo.py new file mode 100644 index 0000000000..932de45b74 --- /dev/null +++ b/gazelle/python/testdata/respect_kind_mapping/foo.py @@ -0,0 +1,16 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +def foo(): + return "foo" diff --git a/gazelle/python/testdata/respect_kind_mapping/test.yaml b/gazelle/python/testdata/respect_kind_mapping/test.yaml new file mode 100644 index 0000000000..2410223e59 --- /dev/null +++ b/gazelle/python/testdata/respect_kind_mapping/test.yaml @@ -0,0 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +expect: + exit_code: 0 From 1e869d8d945f0b406da65817cf70b4fa3105a0de Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius Date: Tue, 11 Apr 2023 03:45:45 +0900 Subject: [PATCH 210/234] test: cleanup gazelle tests and run them in parallel (#1159) --- gazelle/python/python_test.go | 54 +++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/gazelle/python/python_test.go b/gazelle/python/python_test.go index 51e0101df1..79450ad584 100644 --- a/gazelle/python/python_test.go +++ b/gazelle/python/python_test.go @@ -74,8 +74,8 @@ func TestGazelleBinary(t *testing.T) { func testPath(t *testing.T, name string, files []bazel.RunfileEntry) { t.Run(name, func(t *testing.T) { - var inputs []testtools.FileSpec - var goldens []testtools.FileSpec + t.Parallel() + var inputs, goldens []testtools.FileSpec var config *testYAML for _, f := range files { @@ -111,43 +111,49 @@ func testPath(t *testing.T, name string, files []bazel.RunfileEntry) { Path: filepath.Join(name, strings.TrimSuffix(shortPath, ".in")), Content: string(content), }) - } else if strings.HasSuffix(shortPath, ".out") { + continue + } + + if strings.HasSuffix(shortPath, ".out") { goldens = append(goldens, testtools.FileSpec{ Path: filepath.Join(name, strings.TrimSuffix(shortPath, ".out")), Content: string(content), }) - } else { - inputs = append(inputs, testtools.FileSpec{ - Path: filepath.Join(name, shortPath), - Content: string(content), - }) - goldens = append(goldens, testtools.FileSpec{ - Path: filepath.Join(name, shortPath), - Content: string(content), - }) + continue } + + inputs = append(inputs, testtools.FileSpec{ + Path: filepath.Join(name, shortPath), + Content: string(content), + }) + goldens = append(goldens, testtools.FileSpec{ + Path: filepath.Join(name, shortPath), + Content: string(content), + }) } testdataDir, cleanup := testtools.CreateFiles(t, inputs) - defer cleanup() - defer func() { - if t.Failed() { - filepath.Walk(testdataDir, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - t.Logf("%q exists", strings.TrimPrefix(path, testdataDir)) - return nil - }) + t.Cleanup(cleanup) + t.Cleanup(func() { + if !t.Failed() { + return } - }() + + filepath.Walk(testdataDir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + t.Logf("%q exists", strings.TrimPrefix(path, testdataDir)) + return nil + }) + }) workspaceRoot := filepath.Join(testdataDir, name) args := []string{"-build_file_name=BUILD,BUILD.bazel"} ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) - defer cancel() + t.Cleanup(cancel) cmd := exec.CommandContext(ctx, gazellePath, args...) var stdout, stderr bytes.Buffer cmd.Stdout = &stdout From ebe81b7d1c0f33b62e80d2fc97e2ff1a9219b687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Felipe=20Barco=20Santa?= Date: Mon, 10 Apr 2023 22:11:19 -0500 Subject: [PATCH 211/234] [docs] Fixing rule name in coverage.md docs (#1162) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The docs explains that for activating coverage support we use `register_coverage_tool = True` inside the rule `register_python_toolchains`. There is no such rule, the actual rule name is `python_register_toolchains` Signed-off-by: Andrés Felipe Barco Santa --- docs/coverage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/coverage.md b/docs/coverage.md index bc613f8295..63f25782e0 100644 --- a/docs/coverage.md +++ b/docs/coverage.md @@ -23,7 +23,7 @@ python.toolchain( For WORKSPACE configuration: ```starlark -register_python_toolchains( +python_register_toolchains( register_coverage_tool = True, ) ``` From c72c7bcf4e0899c275042328e8233e3124ccae86 Mon Sep 17 00:00:00 2001 From: yuvalk Date: Tue, 11 Apr 2023 19:07:34 +0300 Subject: [PATCH 212/234] feat: Support specifying multiple download URLs in tool_versions. (#1145) The interface of `repository_ctx.download` and `repository_ctx.download_and_extract` supports string lists as well as strings as the value of the `url` argument. This is the ultimate destination of the `url` attribute in the `tool_versions` dictionary, so it makes sense for it to support lists as well. It is often useful to provide multiple download URLs, e.g. when vendoring deps through a mirror (to guard against issues like [git archive checksums changing](https://github.blog/changelog/2023-01-30-git-archive-checksums-may-change/) while still keeping the canonical download URL) or in an airgapped setting (to support internal URLs alongside external URLs). This is also pretty common around Bazel repository rules that download things, e.g. [http_archive](https://bazel.build/rules/lib/repo/http#http_archive-urls), so it can be expected to work with `tool_versions` too. --- python/repositories.bzl | 14 +++++++++----- python/versions.bzl | 36 ++++++++++++++++++++++++------------ 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/python/repositories.bzl b/python/repositories.bzl index f676610ae2..2429d7e026 100644 --- a/python/repositories.bzl +++ b/python/repositories.bzl @@ -99,12 +99,14 @@ def is_standalone_interpreter(rctx, python_interpreter_target): def _python_repository_impl(rctx): if rctx.attr.distutils and rctx.attr.distutils_content: fail("Only one of (distutils, distutils_content) should be set.") + if bool(rctx.attr.url) == bool(rctx.attr.urls): + fail("Exactly one of (url, urls) must be set.") platform = rctx.attr.platform python_version = rctx.attr.python_version python_short_version = python_version.rpartition(".")[0] release_filename = rctx.attr.release_filename - url = rctx.attr.url + url = rctx.attr.urls or [rctx.attr.url] if release_filename.endswith(".zst"): rctx.download( @@ -428,8 +430,10 @@ For more information see the official bazel docs doc = "A directory prefix to strip from the extracted files.", ), "url": attr.string( - doc = "The URL of the interpreter to download", - mandatory = True, + doc = "The URL of the interpreter to download. Exactly one of url and urls must be set.", + ), + "urls": attr.string_list( + doc = "The URL of the interpreter to download. Exactly one of url and urls must be set.", ), "zstd_sha256": attr.string( default = "7c42d56fac126929a6a85dbc73ff1db2411d04f104fae9bdea51305663a83fd0", @@ -506,7 +510,7 @@ def python_register_toolchains( if not sha256: continue - (release_filename, url, strip_prefix, patches) = get_release_info(platform, python_version, base_url, tool_versions) + (release_filename, urls, strip_prefix, patches) = get_release_info(platform, python_version, base_url, tool_versions) # allow passing in a tool version coverage_tool = None @@ -536,7 +540,7 @@ def python_register_toolchains( platform = platform, python_version = python_version, release_filename = release_filename, - url = url, + urls = urls, distutils = distutils, distutils_content = distutils_content, strip_prefix = strip_prefix, diff --git a/python/versions.bzl b/python/versions.bzl index 4feeeae58c..662f89d04b 100644 --- a/python/versions.bzl +++ b/python/versions.bzl @@ -41,6 +41,8 @@ DEFAULT_RELEASE_BASE_URL = "https://github.com/indygreg/python-build-standalone/ # "strip_prefix": "python", # }, # +# It is possible to provide lists in "url". +# # buildifier: disable=unsorted-dict-items TOOL_VERSIONS = { "3.8.10": { @@ -281,19 +283,28 @@ def get_release_info(platform, python_version, base_url = DEFAULT_RELEASE_BASE_U if type(url) == type({}): url = url[platform] + if type(url) != type([]): + url = [url] + strip_prefix = tool_versions[python_version].get("strip_prefix", None) if type(strip_prefix) == type({}): strip_prefix = strip_prefix[platform] - release_filename = url.format( - platform = platform, - python_version = python_version, - build = "shared-install_only" if (WINDOWS_NAME in platform) else "install_only", - ) - if "://" in release_filename: # is absolute url? - url = release_filename - else: - url = "/".join([base_url, release_filename]) + release_filename = None + rendered_urls = [] + for u in url: + release_filename = u.format( + platform = platform, + python_version = python_version, + build = "shared-install_only" if (WINDOWS_NAME in platform) else "install_only", + ) + if "://" in release_filename: # is absolute url? + rendered_urls.append(release_filename) + else: + rendered_urls.append("/".join([base_url, release_filename])) + + if release_filename == None: + fail("release_filename should be set by now; were any download URLs given?") patches = tool_versions[python_version].get("patches", []) if type(patches) == type({}): @@ -302,7 +313,7 @@ def get_release_info(platform, python_version, base_url = DEFAULT_RELEASE_BASE_U else: patches = [] - return (release_filename, url, strip_prefix, patches) + return (release_filename, rendered_urls, strip_prefix, patches) def print_toolchains_checksums(name): native.genrule( @@ -333,10 +344,11 @@ def _commands_for_version(python_version): "echo \"{python_version}: {platform}: $$(curl --location --fail {release_url_sha256} 2>/dev/null || curl --location --fail {release_url} 2>/dev/null | shasum -a 256 | awk '{{ print $$1 }}')\"".format( python_version = python_version, platform = platform, - release_url = get_release_info(platform, python_version)[1], - release_url_sha256 = get_release_info(platform, python_version)[1] + ".sha256", + release_url = release_url, + release_url_sha256 = release_url + ".sha256", ) for platform in TOOL_VERSIONS[python_version]["sha256"].keys() + for release_url in get_release_info(platform, python_version)[1] ]) def gen_python_config_settings(name = ""): From 73aec8f29b12b1e0f69f2cb7fc8e7fa2c34ca591 Mon Sep 17 00:00:00 2001 From: Ivo List Date: Mon, 24 Apr 2023 17:59:34 +0200 Subject: [PATCH 213/234] fix: remove reference to @bazel_tools//tools/python/private:defs.bzl (#1173) The file was removed in Bazel@HEAD in https://github.com/bazelbuild/bazel/pull/17545 This fixes failures when using rules_python with Bazel@HEAD. Addresses: https://github.com/bazelbuild/bazel/issues/17874 --- docs/BUILD.bazel | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/docs/BUILD.bazel b/docs/BUILD.bazel index e1163d9d0e..27af3e7ed5 100644 --- a/docs/BUILD.bazel +++ b/docs/BUILD.bazel @@ -32,17 +32,6 @@ _DOCS = { # because they're only used for doc generation. This way, we avoid requiring # our users to depend on Skylib. -# Requires Bazel 0.29 onward for public visibility of these .bzl files. -bzl_library( - name = "bazel_python_tools", - srcs = [ - "@bazel_tools//tools/python:private/defs.bzl", - "@bazel_tools//tools/python:srcs_version.bzl", - "@bazel_tools//tools/python:toolchain.bzl", - "@bazel_tools//tools/python:utils.bzl", - ], -) - bzl_library( name = "bazel_repo_tools", srcs = [ @@ -57,7 +46,7 @@ bzl_library( "//python/private:reexports.bzl", ], deps = [ - ":bazel_python_tools", + ":bazel_repo_tools", "//python:defs_bzl", "//python/private:reexports_bzl", ], From c5f24dd4927a0ce9881792389c84e359a3a7b528 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Mon, 24 Apr 2023 22:10:42 -0700 Subject: [PATCH 214/234] docs: Tell how to use GitHub to find commits in an upcoming release. (#1092) I can never remember what the syntax is of the compare URLs, so just doc it to make it easier. --- DEVELOPING.md | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/DEVELOPING.md b/DEVELOPING.md index 092e3efeaf..2972d96b79 100644 --- a/DEVELOPING.md +++ b/DEVELOPING.md @@ -7,17 +7,24 @@ Start from a clean checkout at `main`. Before running through the release it's good to run the build and the tests locally, and make sure CI is passing. You can also test-drive the commit in an existing Bazel workspace to sanity check functionality. +#### Steps +1. [Determine the next semantic version number](#determining-semantic-version) +1. Create a tag and push, e.g. `git tag 0.5.0 upstream/main && git push upstream --tags` + NOTE: Pushing the tag will trigger release automation. +1. Watch the release automation run on https://github.com/bazelbuild/rules_python/actions +1. Add missing information to the release notes. The automatic release note + generation only includes commits associated with issues. + #### Determining Semantic Version **rules_python** is currently using [Zero-based versioning](https://0ver.org/) and thus backwards-incompatible API changes still come under the minor-version digit. So releases with API changes and new features bump the minor, and -those with only bug fixes and other minor changes bump the patch digit. +those with only bug fixes and other minor changes bump the patch digit. + +To find if there were any features added or incompatible changes made, review +the commit history. This can be done using github by going to the url: +`https://github.com/bazelbuild/rules_python/compare/...main`. -#### Steps -1. Determine what will be the next release, following semver. -1. Create a tag and push, e.g. `git tag 0.5.0 upstream/main && git push upstream --tags` -1. Watch the release automation run on https://github.com/bazelbuild/rules_python/actions - #### After release creation in Github 1. Ping @philwo to get the new release added to mirror.bazel.build. See [this comment on issue #400](https://github.com/bazelbuild/rules_python/issues/400#issuecomment-779159530) for more context. From 952880642e157cc1dadba82579e7b18dde9b9160 Mon Sep 17 00:00:00 2001 From: Rasrack Date: Tue, 25 Apr 2023 19:20:00 +0200 Subject: [PATCH 215/234] fix: compile_pip_requirements test from external repositories (#1124) Previously when running the compile_pip_requirements test from an external repository the test failed. This was due to the fact that paths in the annotations of the lock file contained paths from the external repository. Another problem was that the requirement files could not be located. --- .bazelci/presubmit.yml | 38 +++++++++++ .../build_file_generation/gazelle_python.yaml | 2 +- .../requirements_lock.txt | 2 +- .../requirements_windows.txt | 2 +- examples/bzlmod/requirements_lock.txt | 12 ++-- examples/bzlmod/requirements_windows.txt | 12 ++-- examples/pip_install/requirements.txt | 8 +-- examples/pip_install/requirements_windows.txt | 6 +- examples/pip_parse/requirements_lock.txt | 6 +- examples/pip_parse_vendored/requirements.txt | 2 +- .../requirements.txt | 4 +- .../test/requirements_parser_tests.bzl | 6 +- python/pip_install/requirements.bzl | 3 +- .../dependency_resolver.py | 63 +++++++++++++++---- .../requirements_lock.txt | 4 +- .../.bazelrc | 1 + .../.gitignore | 1 + .../BUILD.bazel | 0 .../README.md | 3 + .../WORKSPACE | 36 +++++++++++ .../requirements.txt | 6 +- .../requirements_windows.txt | 6 +- 22 files changed, 170 insertions(+), 53 deletions(-) create mode 100644 tests/compile_pip_requirements_test_from_external_workspace/.bazelrc create mode 100644 tests/compile_pip_requirements_test_from_external_workspace/.gitignore create mode 100644 tests/compile_pip_requirements_test_from_external_workspace/BUILD.bazel create mode 100644 tests/compile_pip_requirements_test_from_external_workspace/README.md create mode 100644 tests/compile_pip_requirements_test_from_external_workspace/WORKSPACE diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 0e9feab093..7b5ba8b2f2 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -509,3 +509,41 @@ tasks: name: ignore_root_user_error integration tests on Windows working_directory: tests/ignore_root_user_error platform: windows + + integration_compile_pip_requirements_test_from_external_repo_ubuntu_min: + <<: *minimum_supported_version + name: compile_pip_requirements test from external repo on Ubuntu using minimum supported Bazel version + working_directory: tests/compile_pip_requirements_test_from_external_workspace + platform: ubuntu2004 + shell_commands: + # Assert that @external_repository//:requirements_test does the right thing. + - "bazel test @external_repository//..." + integration_compile_pip_requirements_test_from_external_repo_ubuntu: + name: compile_pip_requirements test from external repo on Ubuntu + working_directory: tests/compile_pip_requirements_test_from_external_workspace + platform: ubuntu2004 + shell_commands: + # Assert that @external_repository//:requirements_test does the right thing. + - "bazel test @external_repository//..." + integration_compile_pip_requirements_test_from_external_repo_debian: + name: compile_pip_requirements test from external repo on Debian + working_directory: tests/compile_pip_requirements_test_from_external_workspace + platform: debian11 + shell_commands: + # Assert that @external_repository//:requirements_test does the right thing. + - "bazel test @external_repository//..." + integration_compile_pip_requirements_test_from_external_repo_macos: + name: compile_pip_requirements test from external repo on macOS + working_directory: tests/compile_pip_requirements_test_from_external_workspace + platform: macos + shell_commands: + # Assert that @external_repository//:requirements_test does the right thing. + - "bazel test @external_repository//..." + integration_compile_pip_requirements_test_from_external_repo_windows: + name: compile_pip_requirements test from external repo on Windows + working_directory: tests/compile_pip_requirements_test_from_external_workspace + platform: windows + shell_commands: + # Assert that @external_repository//:requirements_test does the right thing. + - "bazel test @external_repository//..." + diff --git a/examples/build_file_generation/gazelle_python.yaml b/examples/build_file_generation/gazelle_python.yaml index b57e9f02bc..1000757ea5 100644 --- a/examples/build_file_generation/gazelle_python.yaml +++ b/examples/build_file_generation/gazelle_python.yaml @@ -115,4 +115,4 @@ manifest: pip_repository: name: pip use_pip_repository_aliases: true -integrity: 85f073e37e31339508aaaf5e0d5472adae5148fd5f054e9cc586343c026660e1 +integrity: 030d6d99b56c32d6577e616b617260d0a93588af791269162e43391a5a4fa576 diff --git a/examples/build_file_generation/requirements_lock.txt b/examples/build_file_generation/requirements_lock.txt index f73827a36e..443db71ddc 100644 --- a/examples/build_file_generation/requirements_lock.txt +++ b/examples/build_file_generation/requirements_lock.txt @@ -11,7 +11,7 @@ click==8.1.3 \ flask==2.2.2 \ --hash=sha256:642c450d19c4ad482f96729bd2a8f6d32554aa1e231f4f6b4e7e5264b16cca2b \ --hash=sha256:b9c46cc36662a7949f34b52d8ec7bb59c0d74ba08ba6cb9ce9adc1d8676d9526 - # via -r ./requirements.in + # via -r requirements.in importlib-metadata==5.2.0 \ --hash=sha256:0eafa39ba42bf225fc00e67f701d71f85aead9f878569caf13c3724f704b970f \ --hash=sha256:404d48d62bba0b7a77ff9d405efd91501bef2e67ff4ace0bed40a0cf28c3c7cd diff --git a/examples/build_file_generation/requirements_windows.txt b/examples/build_file_generation/requirements_windows.txt index fc097141c5..bdd536fdcf 100644 --- a/examples/build_file_generation/requirements_windows.txt +++ b/examples/build_file_generation/requirements_windows.txt @@ -15,7 +15,7 @@ colorama==0.4.6 \ flask==2.2.2 \ --hash=sha256:642c450d19c4ad482f96729bd2a8f6d32554aa1e231f4f6b4e7e5264b16cca2b \ --hash=sha256:b9c46cc36662a7949f34b52d8ec7bb59c0d74ba08ba6cb9ce9adc1d8676d9526 - # via -r ./requirements.in + # via -r requirements.in importlib-metadata==5.2.0 \ --hash=sha256:0eafa39ba42bf225fc00e67f701d71f85aead9f878569caf13c3724f704b970f \ --hash=sha256:404d48d62bba0b7a77ff9d405efd91501bef2e67ff4ace0bed40a0cf28c3c7cd diff --git a/examples/bzlmod/requirements_lock.txt b/examples/bzlmod/requirements_lock.txt index 482402ffb8..2160fe1163 100644 --- a/examples/bzlmod/requirements_lock.txt +++ b/examples/bzlmod/requirements_lock.txt @@ -64,12 +64,12 @@ platformdirs==2.6.0 \ pylint==2.15.9 \ --hash=sha256:18783cca3cfee5b83c6c5d10b3cdb66c6594520ffae61890858fe8d932e1c6b4 \ --hash=sha256:349c8cd36aede4d50a0754a8c0218b43323d13d5d88f4b2952ddfe3e169681eb - # via -r ./requirements.in + # via -r requirements.in python-dateutil==2.8.2 \ --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 # via - # -r ./requirements.in + # -r requirements.in # s3cmd python-magic==0.4.27 \ --hash=sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b \ @@ -120,11 +120,11 @@ pyyaml==6.0 \ requests==2.25.1 \ --hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \ --hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e - # via -r ./requirements.in + # via -r requirements.in s3cmd==2.1.0 \ --hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \ --hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03 - # via -r ./requirements.in + # via -r requirements.in setuptools==65.6.3 \ --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 @@ -136,7 +136,7 @@ six==1.16.0 \ tabulate==0.9.0 \ --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \ --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f - # via -r ./requirements.in + # via -r requirements.in tomli==2.0.1 \ --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f @@ -224,4 +224,4 @@ wrapt==1.14.1 \ yamllint==1.28.0 \ --hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \ --hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b - # via -r ./requirements.in + # via -r requirements.in diff --git a/examples/bzlmod/requirements_windows.txt b/examples/bzlmod/requirements_windows.txt index 41187b9475..06cfdc332c 100644 --- a/examples/bzlmod/requirements_windows.txt +++ b/examples/bzlmod/requirements_windows.txt @@ -68,12 +68,12 @@ platformdirs==2.6.0 \ pylint==2.15.9 \ --hash=sha256:18783cca3cfee5b83c6c5d10b3cdb66c6594520ffae61890858fe8d932e1c6b4 \ --hash=sha256:349c8cd36aede4d50a0754a8c0218b43323d13d5d88f4b2952ddfe3e169681eb - # via -r ./requirements.in + # via -r requirements.in python-dateutil==2.8.2 \ --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 # via - # -r ./requirements.in + # -r requirements.in # s3cmd python-magic==0.4.27 \ --hash=sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b \ @@ -124,11 +124,11 @@ pyyaml==6.0 \ requests==2.25.1 \ --hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \ --hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e - # via -r ./requirements.in + # via -r requirements.in s3cmd==2.1.0 \ --hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \ --hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03 - # via -r ./requirements.in + # via -r requirements.in setuptools==65.6.3 \ --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 @@ -140,7 +140,7 @@ six==1.16.0 \ tabulate==0.9.0 \ --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \ --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f - # via -r ./requirements.in + # via -r requirements.in tomli==2.0.1 \ --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f @@ -228,4 +228,4 @@ wrapt==1.14.1 \ yamllint==1.28.0 \ --hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \ --hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b - # via -r ./requirements.in + # via -r requirements.in diff --git a/examples/pip_install/requirements.txt b/examples/pip_install/requirements.txt index ca8d5943a7..495a32a637 100644 --- a/examples/pip_install/requirements.txt +++ b/examples/pip_install/requirements.txt @@ -7,7 +7,7 @@ boto3==1.14.63 \ --hash=sha256:25c716b7c01d4664027afc6a6418a06459e311a610c7fd39a030a1ced1b72ce4 \ --hash=sha256:37158c37a151eab5b9080968305621a40168171fda9584d50a309ceb4e5e6964 - # via -r ./requirements.in + # via -r requirements.in botocore==1.17.63 \ --hash=sha256:40f13f6c9c29c307a9dc5982739e537ddce55b29787b90c3447b507e3283bcd6 \ --hash=sha256:aa88eafc6295132f4bc606f1df32b3248e0fa611724c0a216aceda767948ac75 @@ -84,7 +84,7 @@ pyyaml==6.0 \ s3cmd==2.1.0 \ --hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \ --hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03 - # via -r ./requirements.in + # via -r requirements.in s3transfer==0.3.7 \ --hash=sha256:35627b86af8ff97e7ac27975fe0a98a312814b46c6333d8a6b889627bcd80994 \ --hash=sha256:efa5bd92a897b6a8d5c1383828dca3d52d0790e0756d49740563a3fb6ed03246 @@ -100,11 +100,11 @@ six==1.16.0 \ tree-sitter==0.20.0 ; sys_platform != "win32" \ --hash=sha256:1940f64be1e8c9c3c0e34a2258f1e4c324207534d5b1eefc5ab2960a9d98f668 \ --hash=sha256:51a609a7c1bd9d9e75d92ee128c12c7852ae70a482900fbbccf3d13a79e0378c - # via -r ./requirements.in + # via -r requirements.in urllib3==1.25.11 \ --hash=sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2 \ --hash=sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e # via botocore yamllint==1.26.3 \ --hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e - # via -r ./requirements.in + # via -r requirements.in diff --git a/examples/pip_install/requirements_windows.txt b/examples/pip_install/requirements_windows.txt index c4279cb6d7..b87192f9d0 100644 --- a/examples/pip_install/requirements_windows.txt +++ b/examples/pip_install/requirements_windows.txt @@ -7,7 +7,7 @@ boto3==1.14.63 \ --hash=sha256:25c716b7c01d4664027afc6a6418a06459e311a610c7fd39a030a1ced1b72ce4 \ --hash=sha256:37158c37a151eab5b9080968305621a40168171fda9584d50a309ceb4e5e6964 - # via -r ./requirements.in + # via -r requirements.in botocore==1.17.63 \ --hash=sha256:40f13f6c9c29c307a9dc5982739e537ddce55b29787b90c3447b507e3283bcd6 \ --hash=sha256:aa88eafc6295132f4bc606f1df32b3248e0fa611724c0a216aceda767948ac75 @@ -84,7 +84,7 @@ pyyaml==6.0 \ s3cmd==2.1.0 \ --hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \ --hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03 - # via -r ./requirements.in + # via -r requirements.in s3transfer==0.3.7 \ --hash=sha256:35627b86af8ff97e7ac27975fe0a98a312814b46c6333d8a6b889627bcd80994 \ --hash=sha256:efa5bd92a897b6a8d5c1383828dca3d52d0790e0756d49740563a3fb6ed03246 @@ -103,4 +103,4 @@ urllib3==1.25.11 \ # via botocore yamllint==1.26.3 \ --hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e - # via -r ./requirements.in + # via -r requirements.in diff --git a/examples/pip_parse/requirements_lock.txt b/examples/pip_parse/requirements_lock.txt index d60295c0bf..3cbe57f28c 100644 --- a/examples/pip_parse/requirements_lock.txt +++ b/examples/pip_parse/requirements_lock.txt @@ -73,11 +73,11 @@ pyyaml==6.0 \ requests==2.25.1 \ --hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \ --hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e - # via -r ./requirements.in + # via -r requirements.in s3cmd==2.1.0 \ --hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \ --hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03 - # via -r ./requirements.in + # via -r requirements.in setuptools==65.6.3 \ --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 @@ -92,4 +92,4 @@ urllib3==1.26.13 \ # via requests yamllint==1.26.3 \ --hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e - # via -r ./requirements.in + # via -r requirements.in diff --git a/examples/pip_parse_vendored/requirements.txt b/examples/pip_parse_vendored/requirements.txt index 6a70e036b4..ff1a3633a2 100644 --- a/examples/pip_parse_vendored/requirements.txt +++ b/examples/pip_parse_vendored/requirements.txt @@ -19,7 +19,7 @@ idna==3.4 \ requests==2.28.1 \ --hash=sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983 \ --hash=sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349 - # via -r ./requirements.in + # via -r requirements.in urllib3==1.26.13 \ --hash=sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc \ --hash=sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8 diff --git a/examples/pip_repository_annotations/requirements.txt b/examples/pip_repository_annotations/requirements.txt index f599f7a457..9fde0a922f 100644 --- a/examples/pip_repository_annotations/requirements.txt +++ b/examples/pip_repository_annotations/requirements.txt @@ -21,7 +21,7 @@ idna==3.4 \ requests[security]==2.28.1 \ --hash=sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983 \ --hash=sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349 - # via -r ./requirements.in + # via -r requirements.in urllib3==1.26.13 \ --hash=sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc \ --hash=sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8 @@ -29,4 +29,4 @@ urllib3==1.26.13 \ wheel==0.38.4 \ --hash=sha256:965f5259b566725405b05e7cf774052044b1ed30119b5d586b2703aafe8719ac \ --hash=sha256:b60533f3f5d530e971d6737ca6d58681ee434818fab630c83a734bb10c083ce8 - # via -r ./requirements.in + # via -r requirements.in diff --git a/python/pip_install/private/test/requirements_parser_tests.bzl b/python/pip_install/private/test/requirements_parser_tests.bzl index 13c40c2956..c13ec204fb 100644 --- a/python/pip_install/private/test/requirements_parser_tests.bzl +++ b/python/pip_install/private/test/requirements_parser_tests.bzl @@ -177,11 +177,11 @@ pyyaml==6.0 \ requests==2.25.1 \ --hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \ --hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e - # via -r ./requirements.in + # via -r requirements.in s3cmd==2.1.0 \ --hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \ --hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03 - # via -r ./requirements.in + # via -r requirements.in six==1.16.0 \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 @@ -192,7 +192,7 @@ urllib3==1.26.7 \ # via requests yamllint==1.26.3 \ --hash=sha256:3934dcde484374596d6b52d8db412929a169f6d9e52e20f9ade5bf3523d9b96e - # via -r ./requirements.in + # via -r requirements.in # The following packages are considered to be unsafe in a requirements file: setuptools==59.6.0 \ diff --git a/python/pip_install/requirements.bzl b/python/pip_install/requirements.bzl index dd38c9df5b..7594471897 100644 --- a/python/pip_install/requirements.bzl +++ b/python/pip_install/requirements.bzl @@ -75,7 +75,7 @@ def compile_pip_requirements( # where it appears, which is to say, in @rules_python pip_compile = Label("//python/pip_install/tools/dependency_resolver:dependency_resolver.py") - loc = "$(rootpath {})" + loc = "$(rlocationpath {})" args = [ loc.format(requirements_in), @@ -99,6 +99,7 @@ def compile_pip_requirements( requirement("importlib_metadata"), requirement("zipp"), requirement("more_itertools"), + Label("//python/runfiles:runfiles"), ] + extra_deps tags = tags or [] diff --git a/python/pip_install/tools/dependency_resolver/dependency_resolver.py b/python/pip_install/tools/dependency_resolver/dependency_resolver.py index e636febd93..89e355806c 100644 --- a/python/pip_install/tools/dependency_resolver/dependency_resolver.py +++ b/python/pip_install/tools/dependency_resolver/dependency_resolver.py @@ -23,6 +23,8 @@ import piptools.writer as piptools_writer from piptools.scripts.compile import cli +from python.runfiles import runfiles + # Replace the os.replace function with shutil.copy to work around os.replace not being able to # replace or move files across filesystems. os.replace = shutil.copy @@ -66,6 +68,15 @@ def _select_golden_requirements_file( return requirements_txt +def _locate(bazel_runfiles, file): + """Look up the file via Rlocation""" + + if not file: + return file + + return bazel_runfiles.Rlocation(file) + + if __name__ == "__main__": if len(sys.argv) < 4: print( @@ -75,6 +86,7 @@ def _select_golden_requirements_file( sys.exit(1) parse_str_none = lambda s: None if s == "None" else s + bazel_runfiles = runfiles.Create() requirements_in = sys.argv.pop(1) requirements_txt = sys.argv.pop(1) @@ -83,10 +95,25 @@ def _select_golden_requirements_file( requirements_windows = parse_str_none(sys.argv.pop(1)) update_target_label = sys.argv.pop(1) - # The requirements_in file could be generated, so we will need to remove the - # absolute prefixes in the locked requirements output file. - requirements_in_path = Path(requirements_in) - resolved_requirements_in = str(requirements_in_path.resolve()) + resolved_requirements_in = _locate(bazel_runfiles, requirements_in) + resolved_requirements_txt = _locate(bazel_runfiles, requirements_txt) + + # Files in the runfiles directory has the following naming schema: + # Main repo: __main__/ + # External repo: / + # We want to strip both __main__ and from the absolute prefix + # to keep the requirements lock file agnostic. + repository_prefix = requirements_txt[: requirements_txt.index("/") + 1] + absolute_path_prefix = resolved_requirements_txt[ + : -(len(requirements_txt) - len(repository_prefix)) + ] + + # As requirements_in might contain references to generated files we want to + # use the runfiles file first. Thus, we need to compute the relative path + # from the execution root. + # Note: Windows cannot reference generated files without runfiles support enabled. + requirements_in_relative = requirements_in[len(repository_prefix) :] + requirements_txt_relative = requirements_txt[len(repository_prefix) :] # Before loading click, set the locale for its parser. # If it leaks through to the system setting, it may fail: @@ -112,7 +139,7 @@ def _select_golden_requirements_file( ) # Those two files won't necessarily be on the same filesystem, so we can't use os.replace # or shutil.copyfile, as they will fail with OSError: [Errno 18] Invalid cross-device link. - shutil.copy(requirements_txt, requirements_out) + shutil.copy(resolved_requirements_txt, requirements_out) update_command = os.getenv("CUSTOM_COMPILE_COMMAND") or "bazel run %s" % ( update_target_label, @@ -123,24 +150,33 @@ def _select_golden_requirements_file( sys.argv.append("--generate-hashes") sys.argv.append("--output-file") - sys.argv.append(requirements_txt if UPDATE else requirements_out) + sys.argv.append(requirements_txt_relative if UPDATE else requirements_out) sys.argv.append( - requirements_in if requirements_in_path.exists() else resolved_requirements_in + requirements_in_relative + if Path(requirements_in_relative).exists() + else resolved_requirements_in ) + print(sys.argv) if UPDATE: - print("Updating " + requirements_txt) + print("Updating " + requirements_txt_relative) if "BUILD_WORKSPACE_DIRECTORY" in os.environ: workspace = os.environ["BUILD_WORKSPACE_DIRECTORY"] - requirements_txt_tree = os.path.join(workspace, requirements_txt) + requirements_txt_tree = os.path.join(workspace, requirements_txt_relative) # In most cases, requirements_txt will be a symlink to the real file in the source tree. # If symlinks are not enabled (e.g. on Windows), then requirements_txt will be a copy, # and we should copy the updated requirements back to the source tree. - if not os.path.samefile(requirements_txt, requirements_txt_tree): + if not os.path.samefile(resolved_requirements_txt, requirements_txt_tree): atexit.register( - lambda: shutil.copy(requirements_txt, requirements_txt_tree) + lambda: shutil.copy( + resolved_requirements_txt, requirements_txt_tree + ) ) cli() + requirements_txt_relative_path = Path(requirements_txt_relative) + content = requirements_txt_relative_path.read_text() + content = content.replace(absolute_path_prefix, "") + requirements_txt_relative_path.write_text(content) else: # cli will exit(0) on success try: @@ -153,7 +189,7 @@ def _select_golden_requirements_file( print( "pip-compile exited with code 2. This means that pip-compile found " "incompatible requirements or could not find a version that matches " - f"the install requirement in {requirements_in}.", + f"the install requirement in {requirements_in_relative}.", file=sys.stderr, ) sys.exit(1) @@ -164,8 +200,9 @@ def _select_golden_requirements_file( requirements_darwin, requirements_windows, ) - golden = open(golden_filename).readlines() + golden = open(_locate(bazel_runfiles, golden_filename)).readlines() out = open(requirements_out).readlines() + out = [line.replace(absolute_path_prefix, "") for line in out] if golden != out: import difflib diff --git a/tests/compile_pip_requirements/requirements_lock.txt b/tests/compile_pip_requirements/requirements_lock.txt index 8f7037ce7a..4ca4a11f3e 100644 --- a/tests/compile_pip_requirements/requirements_lock.txt +++ b/tests/compile_pip_requirements/requirements_lock.txt @@ -7,8 +7,8 @@ pip==22.3.1 \ --hash=sha256:65fd48317359f3af8e593943e6ae1506b66325085ea64b706a998c6e83eeaf38 \ --hash=sha256:908c78e6bc29b676ede1c4d57981d490cb892eb45cd8c214ab6298125119e077 - # via -r ./requirements.in + # via -r requirements.in setuptools==65.6.3 \ --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 - # via -r ./requirements_extra.in + # via -r requirements_extra.in diff --git a/tests/compile_pip_requirements_test_from_external_workspace/.bazelrc b/tests/compile_pip_requirements_test_from_external_workspace/.bazelrc new file mode 100644 index 0000000000..b98fc09774 --- /dev/null +++ b/tests/compile_pip_requirements_test_from_external_workspace/.bazelrc @@ -0,0 +1 @@ +test --test_output=errors diff --git a/tests/compile_pip_requirements_test_from_external_workspace/.gitignore b/tests/compile_pip_requirements_test_from_external_workspace/.gitignore new file mode 100644 index 0000000000..ac51a054d2 --- /dev/null +++ b/tests/compile_pip_requirements_test_from_external_workspace/.gitignore @@ -0,0 +1 @@ +bazel-* diff --git a/tests/compile_pip_requirements_test_from_external_workspace/BUILD.bazel b/tests/compile_pip_requirements_test_from_external_workspace/BUILD.bazel new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/compile_pip_requirements_test_from_external_workspace/README.md b/tests/compile_pip_requirements_test_from_external_workspace/README.md new file mode 100644 index 0000000000..8ce77ca1f1 --- /dev/null +++ b/tests/compile_pip_requirements_test_from_external_workspace/README.md @@ -0,0 +1,3 @@ +# compile_pip_requirements_test_from_external_workspace + +This test checks that compile_pip_requirements test can be run from external workspaces without invalidating the lock file. diff --git a/tests/compile_pip_requirements_test_from_external_workspace/WORKSPACE b/tests/compile_pip_requirements_test_from_external_workspace/WORKSPACE new file mode 100644 index 0000000000..35686a1d30 --- /dev/null +++ b/tests/compile_pip_requirements_test_from_external_workspace/WORKSPACE @@ -0,0 +1,36 @@ +local_repository( + name = "rules_python", + path = "../..", +) + +load("@rules_python//python:repositories.bzl", "py_repositories", "python_register_toolchains") + +py_repositories() + +load("@rules_python//python/pip_install:repositories.bzl", "pip_install_dependencies") + +pip_install_dependencies() + +python_register_toolchains( + name = "python39", + python_version = "3.9", +) + +load("@python39//:defs.bzl", "interpreter") +load("@rules_python//python:pip.bzl", "pip_parse") + +local_repository( + name = "external_repository", + path = "../compile_pip_requirements", +) + +pip_parse( + name = "pypi", + python_interpreter_target = interpreter, + requirements_lock = "@external_repository//:requirements_lock.txt", +) + +load("@pypi//:requirements.bzl", "install_deps") + +# Initialize repositories for all packages in requirements_lock.txt. +install_deps() diff --git a/tests/pip_repository_entry_points/requirements.txt b/tests/pip_repository_entry_points/requirements.txt index 90b717e7a7..a93facc03b 100644 --- a/tests/pip_repository_entry_points/requirements.txt +++ b/tests/pip_repository_entry_points/requirements.txt @@ -170,7 +170,7 @@ setuptools==59.6.0 \ --hash=sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373 \ --hash=sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e # via - # -r ./requirements.in + # -r requirements.in # sphinx # yamllint snowballstemmer==2.2.0 \ @@ -180,7 +180,7 @@ snowballstemmer==2.2.0 \ sphinx==4.3.2 \ --hash=sha256:0a8836751a68306b3fe97ecbe44db786f8479c3bf4b80e3a7f5c838657b4698c \ --hash=sha256:6a11ea5dd0bdb197f9c2abc2e0ce73e01340464feaece525e64036546d24c851 - # via -r ./requirements.in + # via -r requirements.in sphinxcontrib-applehelp==1.0.2 \ --hash=sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a \ --hash=sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58 @@ -212,4 +212,4 @@ urllib3==1.26.7 \ yamllint==1.28.0 \ --hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \ --hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b - # via -r ./requirements.in + # via -r requirements.in diff --git a/tests/pip_repository_entry_points/requirements_windows.txt b/tests/pip_repository_entry_points/requirements_windows.txt index 14c3dc3274..651e2b5e56 100644 --- a/tests/pip_repository_entry_points/requirements_windows.txt +++ b/tests/pip_repository_entry_points/requirements_windows.txt @@ -174,7 +174,7 @@ setuptools==59.6.0 \ --hash=sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373 \ --hash=sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e # via - # -r ./requirements.in + # -r requirements.in # sphinx # yamllint snowballstemmer==2.2.0 \ @@ -184,7 +184,7 @@ snowballstemmer==2.2.0 \ sphinx==4.3.2 \ --hash=sha256:0a8836751a68306b3fe97ecbe44db786f8479c3bf4b80e3a7f5c838657b4698c \ --hash=sha256:6a11ea5dd0bdb197f9c2abc2e0ce73e01340464feaece525e64036546d24c851 - # via -r ./requirements.in + # via -r requirements.in sphinxcontrib-applehelp==1.0.2 \ --hash=sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a \ --hash=sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58 @@ -216,4 +216,4 @@ urllib3==1.26.7 \ yamllint==1.28.0 \ --hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \ --hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b - # via -r ./requirements.in + # via -r requirements.in From ba2a903bc1e608c5847bb0b51fd60709b0a187f3 Mon Sep 17 00:00:00 2001 From: Mingliang Jiang Date: Tue, 25 Apr 2023 16:39:51 -0700 Subject: [PATCH 216/234] feat: add Python 3.8.16 (#1168) Add python 3.8.16 --- python/versions.bzl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/python/versions.bzl b/python/versions.bzl index 662f89d04b..baf6e33a06 100644 --- a/python/versions.bzl +++ b/python/versions.bzl @@ -86,6 +86,17 @@ TOOL_VERSIONS = { }, "strip_prefix": "python", }, + "3.8.16": { + "url": "20230116/cpython-{python_version}+20230116-{platform}-{build}.tar.gz", + "sha256": { + "aarch64-apple-darwin": "d1f408569d8807c1053939d7822b082a17545e363697e1ce3cfb1ee75834c7be", + "aarch64-unknown-linux-gnu": "15d00bc8400ed6d94c665a797dc8ed7a491ae25c5022e738dcd665cd29beec42", + "x86_64-apple-darwin": "484ba901f64fc7888bec5994eb49343dc3f9d00ed43df17ee9c40935aad4aa18", + "x86_64-pc-windows-msvc": "b446bec833eaba1bac9063bb9b4aeadfdf67fa81783b4487a90c56d408fb7994", + "x86_64-unknown-linux-gnu": "c890de112f1ae31283a31fefd2061d5c97bdd4d1bdd795552c7abddef2697ea1", + }, + "strip_prefix": "python", + }, "3.9.10": { "url": "20220227/cpython-{python_version}+20220227-{platform}-{build}.tar.gz", "sha256": { From fb6f49f76db31273aa74f86e6ba50bc4facdc24f Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Tue, 25 Apr 2023 20:09:45 -0700 Subject: [PATCH 217/234] test: Set mac platform for test_mac_requires_darwin_for_execution (#1179) This makes the test pass on Bazel built from head. The failure appears due to not forcing the test to a Mac platform, so the underlying logic in `py_test` to detect the Mac platform fails and doesn't add the ExecutionInfo with the necessary info. Work towards bazelbuild/bazel/issues/18170 --- tools/build_defs/python/tests/py_test/py_test_tests.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/build_defs/python/tests/py_test/py_test_tests.bzl b/tools/build_defs/python/tests/py_test/py_test_tests.bzl index f2b4875b15..41fd27da55 100644 --- a/tools/build_defs/python/tests/py_test/py_test_tests.bzl +++ b/tools/build_defs/python/tests/py_test/py_test_tests.bzl @@ -45,7 +45,7 @@ def _test_mac_requires_darwin_for_execution(name, config): config_settings = { "//command_line_option:cpu": "darwin_x86_64", "//command_line_option:crosstool_top": "@rules_python//tools/build_defs/python/tests:cc_toolchain_suite", - #"//command_line_option:platforms": "@rules_python//tools/build_defs/python/tests:mac", + "//command_line_option:platforms": "@rules_python//tools/build_defs/python/tests:mac", }, ) From 600dbe1d10d7055a3fb0644e0cec5badbd5dd240 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Tue, 25 Apr 2023 20:10:02 -0700 Subject: [PATCH 218/234] fix: Don't reference deleted private bazel_tools bzl file (#1180) The latest versions of Bazel have removed the `@bazel_tools//tools/python:private/defs.bzl` file, so it can no longer be referenced. Work towards bazelbuild/bazel/issues/18170 --- BUILD.bazel | 1 - 1 file changed, 1 deletion(-) diff --git a/BUILD.bazel b/BUILD.bazel index dff608a1ca..35a3df892f 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -52,7 +52,6 @@ filegroup( "//python/pip_install:bzl", "//python:bzl", # Requires Bazel 0.29 onward for public visibility of these .bzl files. - "@bazel_tools//tools/python:private/defs.bzl", "@bazel_tools//tools/python:python_version.bzl", "@bazel_tools//tools/python:srcs_version.bzl", "@bazel_tools//tools/python:toolchain.bzl", From 2882bb6eb39b974fc8ba8869ce0f0787598cc69a Mon Sep 17 00:00:00 2001 From: Borja Lorente Date: Thu, 27 Apr 2023 17:14:51 +0100 Subject: [PATCH 219/234] docs: Add starlark directive to code snippet (#1170) A very minor cleaup change. --- gazelle/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gazelle/README.md b/gazelle/README.md index e9a8052353..2cd38764fc 100644 --- a/gazelle/README.md +++ b/gazelle/README.md @@ -93,7 +93,7 @@ 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: -``` +```starlark load("@bazel_gazelle//:def.bzl", "gazelle") load("@rules_python_gazelle_plugin//:def.bzl", "GAZELLE_PYTHON_RUNTIME_DEPS") From 548ced53f980d726f9d8996572fa791f7c8ce0cc Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Thu, 27 Apr 2023 14:04:39 -0700 Subject: [PATCH 220/234] tests: Upgrade rules_testing to 0.0.5 (#1184) This just keeps it at a recent version, which makes errors easier to grok. rules_testing recently underwent a large refactor, so it's confusing when errors reference lines that no longer exist in recent versions. --- internal_deps.bzl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal_deps.bzl b/internal_deps.bzl index 8f52b0e7d7..86a53b25e7 100644 --- a/internal_deps.bzl +++ b/internal_deps.bzl @@ -42,9 +42,9 @@ def rules_python_internal_deps(): maybe( http_archive, name = "rules_testing", - url = "https://github.com/bazelbuild/rules_testing/releases/download/v0.0.1/rules_testing-v0.0.1.tar.gz", - sha256 = "47db8fc9c3c1837491333cdcedebf267285479bd709a1ff0a47b19a324817def", - strip_prefix = "rules_testing-0.0.1", + sha256 = "0c2abee201f566a088c720e12bc1d968bc56e6a51b692d9c81b1fe861bdf2be2", + strip_prefix = "rules_testing-0.0.5", + url = "https://github.com/bazelbuild/rules_testing/releases/download/v0.0.5/rules_testing-v0.0.5.tar.gz", ) maybe( From ce749147a9a4f8fc8ef6141bf34ab538ed7f7476 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Fri, 28 Apr 2023 09:21:40 -0700 Subject: [PATCH 221/234] tests: Set linux platform for test_non_mac_doesnt_require_darwin_for_execution (#1183) This is the inverse test of the one testing for the mac platform. As before, the line forcing the platform to a non-mac platform was commented out, which meant, when a mac host built it, it would build the underlying target for Mac, which violated the test's assumptions. Work towards bazelbuild/bazel/issues/18170 Fixes #1185 --- tools/build_defs/python/tests/py_test/py_test_tests.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/build_defs/python/tests/py_test/py_test_tests.bzl b/tools/build_defs/python/tests/py_test/py_test_tests.bzl index 41fd27da55..560883200a 100644 --- a/tools/build_defs/python/tests/py_test/py_test_tests.bzl +++ b/tools/build_defs/python/tests/py_test/py_test_tests.bzl @@ -76,7 +76,7 @@ def _test_non_mac_doesnt_require_darwin_for_execution(name, config): config_settings = { "//command_line_option:cpu": "k8", "//command_line_option:crosstool_top": "@rules_python//tools/build_defs/python/tests:cc_toolchain_suite", - #"//command_line_option:platforms": "@rules_python//tools/build_defs/python/tests:linux", + "//command_line_option:platforms": "@rules_python//tools/build_defs/python/tests:linux", }, ) From 1d1efe906b4c5bf215f807844ba9b53869fa53e6 Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius Date: Tue, 2 May 2023 02:34:57 +0900 Subject: [PATCH 222/234] fix(bzlmod): correctly template repository macros for requirements, etc (#1190) It seems that the macros for specifying the requirements break when the user starts using `incompatible_generate_aliases=True`. This PR fixes this. Testing done: 1. Modify the example: ``` $ git diff diff --git a/examples/bzlmod/MODULE.bazel b/examples/bzlmod/MODULE.bazel index ce91228..1750210 100644 --- a/examples/bzlmod/MODULE.bazel +++ b/examples/bzlmod/MODULE.bazel @@ -26,6 +26,7 @@ register_toolchains( pip = use_extension("@rules_python//python:extensions.bzl", "pip") pip.parse( name = "pip", + incompatible_generate_aliases=True, requirements_lock = "//:requirements_lock.txt", requirements_windows = "//:requirements_windows.txt", ) ``` 2. Run `bazel build ...` and check that it is still working. I noticed this when working on #1189 and creating a separate PR for easier cherry-picking if we wanted to make a patch release which includes this. I am not sure how I could make an automated test for this other than creating a separate example. --- python/pip_install/pip_repository.bzl | 11 ++++++++++- .../pip_repository_requirements_bzlmod.bzl.tmpl | 8 ++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl index fce0dcdd47..1ea7bca88a 100644 --- a/python/pip_install/pip_repository.bzl +++ b/python/pip_install/pip_repository.bzl @@ -367,6 +367,15 @@ def _pip_repository_bzlmod_impl(rctx): else: build_contents += _bzlmod_pkg_aliases(repo_name, bzl_packages) + # NOTE: we are using the canonical name with the double '@' in order to + # always uniquely identify a repository, as the labels are being passed as + # a string and the resolution of the label happens at the call-site of the + # `requirement`, et al. macros. + if rctx.attr.incompatible_generate_aliases: + macro_tmpl = "@@{name}//{{}}:{{}}".format(name = rctx.attr.name) + else: + macro_tmpl = "@@{name}//:{{}}_{{}}".format(name = rctx.attr.name) + rctx.file("BUILD.bazel", build_contents) rctx.template("requirements.bzl", rctx.attr._template, substitutions = { "%%ALL_REQUIREMENTS%%": _format_repr_list([ @@ -377,7 +386,7 @@ def _pip_repository_bzlmod_impl(rctx): "@{}//{}:whl".format(repo_name, p) if rctx.attr.incompatible_generate_aliases else "@{}_{}//:whl".format(rctx.attr.name, p) for p in bzl_packages ]), - "%%NAME%%": rctx.attr.name, + "%%MACRO_TMPL%%": macro_tmpl, "%%REQUIREMENTS_LOCK%%": str(requirements_txt), }) diff --git a/python/pip_install/pip_repository_requirements_bzlmod.bzl.tmpl b/python/pip_install/pip_repository_requirements_bzlmod.bzl.tmpl index 462829d074..1b2e2178bb 100644 --- a/python/pip_install/pip_repository_requirements_bzlmod.bzl.tmpl +++ b/python/pip_install/pip_repository_requirements_bzlmod.bzl.tmpl @@ -12,13 +12,13 @@ def _clean_name(name): return name.replace("-", "_").replace(".", "_").lower() def requirement(name): - return "@@%%NAME%%//:" + _clean_name(name) + "_pkg" + return "%%MACRO_TMPL%%".format(_clean_name(name), "pkg") def whl_requirement(name): - return "@@%%NAME%%//:" + _clean_name(name) + "_whl" + return "%%MACRO_TMPL%%".format(_clean_name(name), "whl") def data_requirement(name): - return "@@%%NAME%%//:" + _clean_name(name) + "_data" + return "%%MACRO_TMPL%%".format(_clean_name(name), "data") def dist_info_requirement(name): - return "@@%%NAME%%//:" + _clean_name(name) + "_dist_info" + return "%%MACRO_TMPL%%".format(_clean_name(name), "dist_info") From c20aa1a3f5756a3860d6f6b595464edbf7964ea4 Mon Sep 17 00:00:00 2001 From: Wei <56273788+yuanweixin@users.noreply.github.com> Date: Mon, 1 May 2023 15:10:37 -0400 Subject: [PATCH 223/234] type:docs Update README.md (#1186) Change instruction to refer to `MODULE.bazel` instead of `MODULES.bazel`. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 089837de7d..a095a352c1 100644 --- a/README.md +++ b/README.md @@ -39,12 +39,12 @@ the older way of configuring bazel with a `WORKSPACE` file. ### Using bzlmod To import rules_python in your project, you first need to add it to your -`MODULES.bazel` file, using the snippet provided in the +`MODULE.bazel` file, using the snippet provided in the [release you choose](https://github.com/bazelbuild/rules_python/releases). #### Toolchain registration with bzlmod -To register a hermetic Python toolchain rather than rely on a system-installed interpreter for runtime execution, you can add to the `MODULES.bazel` file: +To register a hermetic Python toolchain rather than rely on a system-installed interpreter for runtime execution, you can add to the `MODULE.bazel` file: ```python # Find the latest version number here: https://github.com/bazelbuild/rules_python/releases @@ -161,7 +161,7 @@ target in the appropriate wheel repo. #### Using bzlmod -To add pip dependencies to your `MODULES.bazel` file, use the `pip.parse` extension, and call it to create the +To add pip dependencies to your `MODULE.bazel` file, use the `pip.parse` extension, and call it to create the central external repo and individual wheel external repos. ```python From 2df3259c8e9c5f9dd538207166cdc67b1fcf4877 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Tue, 2 May 2023 09:38:02 -0700 Subject: [PATCH 224/234] fix: Allow passing a tuple to the `tags` attribute. (#1191) Starlark rules allow giving the tags as a tuple. The helper function that added the special migration tag assumed tags was always a list, resulting in an error when it tried to concatenate a list and tuple. To fix, check if tags is a tuple and concatenate a tuple if so. The input type of the tags attribute is preserved so that a test verifying tags can be passed to the underlying rule can be implemented (this test is to verify there isn't a regression during the rewrite to Starlark). --- docs/BUILD.bazel | 3 +++ python/private/BUILD.bazel | 6 ++++- python/private/util.bzl | 19 +++++++++++++++- tools/build_defs/python/tests/base_tests.bzl | 23 +++++++++++++++++++- 4 files changed, 48 insertions(+), 3 deletions(-) diff --git a/docs/BUILD.bazel b/docs/BUILD.bazel index 27af3e7ed5..938ba85dd5 100644 --- a/docs/BUILD.bazel +++ b/docs/BUILD.bazel @@ -80,6 +80,9 @@ bzl_library( "//python/private:stamp.bzl", "//python/private:util.bzl", ], + deps = [ + "//python/private:util_bzl", + ], ) # TODO: Stardoc does not guarantee consistent outputs accross platforms (Unix/Windows). diff --git a/python/private/BUILD.bazel b/python/private/BUILD.bazel index 4068ea480b..f454f42cf3 100644 --- a/python/private/BUILD.bazel +++ b/python/private/BUILD.bazel @@ -44,7 +44,11 @@ bzl_library( bzl_library( name = "util_bzl", srcs = ["util.bzl"], - visibility = ["//python:__subpackages__"], + visibility = [ + "//docs:__subpackages__", + "//python:__subpackages__", + ], + deps = ["@bazel_skylib//lib:types"], ) # @bazel_tools can't define bzl_library itself, so we just put a wrapper around it. diff --git a/python/private/util.bzl b/python/private/util.bzl index 25a50aac6a..f0d43737a0 100644 --- a/python/private/util.bzl +++ b/python/private/util.bzl @@ -1,5 +1,7 @@ """Functionality shared by multiple pieces of code.""" +load("@bazel_skylib//lib:types.bzl", "types") + def copy_propagating_kwargs(from_kwargs, into_kwargs = None): """Copies args that must be compatible between two targets with a dependency relationship. @@ -36,8 +38,23 @@ def copy_propagating_kwargs(from_kwargs, into_kwargs = None): _MIGRATION_TAG = "__PYTHON_RULES_MIGRATION_DO_NOT_USE_WILL_BREAK__" def add_migration_tag(attrs): + """Add a special tag to `attrs` to aid migration off native rles. + + Args: + attrs: dict of keyword args. The `tags` key will be modified in-place. + + Returns: + The same `attrs` object, but modified. + """ if "tags" in attrs and attrs["tags"] != None: - attrs["tags"] = attrs["tags"] + [_MIGRATION_TAG] + tags = attrs["tags"] + + # Preserve the input type: this allows a test verifying the underlying + # rule can accept the tuple for the tags argument. + if types.is_tuple(tags): + attrs["tags"] = tags + (_MIGRATION_TAG,) + else: + attrs["tags"] = tags + [_MIGRATION_TAG] else: attrs["tags"] = [_MIGRATION_TAG] return attrs diff --git a/tools/build_defs/python/tests/base_tests.bzl b/tools/build_defs/python/tests/base_tests.bzl index 715aea7fde..467611fcd8 100644 --- a/tools/build_defs/python/tests/base_tests.bzl +++ b/tools/build_defs/python/tests/base_tests.bzl @@ -15,7 +15,7 @@ load("@rules_testing//lib:analysis_test.bzl", "analysis_test") load("@rules_testing//lib:truth.bzl", "matching") -load("@rules_testing//lib:util.bzl", rt_util = "util") +load("@rules_testing//lib:util.bzl", "PREVENT_IMPLICIT_BUILDING_TAGS", rt_util = "util") load("//python:defs.bzl", "PyInfo") load("//tools/build_defs/python/tests:py_info_subject.bzl", "py_info_subject") load("//tools/build_defs/python/tests:util.bzl", pt_util = "util") @@ -99,5 +99,26 @@ def _test_data_sets_uses_shared_library_impl(env, target): _tests.append(_test_data_sets_uses_shared_library) +def _test_tags_can_be_tuple(name, config): + # We don't use a helper because we want to ensure that value passed is + # a tuple. + config.base_test_rule( + name = name + "_subject", + tags = ("one", "two") + tuple(PREVENT_IMPLICIT_BUILDING_TAGS), + ) + analysis_test( + name = name, + target = name + "_subject", + impl = _test_tags_can_be_tuple_impl, + ) + +def _test_tags_can_be_tuple_impl(env, target): + env.expect.that_target(target).tags().contains_at_least([ + "one", + "two", + ]) + +_tests.append(_test_tags_can_be_tuple) + def create_base_tests(config): return pt_util.create_tests(_tests, config = config) From 81a200be35ff62cd3b50c44968381b99aa4cd1cc Mon Sep 17 00:00:00 2001 From: Chris Love <335402+chrislovecnm@users.noreply.github.com> Date: Wed, 3 May 2023 12:52:28 -0600 Subject: [PATCH 225/234] tests: Add skylib to various test dependencies to fix CI (#1199) This fixes a problem where bazel skylib does not load during the toolchain integration test. The skylib dependency was introduced by #1191, but skylib was not present in the WORKSPACE configs of several things. To fix, skylib just needs to be added to the workspace files. --- internal_deps.bzl | 3 +++ .../toolchains/workspace_template/WORKSPACE.tmpl | 12 ++++++++++++ tests/ignore_root_user_error/WORKSPACE | 15 +++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/internal_deps.bzl b/internal_deps.bzl index 86a53b25e7..e4d2f69d41 100644 --- a/internal_deps.bzl +++ b/internal_deps.bzl @@ -20,6 +20,9 @@ load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") def rules_python_internal_deps(): """Fetches all required dependencies for rules_python tests and tools.""" + # This version is also used in python/tests/toolchains/workspace_template/WORKSPACE.tmpl + # and tests/ignore_root_user_error/WORKSPACE. + # If you update this dependency, please update the tests as well. maybe( http_archive, name = "bazel_skylib", diff --git a/python/tests/toolchains/workspace_template/WORKSPACE.tmpl b/python/tests/toolchains/workspace_template/WORKSPACE.tmpl index d0aa700928..973e020c1e 100644 --- a/python/tests/toolchains/workspace_template/WORKSPACE.tmpl +++ b/python/tests/toolchains/workspace_template/WORKSPACE.tmpl @@ -25,3 +25,15 @@ python_register_toolchains( name = "python", python_version = "%python_version%", ) + +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +http_archive( + name = "bazel_skylib", + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", + "https://github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", + ], + sha256 = "c6966ec828da198c5d9adbaa94c05e3a1c7f21bd012a0b29ba8ddbccb2c93b0d", +) +load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") +bazel_skylib_workspace() diff --git a/tests/ignore_root_user_error/WORKSPACE b/tests/ignore_root_user_error/WORKSPACE index d2f4d6ec3a..e0528e4047 100644 --- a/tests/ignore_root_user_error/WORKSPACE +++ b/tests/ignore_root_user_error/WORKSPACE @@ -10,3 +10,18 @@ python_register_toolchains( ignore_root_user_error = True, python_version = "3.9", ) + +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +http_archive( + name = "bazel_skylib", + sha256 = "c6966ec828da198c5d9adbaa94c05e3a1c7f21bd012a0b29ba8ddbccb2c93b0d", + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", + "https://github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz", + ], +) + +load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") + +bazel_skylib_workspace() From 96b4fa13b9dfcf32422455931621598eb99d28f5 Mon Sep 17 00:00:00 2001 From: Chris Love <335402+chrislovecnm@users.noreply.github.com> Date: Wed, 3 May 2023 14:56:31 -0600 Subject: [PATCH 226/234] feat: removing bzlmod from example (#1200) Having both bzlmod and a WORKSPACE file confuses the user, and I have #1155 which adds a new example for gazelle and bzlmod. --- .bazelci/presubmit.yml | 26 ----------- examples/build_file_generation/MODULE.bazel | 43 ------------------- .../build_file_generation/WORKSPACE.bzlmod | 2 - 3 files changed, 71 deletions(-) delete mode 100644 examples/build_file_generation/MODULE.bazel delete mode 100644 examples/build_file_generation/WORKSPACE.bzlmod diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 7b5ba8b2f2..8ad04894d9 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -147,32 +147,6 @@ tasks: working_directory: examples/build_file_generation platform: windows - integration_test_build_file_generation_bzlmod_ubuntu: - <<: *minimum_supported_bzlmod_version - <<: *common_bzlmod_flags - <<: *reusable_build_test_all - name: build_file_generation_bzlmod integration tests on Ubuntu - working_directory: examples/build_file_generation - platform: ubuntu2004 - integration_test_build_file_generation_bzlmod_debian: - <<: *common_bzlmod_flags - <<: *reusable_build_test_all - name: build_file_generation_bzlmod integration tests on Debian - working_directory: examples/build_file_generation - platform: debian11 - integration_test_build_file_generation_bzlmod_macos: - <<: *common_bzlmod_flags - <<: *reusable_build_test_all - name: build_file_generation_bzlmod integration tests on macOS - working_directory: examples/build_file_generation - platform: macos - integration_test_build_file_generation_bzlmod_windows: - <<: *common_bzlmod_flags - <<: *reusable_build_test_all - name: build_file_generation_bzlmod integration tests on Windows - working_directory: examples/build_file_generation - platform: windows - integration_test_bzlmod_ubuntu_min: <<: *minimum_supported_bzlmod_version <<: *reusable_build_test_all diff --git a/examples/build_file_generation/MODULE.bazel b/examples/build_file_generation/MODULE.bazel deleted file mode 100644 index 5f79fec486..0000000000 --- a/examples/build_file_generation/MODULE.bazel +++ /dev/null @@ -1,43 +0,0 @@ -module( - name = "example_bzlmod", - version = "0.0.0", - compatibility_level = 1, -) - -bazel_dep(name = "rules_python", version = "0.19.0") -bazel_dep(name = "rules_python_gazelle_plugin", version = "0.19.0") -bazel_dep(name = "gazelle", version = "0.29.0", repo_name = "bazel_gazelle") - -# local overrides for the packages for CI purposes. -# for usual setups you should remove this block. -local_path_override( - module_name = "rules_python", - path = "../..", -) - -local_path_override( - module_name = "rules_python_gazelle_plugin", - path = "../../gazelle", -) - -# Register python toolchain -python = use_extension("@rules_python//python:extensions.bzl", "python") -python.toolchain( - name = "python3_9", - python_version = "3.9", -) -use_repo(python, "python3_9_toolchains") - -register_toolchains( - "@python3_9_toolchains//:all", -) - -pip = use_extension("@rules_python//python:extensions.bzl", "pip") -pip.parse( - name = "pip", - # Generate user friendly alias labels for each dependency that we have. - incompatible_generate_aliases = True, - requirements_lock = "//:requirements_lock.txt", - requirements_windows = "//:requirements_windows.txt", -) -use_repo(pip, "pip") diff --git a/examples/build_file_generation/WORKSPACE.bzlmod b/examples/build_file_generation/WORKSPACE.bzlmod deleted file mode 100644 index 721e065154..0000000000 --- a/examples/build_file_generation/WORKSPACE.bzlmod +++ /dev/null @@ -1,2 +0,0 @@ -# This file will be used when bzlmod is enabled, keep it empty -# to ensure that all of the setup is done in MODULE.bazel From e40079186ddd403cbad6a0e951363d1c5bf9238a Mon Sep 17 00:00:00 2001 From: Chris Love <335402+chrislovecnm@users.noreply.github.com> Date: Wed, 3 May 2023 15:01:31 -0600 Subject: [PATCH 227/234] feat: propagate visibility attribute for py_wheel publishing (#1203) py_wheel does not propagate "visibility" attribute to the "publish" rule. The visibility attribute on py_wheel target is not propagated to the auto-generated "publish" target. This commit adds the visibility attribute. Closes: https://github.com/bazelbuild/rules_python/issues/1192 --- python/packaging.bzl | 1 + 1 file changed, 1 insertion(+) diff --git a/python/packaging.bzl b/python/packaging.bzl index fffd239c15..45d5c963b9 100644 --- a/python/packaging.bzl +++ b/python/packaging.bzl @@ -172,6 +172,7 @@ def py_wheel(name, twine = None, **kwargs): imports = ["."], main = twine_main, deps = [twine], + visibility = kwargs.get("visibility"), ) py_wheel_rule = _py_wheel From fc94642ed05a1f3a851487f9bce84e5f5317c926 Mon Sep 17 00:00:00 2001 From: Martin Medler <36563496+martis42@users.noreply.github.com> Date: Wed, 3 May 2023 23:30:24 +0200 Subject: [PATCH 228/234] docs: fix typos in pip_repository docs (#1202) --- docs/pip_repository.md | 4 ++-- python/pip_install/pip_repository.bzl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/pip_repository.md b/docs/pip_repository.md index c02058e08d..99af4bac81 100644 --- a/docs/pip_repository.md +++ b/docs/pip_repository.md @@ -66,7 +66,7 @@ py_binary( | environment | Environment variables to set in the pip subprocess. Can be used to set common variables such as http_proxy, https_proxy and no_proxy Note that pip is run with "--isolated" on the CLI so PIP_<VAR>_<NAME> style env vars are ignored, but env vars that control requests and urllib3 can be passed. | Dictionary: String -> String | optional | {} | | extra_pip_args | Extra arguments to pass on to pip. Must not contain spaces. | List of strings | optional | [] | | incompatible_generate_aliases | Allow generating aliases '@pip//<pkg>' -> '@pip_<pkg>//:pkg'. | Boolean | optional | False | -| isolated | Whether or not to pass the [--isolated](https://pip.pypa.io/en/stable/cli/pip/#cmdoption-isolated) flag to the underlying pip command. Alternatively, the RULES_PYTHON_PIP_ISOLATED enviornment varaible can be used to control this flag. | Boolean | optional | True | +| isolated | Whether or not to pass the [--isolated](https://pip.pypa.io/en/stable/cli/pip/#cmdoption-isolated) flag to the underlying pip command. Alternatively, the RULES_PYTHON_PIP_ISOLATED environment variable can be used to control this flag. | Boolean | optional | True | | pip_data_exclude | Additional data exclusion parameters to add to the pip packages BUILD file. | List of strings | optional | [] | | python_interpreter | The python interpreter to use. This can either be an absolute path or the name of a binary found on the host's PATH environment variable. If no value is set python3 is defaulted for Unix systems and python.exe for Windows. | String | optional | "" | | python_interpreter_target | If you are using a custom python interpreter built by another repository rule, use this attribute to specify its BUILD target. This allows pip_repository to invoke pip using the same interpreter as your toolchain. If set, takes precedence over python_interpreter. | Label | optional | None | @@ -130,7 +130,7 @@ Instantiated from pip_repository and inherits config options from there. | enable_implicit_namespace_pkgs | If true, disables conversion of native namespace packages into pkg-util style namespace packages. When set all py_binary and py_test targets must specify either legacy_create_init=False or the global Bazel option --incompatible_default_to_explicit_init_py to prevent __init__.py being automatically generated in every directory.

This option is required to support some packages which cannot handle the conversion to pkg-util style. | Boolean | optional | False | | environment | Environment variables to set in the pip subprocess. Can be used to set common variables such as http_proxy, https_proxy and no_proxy Note that pip is run with "--isolated" on the CLI so PIP_<VAR>_<NAME> style env vars are ignored, but env vars that control requests and urllib3 can be passed. | Dictionary: String -> String | optional | {} | | extra_pip_args | Extra arguments to pass on to pip. Must not contain spaces. | List of strings | optional | [] | -| isolated | Whether or not to pass the [--isolated](https://pip.pypa.io/en/stable/cli/pip/#cmdoption-isolated) flag to the underlying pip command. Alternatively, the RULES_PYTHON_PIP_ISOLATED enviornment varaible can be used to control this flag. | Boolean | optional | True | +| isolated | Whether or not to pass the [--isolated](https://pip.pypa.io/en/stable/cli/pip/#cmdoption-isolated) flag to the underlying pip command. Alternatively, the RULES_PYTHON_PIP_ISOLATED environment variable can be used to control this flag. | Boolean | optional | True | | pip_data_exclude | Additional data exclusion parameters to add to the pip packages BUILD file. | List of strings | optional | [] | | python_interpreter | The python interpreter to use. This can either be an absolute path or the name of a binary found on the host's PATH environment variable. If no value is set python3 is defaulted for Unix systems and python.exe for Windows. | String | optional | "" | | python_interpreter_target | If you are using a custom python interpreter built by another repository rule, use this attribute to specify its BUILD target. This allows pip_repository to invoke pip using the same interpreter as your toolchain. If set, takes precedence over python_interpreter. | Label | optional | None | diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl index 1ea7bca88a..f58c2afddb 100644 --- a/python/pip_install/pip_repository.bzl +++ b/python/pip_install/pip_repository.bzl @@ -536,7 +536,7 @@ can be passed. "isolated": attr.bool( doc = """\ Whether or not to pass the [--isolated](https://pip.pypa.io/en/stable/cli/pip/#cmdoption-isolated) flag to -the underlying pip command. Alternatively, the `RULES_PYTHON_PIP_ISOLATED` enviornment varaible can be used +the underlying pip command. Alternatively, the `RULES_PYTHON_PIP_ISOLATED` environment variable can be used to control this flag. """, default = True, From 532f07a9930ef8d218b7415e373e31dc2006d75c Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Wed, 3 May 2023 15:02:32 -0700 Subject: [PATCH 229/234] tests: Force analysis test labels to resolve within @rules_python context (#1187) When a string label is passed to the `@rules_testing` analysis_test functions, the strings are evaluated within the context of @rules_testing because that is where the actual rule invocation happens. Without bzlmod, this just requires qualifying the labels with the repo name (which is what was being done) because there's just a flat global namespace of repos. With bzlmod enabled, repo mapping happens, so rules_testing tries to resolve those repo names using its repo mapping, which doesn't work because rules_testing's mapping doesn't include every repo using it. --- .../python/tests/py_test/py_test_tests.bzl | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tools/build_defs/python/tests/py_test/py_test_tests.bzl b/tools/build_defs/python/tests/py_test/py_test_tests.bzl index 560883200a..8bb2fc2af0 100644 --- a/tools/build_defs/python/tests/py_test/py_test_tests.bzl +++ b/tools/build_defs/python/tests/py_test/py_test_tests.bzl @@ -22,6 +22,12 @@ load( ) load("//tools/build_defs/python/tests:util.bzl", pt_util = "util") +# Explicit Label() calls are required so that it resolves in @rules_python context instead of +# @rules_testing context. +_FAKE_CC_TOOLCHAIN = Label("//tools/build_defs/python/tests:cc_toolchain_suite") +_PLATFORM_MAC = Label("//tools/build_defs/python/tests:mac") +_PLATFORM_LINUX = Label("//tools/build_defs/python/tests:linux") + _tests = [] def _test_mac_requires_darwin_for_execution(name, config): @@ -44,8 +50,8 @@ def _test_mac_requires_darwin_for_execution(name, config): target = name + "_subject", config_settings = { "//command_line_option:cpu": "darwin_x86_64", - "//command_line_option:crosstool_top": "@rules_python//tools/build_defs/python/tests:cc_toolchain_suite", - "//command_line_option:platforms": "@rules_python//tools/build_defs/python/tests:mac", + "//command_line_option:crosstool_top": _FAKE_CC_TOOLCHAIN, + "//command_line_option:platforms": [_PLATFORM_MAC], }, ) @@ -75,8 +81,8 @@ def _test_non_mac_doesnt_require_darwin_for_execution(name, config): target = name + "_subject", config_settings = { "//command_line_option:cpu": "k8", - "//command_line_option:crosstool_top": "@rules_python//tools/build_defs/python/tests:cc_toolchain_suite", - "//command_line_option:platforms": "@rules_python//tools/build_defs/python/tests:linux", + "//command_line_option:crosstool_top": _FAKE_CC_TOOLCHAIN, + "//command_line_option:platforms": [_PLATFORM_LINUX], }, ) From 262c699f71c65bb778a15ba992bca091a851e35b Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius Date: Fri, 5 May 2023 02:36:34 +0900 Subject: [PATCH 230/234] fix(update_deleted_packages.sh): allow to run from anywhere in the repo (#1206) It seems that the tool was correctly trying to modify the `.bazelrc` at the root of the repo, but the `find` execution would run in the `$PWD`. This change ensures that the `find` is consistent with the file we are trying to modify and allows the user to execute the script from anywhere in the repo. Tested: 1. Update the deleted packages with the version of the script at HEAD 1. Fix the bug 1. Rerun the script from the 'tests' sub-folder in the repo to ensure that running the script is noop. 1. Revert the changes to '.bazelrc' to reduce conflicts as other PRs are modifying it. Work towards #958. --- tools/bazel_integration_test/update_deleted_packages.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/bazel_integration_test/update_deleted_packages.sh b/tools/bazel_integration_test/update_deleted_packages.sh index ce7b05ada7..e21f88706a 100755 --- a/tools/bazel_integration_test/update_deleted_packages.sh +++ b/tools/bazel_integration_test/update_deleted_packages.sh @@ -16,9 +16,11 @@ # For integration tests, we want to be able to glob() up the sources inside a nested package # See explanation in .bazelrc -set -eux +set -euxo pipefail DIR="$(dirname $0)/../.." +cd $DIR + # The sed -i.bak pattern is compatible between macos and linux sed -i.bak "/^[^#].*--deleted_packages/s#=.*#=$(\ find examples/*/* tests/*/* \( -name BUILD -or -name BUILD.bazel \) | xargs -n 1 dirname | paste -sd, -\ From 0912bba35d0f3e341c7beae206b21e9ca5b8322e Mon Sep 17 00:00:00 2001 From: Chris Love <335402+chrislovecnm@users.noreply.github.com> Date: Thu, 4 May 2023 14:08:34 -0600 Subject: [PATCH 231/234] feat(bzlmod): expose platform-agnostic repo target for toolchain interpreter (#1155) This exposes a new repo and target, `@{name}_host_interpreter//:python`, created by `python.toolchain()`, that points to the host OS's Python interpreter for that particular toolchain. This solves two problems: 1. `pip.parse()` can now refer to the same interpreter used in the toolchains 2. There is now a canonical, public, way to refer to the host OS Python interpreter for repository rules. The above were _sort of_ possible for users to do already, but it required them to write much more configuration and extension code to do so. This moves that sort of boilerplate into our code so they have a simpler configuration. Also: - removing bzlmod support in the build_file_generation example; making examples work with both WORKSPACE and MODULE is a pain, hence splitting them. - adding an example of bzlmod and gazelle - improved documentation in the pip arguments Closes: https://github.com/bazelbuild/rules_python/issues/1161 --- .bazelci/presubmit.yml | 42 ++ .bazelrc | 4 +- docs/pip_repository.md | 4 +- examples/BUILD.bazel | 5 + examples/build_file_generation/.bazelrc | 2 +- examples/bzlmod/gazelle_python.yaml | 590 ++++++++++++++++++ examples/bzlmod/runfiles/BUILD.bazel | 1 + .../bzlmod_build_file_generation/.bazelignore | 1 + .../bzlmod_build_file_generation/.bazelrc | 9 + .../.bazelversion | 1 + .../bzlmod_build_file_generation/.gitignore | 1 + .../bzlmod_build_file_generation/BUILD.bazel | 103 +++ .../bzlmod_build_file_generation/MODULE.bazel | 113 ++++ .../bzlmod_build_file_generation/README.md | 28 + .../bzlmod_build_file_generation/WORKSPACE | 2 + .../bzlmod_build_file_generation/__main__.py | 18 + .../bzlmod_build_file_generation/__test__.py | 33 + .../gazelle_python.yaml | 590 ++++++++++++++++++ examples/bzlmod_build_file_generation/lib.py | 19 + .../other_module/MODULE.bazel | 5 + .../other_module/WORKSPACE | 0 .../other_module/other_module/pkg/BUILD.bazel | 11 + .../other_module/pkg/data/data.txt | 1 + .../other_module/other_module/pkg/lib.py | 27 + .../requirements.in | 6 + .../requirements_lock.txt | 227 +++++++ .../requirements_windows.txt | 231 +++++++ .../runfiles/BUILD.bazel | 19 + .../runfiles/data/data.txt | 1 + .../runfiles/runfiles_test.py | 64 ++ gazelle/README.md | 43 +- python/extensions.bzl | 102 ++- python/pip_install/pip_repository.bzl | 2 +- 33 files changed, 2288 insertions(+), 17 deletions(-) create mode 100644 examples/bzlmod/gazelle_python.yaml create mode 100644 examples/bzlmod_build_file_generation/.bazelignore create mode 100644 examples/bzlmod_build_file_generation/.bazelrc create mode 100644 examples/bzlmod_build_file_generation/.bazelversion create mode 100644 examples/bzlmod_build_file_generation/.gitignore create mode 100644 examples/bzlmod_build_file_generation/BUILD.bazel create mode 100644 examples/bzlmod_build_file_generation/MODULE.bazel create mode 100644 examples/bzlmod_build_file_generation/README.md create mode 100644 examples/bzlmod_build_file_generation/WORKSPACE create mode 100644 examples/bzlmod_build_file_generation/__main__.py create mode 100644 examples/bzlmod_build_file_generation/__test__.py create mode 100644 examples/bzlmod_build_file_generation/gazelle_python.yaml create mode 100644 examples/bzlmod_build_file_generation/lib.py create mode 100644 examples/bzlmod_build_file_generation/other_module/MODULE.bazel create mode 100644 examples/bzlmod_build_file_generation/other_module/WORKSPACE create mode 100644 examples/bzlmod_build_file_generation/other_module/other_module/pkg/BUILD.bazel create mode 100644 examples/bzlmod_build_file_generation/other_module/other_module/pkg/data/data.txt create mode 100644 examples/bzlmod_build_file_generation/other_module/other_module/pkg/lib.py create mode 100644 examples/bzlmod_build_file_generation/requirements.in create mode 100644 examples/bzlmod_build_file_generation/requirements_lock.txt create mode 100644 examples/bzlmod_build_file_generation/requirements_windows.txt create mode 100644 examples/bzlmod_build_file_generation/runfiles/BUILD.bazel create mode 100644 examples/bzlmod_build_file_generation/runfiles/data/data.txt create mode 100644 examples/bzlmod_build_file_generation/runfiles/runfiles_test.py diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 8ad04894d9..b468970fbb 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -48,6 +48,8 @@ buildifier: test_targets: ["..."] .coverage_targets_example_bzlmod: &coverage_targets_example_bzlmod coverage_targets: ["//:test"] +.coverage_targets_example_bzlmod_build_file_generation: &coverage_targets_example_bzlmod_build_file_generation + coverage_targets: ["//:bzlmod_build_file_generation_test"] .coverage_targets_example_multi_python: &coverage_targets_example_multi_python coverage_targets: - //tests:my_lib_3_10_test @@ -179,6 +181,46 @@ tasks: working_directory: examples/bzlmod platform: windows + integration_test_bzlmod_generate_build_file_generation_ubuntu_min: + <<: *minimum_supported_bzlmod_version + <<: *reusable_build_test_all + <<: *coverage_targets_example_bzlmod_build_file_generation + name: example bzlmod build file min bazel version integration test + working_directory: examples/bzlmod_build_file_generation + platform: ubuntu2004 + integration_test_bzlmod_generation_build_files_ubuntu: + <<: *reusable_build_test_all + <<: *coverage_targets_example_bzlmod_build_file_generation + name: example bzlmod build file integration test + working_directory: examples/bzlmod_build_file_generation + platform: ubuntu2004 + integration_test_bzlmod_generation_build_files_ubuntu_run: + <<: *reusable_build_test_all + name: example bzlmod build file running gazelle and pip integration test + working_directory: examples/bzlmod_build_file_generation + platform: ubuntu2004 + shell_commands: + - "bazel run //:gazelle_python_manifest.update" + - "bazel run //:gazelle -- update" + integration_test_bzlmod_build_file_generation_debian: + <<: *reusable_build_test_all + <<: *coverage_targets_example_bzlmod_build_file_generation + name: example bzlmod build file integration test + working_directory: examples/bzlmod_build_file_generation + platform: debian11 + integration_test_bzlmod_build_file_generation_macos: + <<: *reusable_build_test_all + <<: *coverage_targets_example_bzlmod_build_file_generation + name: example bzlmod build file integration test + working_directory: examples/bzlmod_build_file_generation + platform: macos + integration_test_bzlmod_build_file_generation_windows: + <<: *reusable_build_test_all + # coverage is not supported on Windows + name: example bzlmod build file integration test + working_directory: examples/bzlmod_build_file_generation + platform: windows + integration_test_multi_python_versions_ubuntu_min: <<: *minimum_supported_version <<: *reusable_build_test_all diff --git a/.bazelrc b/.bazelrc index d607cdd9b7..e7e4af7bbd 100644 --- a/.bazelrc +++ b/.bazelrc @@ -3,8 +3,8 @@ # This lets us glob() up all the files inside the examples to make them inputs to tests # (Note, we cannot use `common --deleted_packages` because the bazel version command doesn't support it) # To update these lines, run tools/bazel_integration_test/update_deleted_packages.sh -build --deleted_packages=examples/build_file_generation,examples/build_file_generation/get_url,examples/bzlmod,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/runfiles,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/py_proto_library,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps -query --deleted_packages=examples/build_file_generation,examples/build_file_generation/get_url,examples/bzlmod,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/runfiles,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/py_proto_library,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps +build --deleted_packages=examples/build_file_generation,examples/build_file_generation/get_url,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/bzlmod,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/runfiles,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/py_proto_library,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps +query --deleted_packages=examples/build_file_generation,examples/build_file_generation/get_url,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/bzlmod,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/runfiles,examples/multi_python_versions,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_install,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_import,examples/py_proto_library,examples/relative_requirements,tests/compile_pip_requirements,tests/pip_repository_entry_points,tests/pip_deps test --test_output=errors diff --git a/docs/pip_repository.md b/docs/pip_repository.md index 99af4bac81..29cb3d9c32 100644 --- a/docs/pip_repository.md +++ b/docs/pip_repository.md @@ -69,7 +69,7 @@ py_binary( | isolated | Whether or not to pass the [--isolated](https://pip.pypa.io/en/stable/cli/pip/#cmdoption-isolated) flag to the underlying pip command. Alternatively, the RULES_PYTHON_PIP_ISOLATED environment variable can be used to control this flag. | Boolean | optional | True | | pip_data_exclude | Additional data exclusion parameters to add to the pip packages BUILD file. | List of strings | optional | [] | | python_interpreter | The python interpreter to use. This can either be an absolute path or the name of a binary found on the host's PATH environment variable. If no value is set python3 is defaulted for Unix systems and python.exe for Windows. | String | optional | "" | -| python_interpreter_target | If you are using a custom python interpreter built by another repository rule, use this attribute to specify its BUILD target. This allows pip_repository to invoke pip using the same interpreter as your toolchain. If set, takes precedence over python_interpreter. | Label | optional | None | +| python_interpreter_target | If you are using a custom python interpreter built by another repository rule, use this attribute to specify its BUILD target. This allows pip_repository to invoke pip using the same interpreter as your toolchain. If set, takes precedence over python_interpreter. An example value: "@python3_x86_64-unknown-linux-gnu//:python". | Label | optional | None | | quiet | If True, suppress printing stdout and stderr output to the terminal. | Boolean | optional | True | | repo_mapping | A dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.<p>For example, an entry "@foo": "@bar" declares that, for any time this repository depends on @foo (such as a dependency on @foo//some:target, it should actually resolve that dependency within globally-declared @bar (@bar//some:target). | Dictionary: String -> String | required | | | repo_prefix | Prefix for the generated packages will be of the form @<prefix><sanitized-package-name>//... | String | optional | "" | @@ -133,7 +133,7 @@ Instantiated from pip_repository and inherits config options from there. | isolated | Whether or not to pass the [--isolated](https://pip.pypa.io/en/stable/cli/pip/#cmdoption-isolated) flag to the underlying pip command. Alternatively, the RULES_PYTHON_PIP_ISOLATED environment variable can be used to control this flag. | Boolean | optional | True | | pip_data_exclude | Additional data exclusion parameters to add to the pip packages BUILD file. | List of strings | optional | [] | | python_interpreter | The python interpreter to use. This can either be an absolute path or the name of a binary found on the host's PATH environment variable. If no value is set python3 is defaulted for Unix systems and python.exe for Windows. | String | optional | "" | -| python_interpreter_target | If you are using a custom python interpreter built by another repository rule, use this attribute to specify its BUILD target. This allows pip_repository to invoke pip using the same interpreter as your toolchain. If set, takes precedence over python_interpreter. | Label | optional | None | +| python_interpreter_target | If you are using a custom python interpreter built by another repository rule, use this attribute to specify its BUILD target. This allows pip_repository to invoke pip using the same interpreter as your toolchain. If set, takes precedence over python_interpreter. An example value: "@python3_x86_64-unknown-linux-gnu//:python". | Label | optional | None | | quiet | If True, suppress printing stdout and stderr output to the terminal. | Boolean | optional | True | | repo | Pointer to parent repo name. Used to make these rules rerun if the parent repo changes. | String | required | | | repo_mapping | A dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.<p>For example, an entry "@foo": "@bar" declares that, for any time this repository depends on @foo (such as a dependency on @foo//some:target, it should actually resolve that dependency within globally-declared @bar (@bar//some:target). | Dictionary: String -> String | required | | diff --git a/examples/BUILD.bazel b/examples/BUILD.bazel index 3ef89054c9..feb1cfbd4e 100644 --- a/examples/BUILD.bazel +++ b/examples/BUILD.bazel @@ -22,6 +22,11 @@ bazel_integration_test( timeout = "long", ) +bazel_integration_test( + name = "bzlmod_build_file_generation_example", + timeout = "long", +) + bazel_integration_test( name = "pip_install_example", timeout = "long", diff --git a/examples/build_file_generation/.bazelrc b/examples/build_file_generation/.bazelrc index f23315a7a1..28f634bef6 100644 --- a/examples/build_file_generation/.bazelrc +++ b/examples/build_file_generation/.bazelrc @@ -1,4 +1,4 @@ -test --test_output=errors +test --test_output=errors --enable_runfiles # Windows requires these for multi-python support: build --enable_runfiles diff --git a/examples/bzlmod/gazelle_python.yaml b/examples/bzlmod/gazelle_python.yaml new file mode 100644 index 0000000000..12096e5837 --- /dev/null +++ b/examples/bzlmod/gazelle_python.yaml @@ -0,0 +1,590 @@ +# GENERATED FILE - DO NOT EDIT! +# +# To update this file, run: +# bazel run //:gazelle_python_manifest.update + +manifest: + modules_mapping: + S3: s3cmd + S3.ACL: s3cmd + S3.AccessLog: s3cmd + S3.BidirMap: s3cmd + S3.CloudFront: s3cmd + S3.Config: s3cmd + S3.ConnMan: s3cmd + S3.Crypto: s3cmd + S3.Custom_httplib27: s3cmd + S3.Custom_httplib3x: s3cmd + S3.Exceptions: s3cmd + S3.ExitCodes: s3cmd + S3.FileDict: s3cmd + S3.FileLists: s3cmd + S3.HashCache: s3cmd + S3.MultiPart: s3cmd + S3.PkgInfo: s3cmd + S3.Progress: s3cmd + S3.S3: s3cmd + S3.S3Uri: s3cmd + S3.SortedDict: s3cmd + S3.Utils: s3cmd + astroid: astroid + astroid.arguments: astroid + astroid.astroid_manager: astroid + astroid.bases: astroid + astroid.brain: astroid + astroid.brain.brain_argparse: astroid + astroid.brain.brain_attrs: astroid + astroid.brain.brain_boto3: astroid + astroid.brain.brain_builtin_inference: astroid + astroid.brain.brain_collections: astroid + astroid.brain.brain_crypt: astroid + astroid.brain.brain_ctypes: astroid + astroid.brain.brain_curses: astroid + astroid.brain.brain_dataclasses: astroid + astroid.brain.brain_dateutil: astroid + astroid.brain.brain_fstrings: astroid + astroid.brain.brain_functools: astroid + astroid.brain.brain_gi: astroid + astroid.brain.brain_hashlib: astroid + astroid.brain.brain_http: astroid + astroid.brain.brain_hypothesis: astroid + astroid.brain.brain_io: astroid + astroid.brain.brain_mechanize: astroid + astroid.brain.brain_multiprocessing: astroid + astroid.brain.brain_namedtuple_enum: astroid + astroid.brain.brain_nose: astroid + astroid.brain.brain_numpy_core_einsumfunc: astroid + astroid.brain.brain_numpy_core_fromnumeric: astroid + astroid.brain.brain_numpy_core_function_base: astroid + astroid.brain.brain_numpy_core_multiarray: astroid + astroid.brain.brain_numpy_core_numeric: astroid + astroid.brain.brain_numpy_core_numerictypes: astroid + astroid.brain.brain_numpy_core_umath: astroid + astroid.brain.brain_numpy_ma: astroid + astroid.brain.brain_numpy_ndarray: astroid + astroid.brain.brain_numpy_random_mtrand: astroid + astroid.brain.brain_numpy_utils: astroid + astroid.brain.brain_pathlib: astroid + astroid.brain.brain_pkg_resources: astroid + astroid.brain.brain_pytest: astroid + astroid.brain.brain_qt: astroid + astroid.brain.brain_random: astroid + astroid.brain.brain_re: astroid + astroid.brain.brain_responses: astroid + astroid.brain.brain_scipy_signal: astroid + astroid.brain.brain_signal: astroid + astroid.brain.brain_six: astroid + astroid.brain.brain_sqlalchemy: astroid + astroid.brain.brain_ssl: astroid + astroid.brain.brain_subprocess: astroid + astroid.brain.brain_threading: astroid + astroid.brain.brain_type: astroid + astroid.brain.brain_typing: astroid + astroid.brain.brain_unittest: astroid + astroid.brain.brain_uuid: astroid + astroid.brain.helpers: astroid + astroid.builder: astroid + astroid.const: astroid + astroid.context: astroid + astroid.decorators: astroid + astroid.exceptions: astroid + astroid.filter_statements: astroid + astroid.helpers: astroid + astroid.inference: astroid + astroid.inference_tip: astroid + astroid.interpreter: astroid + astroid.interpreter.dunder_lookup: astroid + astroid.interpreter.objectmodel: astroid + astroid.manager: astroid + astroid.mixins: astroid + astroid.modutils: astroid + astroid.node_classes: astroid + astroid.nodes: astroid + astroid.nodes.as_string: astroid + astroid.nodes.const: astroid + astroid.nodes.node_classes: astroid + astroid.nodes.node_ng: astroid + astroid.nodes.scoped_nodes: astroid + astroid.nodes.scoped_nodes.mixin: astroid + astroid.nodes.scoped_nodes.scoped_nodes: astroid + astroid.nodes.scoped_nodes.utils: astroid + astroid.nodes.utils: astroid + astroid.objects: astroid + astroid.protocols: astroid + astroid.raw_building: astroid + astroid.rebuilder: astroid + astroid.scoped_nodes: astroid + astroid.test_utils: astroid + astroid.transforms: astroid + astroid.typing: astroid + astroid.util: astroid + certifi: certifi + certifi.core: certifi + chardet: chardet + chardet.big5freq: chardet + chardet.big5prober: chardet + chardet.chardistribution: chardet + chardet.charsetgroupprober: chardet + chardet.charsetprober: chardet + chardet.cli: chardet + chardet.cli.chardetect: chardet + chardet.codingstatemachine: chardet + chardet.compat: chardet + chardet.cp949prober: chardet + chardet.enums: chardet + chardet.escprober: chardet + chardet.escsm: chardet + chardet.eucjpprober: chardet + chardet.euckrfreq: chardet + chardet.euckrprober: chardet + chardet.euctwfreq: chardet + chardet.euctwprober: chardet + chardet.gb2312freq: chardet + chardet.gb2312prober: chardet + chardet.hebrewprober: chardet + chardet.jisfreq: chardet + chardet.jpcntx: chardet + chardet.langbulgarianmodel: chardet + chardet.langgreekmodel: chardet + chardet.langhebrewmodel: chardet + chardet.langhungarianmodel: chardet + chardet.langrussianmodel: chardet + chardet.langthaimodel: chardet + chardet.langturkishmodel: chardet + chardet.latin1prober: chardet + chardet.mbcharsetprober: chardet + chardet.mbcsgroupprober: chardet + chardet.mbcssm: chardet + chardet.metadata: chardet + chardet.metadata.languages: chardet + chardet.sbcharsetprober: chardet + chardet.sbcsgroupprober: chardet + chardet.sjisprober: chardet + chardet.universaldetector: chardet + chardet.utf8prober: chardet + chardet.version: chardet + dateutil: python_dateutil + dateutil.easter: python_dateutil + dateutil.parser: python_dateutil + dateutil.parser.isoparser: python_dateutil + dateutil.relativedelta: python_dateutil + dateutil.rrule: python_dateutil + dateutil.tz: python_dateutil + dateutil.tz.tz: python_dateutil + dateutil.tz.win: python_dateutil + dateutil.tzwin: python_dateutil + dateutil.utils: python_dateutil + dateutil.zoneinfo: python_dateutil + dateutil.zoneinfo.rebuild: python_dateutil + dill: dill + dill.detect: dill + dill.logger: dill + dill.objtypes: dill + dill.pointers: dill + dill.session: dill + dill.settings: dill + dill.source: dill + dill.temp: dill + idna: idna + idna.codec: idna + idna.compat: idna + idna.core: idna + idna.idnadata: idna + idna.intranges: idna + idna.package_data: idna + idna.uts46data: idna + isort: isort + isort.api: isort + isort.comments: isort + isort.core: isort + isort.deprecated: isort + isort.deprecated.finders: isort + isort.exceptions: isort + isort.files: isort + isort.format: isort + isort.hooks: isort + isort.identify: isort + isort.io: isort + isort.literal: isort + isort.logo: isort + isort.main: isort + isort.output: isort + isort.parse: isort + isort.place: isort + isort.profiles: isort + isort.pylama_isort: isort + isort.sections: isort + isort.settings: isort + isort.setuptools_commands: isort + isort.sorting: isort + isort.stdlibs: isort + isort.stdlibs.all: isort + isort.stdlibs.py2: isort + isort.stdlibs.py27: isort + isort.stdlibs.py3: isort + isort.stdlibs.py310: isort + isort.stdlibs.py311: isort + isort.stdlibs.py36: isort + isort.stdlibs.py37: isort + isort.stdlibs.py38: isort + isort.stdlibs.py39: isort + isort.utils: isort + isort.wrap: isort + isort.wrap_modes: isort + lazy_object_proxy: lazy_object_proxy + lazy_object_proxy.compat: lazy_object_proxy + lazy_object_proxy.simple: lazy_object_proxy + lazy_object_proxy.slots: lazy_object_proxy + lazy_object_proxy.utils: lazy_object_proxy + magic: python_magic + magic.compat: python_magic + magic.loader: python_magic + mccabe: mccabe + pathspec: pathspec + pathspec.gitignore: pathspec + pathspec.pathspec: pathspec + pathspec.pattern: pathspec + pathspec.patterns: pathspec + pathspec.patterns.gitwildmatch: pathspec + pathspec.util: pathspec + pkg_resources: setuptools + pkg_resources.extern: setuptools + platformdirs: platformdirs + platformdirs.android: platformdirs + platformdirs.api: platformdirs + platformdirs.macos: platformdirs + platformdirs.unix: platformdirs + platformdirs.version: platformdirs + platformdirs.windows: platformdirs + pylint: pylint + pylint.checkers: pylint + pylint.checkers.async: pylint + pylint.checkers.base: pylint + pylint.checkers.base.basic_checker: pylint + pylint.checkers.base.basic_error_checker: pylint + pylint.checkers.base.comparison_checker: pylint + pylint.checkers.base.docstring_checker: pylint + pylint.checkers.base.name_checker: pylint + pylint.checkers.base.name_checker.checker: pylint + pylint.checkers.base.name_checker.naming_style: pylint + pylint.checkers.base.pass_checker: pylint + pylint.checkers.base_checker: pylint + pylint.checkers.classes: pylint + pylint.checkers.classes.class_checker: pylint + pylint.checkers.classes.special_methods_checker: pylint + pylint.checkers.deprecated: pylint + pylint.checkers.design_analysis: pylint + pylint.checkers.dunder_methods: pylint + pylint.checkers.ellipsis_checker: pylint + pylint.checkers.exceptions: pylint + pylint.checkers.format: pylint + pylint.checkers.imports: pylint + pylint.checkers.lambda_expressions: pylint + pylint.checkers.logging: pylint + pylint.checkers.mapreduce_checker: pylint + pylint.checkers.method_args: pylint + pylint.checkers.misc: pylint + pylint.checkers.modified_iterating_checker: pylint + pylint.checkers.newstyle: pylint + pylint.checkers.non_ascii_names: pylint + pylint.checkers.raw_metrics: pylint + pylint.checkers.refactoring: pylint + pylint.checkers.refactoring.implicit_booleaness_checker: pylint + pylint.checkers.refactoring.not_checker: pylint + pylint.checkers.refactoring.recommendation_checker: pylint + pylint.checkers.refactoring.refactoring_checker: pylint + pylint.checkers.similar: pylint + pylint.checkers.spelling: pylint + pylint.checkers.stdlib: pylint + pylint.checkers.strings: pylint + pylint.checkers.threading_checker: pylint + pylint.checkers.typecheck: pylint + pylint.checkers.unicode: pylint + pylint.checkers.unsupported_version: pylint + pylint.checkers.utils: pylint + pylint.checkers.variables: pylint + pylint.config: pylint + pylint.config.argument: pylint + pylint.config.arguments_manager: pylint + pylint.config.arguments_provider: pylint + pylint.config.callback_actions: pylint + pylint.config.config_file_parser: pylint + pylint.config.config_initialization: pylint + pylint.config.configuration_mixin: pylint + pylint.config.deprecation_actions: pylint + pylint.config.environment_variable: pylint + pylint.config.exceptions: pylint + pylint.config.find_default_config_files: pylint + pylint.config.help_formatter: pylint + pylint.config.option: pylint + pylint.config.option_manager_mixin: pylint + pylint.config.option_parser: pylint + pylint.config.options_provider_mixin: pylint + pylint.config.utils: pylint + pylint.constants: pylint + pylint.epylint: pylint + pylint.exceptions: pylint + pylint.extensions: pylint + pylint.extensions.bad_builtin: pylint + pylint.extensions.broad_try_clause: pylint + pylint.extensions.check_elif: pylint + pylint.extensions.code_style: pylint + pylint.extensions.comparetozero: pylint + pylint.extensions.comparison_placement: pylint + pylint.extensions.confusing_elif: pylint + pylint.extensions.consider_ternary_expression: pylint + pylint.extensions.docparams: pylint + pylint.extensions.docstyle: pylint + pylint.extensions.empty_comment: pylint + pylint.extensions.emptystring: pylint + pylint.extensions.eq_without_hash: pylint + pylint.extensions.for_any_all: pylint + pylint.extensions.mccabe: pylint + pylint.extensions.no_self_use: pylint + pylint.extensions.overlapping_exceptions: pylint + pylint.extensions.private_import: pylint + pylint.extensions.redefined_loop_name: pylint + pylint.extensions.redefined_variable_type: pylint + pylint.extensions.set_membership: pylint + pylint.extensions.typing: pylint + pylint.extensions.while_used: pylint + pylint.graph: pylint + pylint.interfaces: pylint + pylint.lint: pylint + pylint.lint.base_options: pylint + pylint.lint.caching: pylint + pylint.lint.expand_modules: pylint + pylint.lint.message_state_handler: pylint + pylint.lint.parallel: pylint + pylint.lint.pylinter: pylint + pylint.lint.report_functions: pylint + pylint.lint.run: pylint + pylint.lint.utils: pylint + pylint.message: pylint + pylint.message.message: pylint + pylint.message.message_definition: pylint + pylint.message.message_definition_store: pylint + pylint.message.message_id_store: pylint + pylint.pyreverse: pylint + pylint.pyreverse.diadefslib: pylint + pylint.pyreverse.diagrams: pylint + pylint.pyreverse.dot_printer: pylint + pylint.pyreverse.inspector: pylint + pylint.pyreverse.main: pylint + pylint.pyreverse.mermaidjs_printer: pylint + pylint.pyreverse.plantuml_printer: pylint + pylint.pyreverse.printer: pylint + pylint.pyreverse.printer_factory: pylint + pylint.pyreverse.utils: pylint + pylint.pyreverse.vcg_printer: pylint + pylint.pyreverse.writer: pylint + pylint.reporters: pylint + pylint.reporters.base_reporter: pylint + pylint.reporters.collecting_reporter: pylint + pylint.reporters.json_reporter: pylint + pylint.reporters.multi_reporter: pylint + pylint.reporters.reports_handler_mix_in: pylint + pylint.reporters.text: pylint + pylint.reporters.ureports: pylint + pylint.reporters.ureports.base_writer: pylint + pylint.reporters.ureports.nodes: pylint + pylint.reporters.ureports.text_writer: pylint + pylint.testutils: pylint + pylint.testutils.checker_test_case: pylint + pylint.testutils.configuration_test: pylint + pylint.testutils.constants: pylint + pylint.testutils.decorator: pylint + pylint.testutils.functional: pylint + pylint.testutils.functional.find_functional_tests: pylint + pylint.testutils.functional.lint_module_output_update: pylint + pylint.testutils.functional.test_file: pylint + pylint.testutils.functional_test_file: pylint + pylint.testutils.get_test_info: pylint + pylint.testutils.global_test_linter: pylint + pylint.testutils.lint_module_test: pylint + pylint.testutils.output_line: pylint + pylint.testutils.pyreverse: pylint + pylint.testutils.reporter_for_tests: pylint + pylint.testutils.tokenize_str: pylint + pylint.testutils.unittest_linter: pylint + pylint.testutils.utils: pylint + pylint.typing: pylint + pylint.utils: pylint + pylint.utils.ast_walker: pylint + pylint.utils.docs: pylint + pylint.utils.file_state: pylint + pylint.utils.linterstats: pylint + pylint.utils.pragma_parser: pylint + pylint.utils.utils: pylint + requests: requests + requests.adapters: requests + requests.api: requests + requests.auth: requests + requests.certs: requests + requests.compat: requests + requests.cookies: requests + requests.exceptions: requests + requests.help: requests + requests.hooks: requests + requests.models: requests + requests.packages: requests + requests.sessions: requests + requests.status_codes: requests + requests.structures: requests + requests.utils: requests + setuptools: setuptools + setuptools.archive_util: setuptools + setuptools.build_meta: setuptools + setuptools.command: setuptools + setuptools.command.alias: setuptools + setuptools.command.bdist_egg: setuptools + setuptools.command.bdist_rpm: setuptools + setuptools.command.build: setuptools + setuptools.command.build_clib: setuptools + setuptools.command.build_ext: setuptools + setuptools.command.build_py: setuptools + setuptools.command.develop: setuptools + setuptools.command.dist_info: setuptools + setuptools.command.easy_install: setuptools + setuptools.command.editable_wheel: setuptools + setuptools.command.egg_info: setuptools + setuptools.command.install: setuptools + setuptools.command.install_egg_info: setuptools + setuptools.command.install_lib: setuptools + setuptools.command.install_scripts: setuptools + setuptools.command.py36compat: setuptools + setuptools.command.register: setuptools + setuptools.command.rotate: setuptools + setuptools.command.saveopts: setuptools + setuptools.command.sdist: setuptools + setuptools.command.setopt: setuptools + setuptools.command.test: setuptools + setuptools.command.upload: setuptools + setuptools.command.upload_docs: setuptools + setuptools.config: setuptools + setuptools.config.expand: setuptools + setuptools.config.pyprojecttoml: setuptools + setuptools.config.setupcfg: setuptools + setuptools.dep_util: setuptools + setuptools.depends: setuptools + setuptools.discovery: setuptools + setuptools.dist: setuptools + setuptools.errors: setuptools + setuptools.extension: setuptools + setuptools.extern: setuptools + setuptools.glob: setuptools + setuptools.installer: setuptools + setuptools.launch: setuptools + setuptools.logging: setuptools + setuptools.monkey: setuptools + setuptools.msvc: setuptools + setuptools.namespaces: setuptools + setuptools.package_index: setuptools + setuptools.py34compat: setuptools + setuptools.sandbox: setuptools + setuptools.unicode_utils: setuptools + setuptools.version: setuptools + setuptools.wheel: setuptools + setuptools.windows_support: setuptools + six: six + tabulate: tabulate + tabulate.version: tabulate + tomli: tomli + tomlkit: tomlkit + tomlkit.api: tomlkit + tomlkit.container: tomlkit + tomlkit.exceptions: tomlkit + tomlkit.items: tomlkit + tomlkit.parser: tomlkit + tomlkit.source: tomlkit + tomlkit.toml_char: tomlkit + tomlkit.toml_document: tomlkit + tomlkit.toml_file: tomlkit + typing_extensions: typing_extensions + urllib3: urllib3 + urllib3.connection: urllib3 + urllib3.connectionpool: urllib3 + urllib3.contrib: urllib3 + urllib3.contrib.appengine: urllib3 + urllib3.contrib.ntlmpool: urllib3 + urllib3.contrib.pyopenssl: urllib3 + urllib3.contrib.securetransport: urllib3 + urllib3.contrib.socks: urllib3 + urllib3.exceptions: urllib3 + urllib3.fields: urllib3 + urllib3.filepost: urllib3 + urllib3.packages: urllib3 + urllib3.packages.backports: urllib3 + urllib3.packages.backports.makefile: urllib3 + urllib3.packages.six: urllib3 + urllib3.poolmanager: urllib3 + urllib3.request: urllib3 + urllib3.response: urllib3 + urllib3.util: urllib3 + urllib3.util.connection: urllib3 + urllib3.util.proxy: urllib3 + urllib3.util.queue: urllib3 + urllib3.util.request: urllib3 + urllib3.util.response: urllib3 + urllib3.util.retry: urllib3 + urllib3.util.ssl_: urllib3 + urllib3.util.ssl_match_hostname: urllib3 + urllib3.util.ssltransport: urllib3 + urllib3.util.timeout: urllib3 + urllib3.util.url: urllib3 + urllib3.util.wait: urllib3 + wrapt: wrapt + wrapt.arguments: wrapt + wrapt.decorators: wrapt + wrapt.importer: wrapt + wrapt.wrappers: wrapt + yaml: PyYAML + yaml.composer: PyYAML + yaml.constructor: PyYAML + yaml.cyaml: PyYAML + yaml.dumper: PyYAML + yaml.emitter: PyYAML + yaml.error: PyYAML + yaml.events: PyYAML + yaml.loader: PyYAML + yaml.nodes: PyYAML + yaml.parser: PyYAML + yaml.reader: PyYAML + yaml.representer: PyYAML + yaml.resolver: PyYAML + yaml.scanner: PyYAML + yaml.serializer: PyYAML + yaml.tokens: PyYAML + yamllint: yamllint + yamllint.cli: yamllint + yamllint.config: yamllint + yamllint.linter: yamllint + yamllint.parser: yamllint + yamllint.rules: yamllint + yamllint.rules.braces: yamllint + yamllint.rules.brackets: yamllint + yamllint.rules.colons: yamllint + yamllint.rules.commas: yamllint + yamllint.rules.comments: yamllint + yamllint.rules.comments_indentation: yamllint + yamllint.rules.common: yamllint + yamllint.rules.document_end: yamllint + yamllint.rules.document_start: yamllint + yamllint.rules.empty_lines: yamllint + yamllint.rules.empty_values: yamllint + yamllint.rules.float_values: yamllint + yamllint.rules.hyphens: yamllint + yamllint.rules.indentation: yamllint + yamllint.rules.key_duplicates: yamllint + yamllint.rules.key_ordering: yamllint + yamllint.rules.line_length: yamllint + yamllint.rules.new_line_at_end_of_file: yamllint + yamllint.rules.new_lines: yamllint + yamllint.rules.octal_values: yamllint + yamllint.rules.quoted_strings: yamllint + yamllint.rules.trailing_spaces: yamllint + yamllint.rules.truthy: yamllint + pip_repository: + name: pip + use_pip_repository_aliases: true +integrity: d979738b10adbbaff0884837e4414688990491c6c40f6a25d58b9bb564411477 diff --git a/examples/bzlmod/runfiles/BUILD.bazel b/examples/bzlmod/runfiles/BUILD.bazel index add56b3bd0..3503ac3017 100644 --- a/examples/bzlmod/runfiles/BUILD.bazel +++ b/examples/bzlmod/runfiles/BUILD.bazel @@ -1,5 +1,6 @@ load("@rules_python//python:defs.bzl", "py_test") +# gazelle:ignore py_test( name = "runfiles_test", srcs = ["runfiles_test.py"], diff --git a/examples/bzlmod_build_file_generation/.bazelignore b/examples/bzlmod_build_file_generation/.bazelignore new file mode 100644 index 0000000000..ab3eb1635c --- /dev/null +++ b/examples/bzlmod_build_file_generation/.bazelignore @@ -0,0 +1 @@ +other_module diff --git a/examples/bzlmod_build_file_generation/.bazelrc b/examples/bzlmod_build_file_generation/.bazelrc new file mode 100644 index 0000000000..1fbada7ec4 --- /dev/null +++ b/examples/bzlmod_build_file_generation/.bazelrc @@ -0,0 +1,9 @@ +test --test_output=errors --enable_runfiles + +# Windows requires these for multi-python support: +build --enable_runfiles +startup --windows_enable_symlinks + +common --experimental_enable_bzlmod + +coverage --java_runtime_version=remotejdk_11 diff --git a/examples/bzlmod_build_file_generation/.bazelversion b/examples/bzlmod_build_file_generation/.bazelversion new file mode 100644 index 0000000000..09b254e90c --- /dev/null +++ b/examples/bzlmod_build_file_generation/.bazelversion @@ -0,0 +1 @@ +6.0.0 diff --git a/examples/bzlmod_build_file_generation/.gitignore b/examples/bzlmod_build_file_generation/.gitignore new file mode 100644 index 0000000000..ac51a054d2 --- /dev/null +++ b/examples/bzlmod_build_file_generation/.gitignore @@ -0,0 +1 @@ +bazel-* diff --git a/examples/bzlmod_build_file_generation/BUILD.bazel b/examples/bzlmod_build_file_generation/BUILD.bazel new file mode 100644 index 0000000000..c667f1e49b --- /dev/null +++ b/examples/bzlmod_build_file_generation/BUILD.bazel @@ -0,0 +1,103 @@ +# Load various rules so that we can have bazel download +# various rulesets and dependencies. +# The `load` statement imports the symbol for the rule, in the defined +# ruleset. When the symbol is loaded you can use the rule. + +# The following code loads the base python requirements and gazelle +# requirements. +load("@bazel_gazelle//:def.bzl", "gazelle") +load("@pip//:requirements.bzl", "all_whl_requirements") +load("@python3//:defs.bzl", py_test_with_transition = "py_test") +load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test") +load("@rules_python//python:pip.bzl", "compile_pip_requirements") +load("@rules_python_gazelle_plugin//:def.bzl", "GAZELLE_PYTHON_RUNTIME_DEPS") +load("@rules_python_gazelle_plugin//manifest:defs.bzl", "gazelle_python_manifest") +load("@rules_python_gazelle_plugin//modules_mapping:def.bzl", "modules_mapping") + +# This stanza calls a rule that generates targets for managing pip dependencies +# with pip-compile. +compile_pip_requirements( + name = "requirements", + extra_args = ["--allow-unsafe"], + requirements_in = "requirements.in", + requirements_txt = "requirements_lock.txt", + requirements_windows = "requirements_windows.txt", +) + +# This repository rule fetches the metadata for python packages we +# depend on. That data is required for the gazelle_python_manifest +# rule to update our manifest file. +modules_mapping( + name = "modules_map", + exclude_patterns = [ + "^_|(\\._)+", # This is the default. + "(\\.tests)+", # Add a custom one to get rid of the psutil tests. + ], + wheels = all_whl_requirements, +) + +# Gazelle python extension needs a manifest file mapping from +# an import to the installed package that provides it. +# This macro produces two targets: +# - //:gazelle_python_manifest.update can be used with `bazel run` +# to recalculate the manifest +# - //:gazelle_python_manifest.test is a test target ensuring that +# the manifest doesn't need to be updated +# This target updates a file called gazelle_python.yaml, and +# requires that file exist before the target is run. +# When you are using gazelle you need to run this target first. +gazelle_python_manifest( + name = "gazelle_python_manifest", + modules_mapping = ":modules_map", + pip_repository_name = "pip", + requirements = "//:requirements_lock.txt", + # NOTE: we can use this flag in order to make our setup compatible with + # bzlmod. + use_pip_repository_aliases = True, +) + +# Our gazelle target points to the python gazelle binary. +# This is the simple case where we only need one language supported. +# If you also had proto, go, or other gazelle-supported languages, +# you would also need a gazelle_binary rule. +# See https://github.com/bazelbuild/bazel-gazelle/blob/master/extend.rst#example +# This is the primary gazelle target to run, so that you can update BUILD.bazel files. +# You can execute: +# - bazel run //:gazelle update +# - bazel run //:gazelle fix +# See: https://github.com/bazelbuild/bazel-gazelle#fix-and-update +gazelle( + name = "gazelle", + data = GAZELLE_PYTHON_RUNTIME_DEPS, + gazelle = "@rules_python_gazelle_plugin//python:gazelle_binary", +) + +py_test_with_transition( + name = "test_with_transition", + srcs = ["__test__.py"], + main = "__test__.py", + deps = [":bzlmod_build_file_generation"], +) + +# The following targets are created and maintained by gazelle +py_library( + name = "bzlmod_build_file_generation", + srcs = ["lib.py"], + visibility = ["//:__subpackages__"], + deps = ["@pip//tabulate"], +) + +py_binary( + name = "bzlmod_build_file_generation_bin", + srcs = ["__main__.py"], + main = "__main__.py", + visibility = ["//:__subpackages__"], + deps = [":bzlmod_build_file_generation"], +) + +py_test( + name = "bzlmod_build_file_generation_test", + srcs = ["__test__.py"], + main = "__test__.py", + deps = [":bzlmod_build_file_generation"], +) diff --git a/examples/bzlmod_build_file_generation/MODULE.bazel b/examples/bzlmod_build_file_generation/MODULE.bazel new file mode 100644 index 0000000000..781b0cba39 --- /dev/null +++ b/examples/bzlmod_build_file_generation/MODULE.bazel @@ -0,0 +1,113 @@ +# This file replaces the WORKSPACE file when using bzlmod. + +# module declares certain properties of the Bazel module represented by the current Bazel repo. +# These properties are either essential metadata of the module (such as the name and version), +# or affect behavior of the current module and its dependents. +module( + name = "example_bzlmod_build_file_generation", + version = "0.0.0", + compatibility_level = 1, +) + +# The following stanza defines the dependency rules_python. +# For typical setups you set the version. +# See the releases page for available versions. +# https://github.com/bazelbuild/rules_python/releases +bazel_dep(name = "rules_python", version = "0.0.0") + +# The following loads rules_python from the file system. +# For usual setups you should remove this local_path_override block. +local_path_override( + module_name = "rules_python", + path = "../..", +) + +# The following stanza defines the dependency rules_python_gazelle_plugin. +# For typical setups you set the version. +# See the releases page for available versions. +# https://github.com/bazelbuild/rules_python/releases +bazel_dep(name = "rules_python_gazelle_plugin", version = "0.0.0") + +# The following starlark loads the gazelle plugin from the file system. +# For usual setups you should remove this local_path_override block. +local_path_override( + module_name = "rules_python_gazelle_plugin", + path = "../../gazelle", +) + +# The following stanza defines the dependency for gazelle +# See here https://github.com/bazelbuild/bazel-gazelle/releases/ for the +# latest version. +bazel_dep(name = "gazelle", version = "0.30.0", repo_name = "bazel_gazelle") + +# The following stanze returns a proxy object representing a module extension; +# its methods can be invoked to create module extension tags. +python = use_extension("@rules_python//python:extensions.bzl", "python") + +# This name is passed into python.toolchain and it's use_repo statement. +# We also use the same name for python.host_python_interpreter. +PYTHON_NAME = "python3" + +# This is the name that is used for the host interpreter +PYTHON_INTERPRETER = PYTHON_NAME + "_host_interpreter" + +# We next initialize the python toolchain using the extension. +# You can set different Python versions in this block. +python.toolchain( + # This name is used in the various use_repo statements + # below, and in the local extension that is in this + # example. + name = PYTHON_NAME, + configure_coverage_tool = True, + python_version = "3.9", +) + +# Import the python repositories generated by the given module extension +# into the scope of the current module. +# All of the python3 repositories use the PYTHON_NAME as there prefix. They +# are not catenated for ease of reading. +use_repo(python, PYTHON_NAME) +use_repo(python, "python3_toolchains") +use_repo(python, PYTHON_INTERPRETER) + +# Register an already-defined toolchain so that Bazel can use it during toolchain resolution. +register_toolchains( + "@python3_toolchains//:all", +) + +# Use the pip extension +pip = use_extension("@rules_python//python:extensions.bzl", "pip") + +# Use the extension to call the `pip_repository` rule that invokes `pip`, with `incremental` set. +# Accepts a locked/compiled requirements file and installs the dependencies listed within. +# Those dependencies become available in a generated `requirements.bzl` file. +# You can instead check this `requirements.bzl` file into your repo. +# Because this project has different requirements for windows vs other +# operating systems, we have requirements for each. +pip.parse( + name = "pip", + # When using gazelle you must use set the following flag + # in order for the generation of gazelle dependency resolution. + incompatible_generate_aliases = True, + # The interpreter attribute points to the interpreter to use for running + # pip commands to download the packages in the requirements file. + # As a best practice, we use the same interpreter as the toolchain + # that was configured above; this ensures the same Python version + # is used for both resolving dependencies and running tests/binaries. + # If this isn't specified, then you'll get whatever is locally installed + # on your system. + python_interpreter_target = "@" + PYTHON_INTERPRETER + "//:python", + requirements_lock = "//:requirements_lock.txt", + requirements_windows = "//:requirements_windows.txt", +) + +# Imports the pip toolchain generated by the given module extension into the scope of the current module. +use_repo(pip, "pip") + +# This project includes a different module that is on the local file system. +# Add the module to this parent project. +bazel_dep(name = "other_module", version = "", repo_name = "our_other_module") +local_path_override( + module_name = "other_module", + path = "other_module", +) diff --git a/examples/bzlmod_build_file_generation/README.md b/examples/bzlmod_build_file_generation/README.md new file mode 100644 index 0000000000..703fd38ebe --- /dev/null +++ b/examples/bzlmod_build_file_generation/README.md @@ -0,0 +1,28 @@ +# Bzlmod build file generation example + +This example demostrates how to use `rules_python` and gazelle with `bzlmod` enabled. +[Bzlmod](https://bazel.build/external/overview#bzlmod), the new external dependency +subsystem, does not directly work with repo definitions. Instead, it builds a dependency +graph from modules, runs extensions on top of the graph, and defines repos accordingly. + +Gazelle is setup with the `rules_python` +extension, so that targets like `py_library` and `py_binary` can be +automatically created just by running: + +```sh +$ bazel run //:gazelle update +``` + +The are other targets that allow you to update the gazelle dependency management +when you update the requirements.in file. See: + +```bash +bazel run //:gazelle_python_manifest.update +``` + +For more information on the behavior of the `rules_python` gazelle extension, +see the [README.md](../../gazelle/README.md) file in the /gazelle folder. + +This example uses a `MODULE.bazel` file that configures the bzlmod dependency +management. See comments in the `MODULE.bazel` and `BUILD.bazel` files for more +information. diff --git a/examples/bzlmod_build_file_generation/WORKSPACE b/examples/bzlmod_build_file_generation/WORKSPACE new file mode 100644 index 0000000000..78cc252e57 --- /dev/null +++ b/examples/bzlmod_build_file_generation/WORKSPACE @@ -0,0 +1,2 @@ +# Empty file indicating the root of a Bazel workspace. +# Dependencies and setup are in MODULE.bazel. diff --git a/examples/bzlmod_build_file_generation/__main__.py b/examples/bzlmod_build_file_generation/__main__.py new file mode 100644 index 0000000000..099493b3c8 --- /dev/null +++ b/examples/bzlmod_build_file_generation/__main__.py @@ -0,0 +1,18 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from lib import main + +if __name__ == "__main__": + print(main([["A", 1], ["B", 2]])) diff --git a/examples/bzlmod_build_file_generation/__test__.py b/examples/bzlmod_build_file_generation/__test__.py new file mode 100644 index 0000000000..cdc1c89680 --- /dev/null +++ b/examples/bzlmod_build_file_generation/__test__.py @@ -0,0 +1,33 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest + +from lib import main + + +class ExampleTest(unittest.TestCase): + def test_main(self): + self.assertEquals( + """\ +- - +A 1 +B 2 +- -""", + main([["A", 1], ["B", 2]]), + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/examples/bzlmod_build_file_generation/gazelle_python.yaml b/examples/bzlmod_build_file_generation/gazelle_python.yaml new file mode 100644 index 0000000000..12096e5837 --- /dev/null +++ b/examples/bzlmod_build_file_generation/gazelle_python.yaml @@ -0,0 +1,590 @@ +# GENERATED FILE - DO NOT EDIT! +# +# To update this file, run: +# bazel run //:gazelle_python_manifest.update + +manifest: + modules_mapping: + S3: s3cmd + S3.ACL: s3cmd + S3.AccessLog: s3cmd + S3.BidirMap: s3cmd + S3.CloudFront: s3cmd + S3.Config: s3cmd + S3.ConnMan: s3cmd + S3.Crypto: s3cmd + S3.Custom_httplib27: s3cmd + S3.Custom_httplib3x: s3cmd + S3.Exceptions: s3cmd + S3.ExitCodes: s3cmd + S3.FileDict: s3cmd + S3.FileLists: s3cmd + S3.HashCache: s3cmd + S3.MultiPart: s3cmd + S3.PkgInfo: s3cmd + S3.Progress: s3cmd + S3.S3: s3cmd + S3.S3Uri: s3cmd + S3.SortedDict: s3cmd + S3.Utils: s3cmd + astroid: astroid + astroid.arguments: astroid + astroid.astroid_manager: astroid + astroid.bases: astroid + astroid.brain: astroid + astroid.brain.brain_argparse: astroid + astroid.brain.brain_attrs: astroid + astroid.brain.brain_boto3: astroid + astroid.brain.brain_builtin_inference: astroid + astroid.brain.brain_collections: astroid + astroid.brain.brain_crypt: astroid + astroid.brain.brain_ctypes: astroid + astroid.brain.brain_curses: astroid + astroid.brain.brain_dataclasses: astroid + astroid.brain.brain_dateutil: astroid + astroid.brain.brain_fstrings: astroid + astroid.brain.brain_functools: astroid + astroid.brain.brain_gi: astroid + astroid.brain.brain_hashlib: astroid + astroid.brain.brain_http: astroid + astroid.brain.brain_hypothesis: astroid + astroid.brain.brain_io: astroid + astroid.brain.brain_mechanize: astroid + astroid.brain.brain_multiprocessing: astroid + astroid.brain.brain_namedtuple_enum: astroid + astroid.brain.brain_nose: astroid + astroid.brain.brain_numpy_core_einsumfunc: astroid + astroid.brain.brain_numpy_core_fromnumeric: astroid + astroid.brain.brain_numpy_core_function_base: astroid + astroid.brain.brain_numpy_core_multiarray: astroid + astroid.brain.brain_numpy_core_numeric: astroid + astroid.brain.brain_numpy_core_numerictypes: astroid + astroid.brain.brain_numpy_core_umath: astroid + astroid.brain.brain_numpy_ma: astroid + astroid.brain.brain_numpy_ndarray: astroid + astroid.brain.brain_numpy_random_mtrand: astroid + astroid.brain.brain_numpy_utils: astroid + astroid.brain.brain_pathlib: astroid + astroid.brain.brain_pkg_resources: astroid + astroid.brain.brain_pytest: astroid + astroid.brain.brain_qt: astroid + astroid.brain.brain_random: astroid + astroid.brain.brain_re: astroid + astroid.brain.brain_responses: astroid + astroid.brain.brain_scipy_signal: astroid + astroid.brain.brain_signal: astroid + astroid.brain.brain_six: astroid + astroid.brain.brain_sqlalchemy: astroid + astroid.brain.brain_ssl: astroid + astroid.brain.brain_subprocess: astroid + astroid.brain.brain_threading: astroid + astroid.brain.brain_type: astroid + astroid.brain.brain_typing: astroid + astroid.brain.brain_unittest: astroid + astroid.brain.brain_uuid: astroid + astroid.brain.helpers: astroid + astroid.builder: astroid + astroid.const: astroid + astroid.context: astroid + astroid.decorators: astroid + astroid.exceptions: astroid + astroid.filter_statements: astroid + astroid.helpers: astroid + astroid.inference: astroid + astroid.inference_tip: astroid + astroid.interpreter: astroid + astroid.interpreter.dunder_lookup: astroid + astroid.interpreter.objectmodel: astroid + astroid.manager: astroid + astroid.mixins: astroid + astroid.modutils: astroid + astroid.node_classes: astroid + astroid.nodes: astroid + astroid.nodes.as_string: astroid + astroid.nodes.const: astroid + astroid.nodes.node_classes: astroid + astroid.nodes.node_ng: astroid + astroid.nodes.scoped_nodes: astroid + astroid.nodes.scoped_nodes.mixin: astroid + astroid.nodes.scoped_nodes.scoped_nodes: astroid + astroid.nodes.scoped_nodes.utils: astroid + astroid.nodes.utils: astroid + astroid.objects: astroid + astroid.protocols: astroid + astroid.raw_building: astroid + astroid.rebuilder: astroid + astroid.scoped_nodes: astroid + astroid.test_utils: astroid + astroid.transforms: astroid + astroid.typing: astroid + astroid.util: astroid + certifi: certifi + certifi.core: certifi + chardet: chardet + chardet.big5freq: chardet + chardet.big5prober: chardet + chardet.chardistribution: chardet + chardet.charsetgroupprober: chardet + chardet.charsetprober: chardet + chardet.cli: chardet + chardet.cli.chardetect: chardet + chardet.codingstatemachine: chardet + chardet.compat: chardet + chardet.cp949prober: chardet + chardet.enums: chardet + chardet.escprober: chardet + chardet.escsm: chardet + chardet.eucjpprober: chardet + chardet.euckrfreq: chardet + chardet.euckrprober: chardet + chardet.euctwfreq: chardet + chardet.euctwprober: chardet + chardet.gb2312freq: chardet + chardet.gb2312prober: chardet + chardet.hebrewprober: chardet + chardet.jisfreq: chardet + chardet.jpcntx: chardet + chardet.langbulgarianmodel: chardet + chardet.langgreekmodel: chardet + chardet.langhebrewmodel: chardet + chardet.langhungarianmodel: chardet + chardet.langrussianmodel: chardet + chardet.langthaimodel: chardet + chardet.langturkishmodel: chardet + chardet.latin1prober: chardet + chardet.mbcharsetprober: chardet + chardet.mbcsgroupprober: chardet + chardet.mbcssm: chardet + chardet.metadata: chardet + chardet.metadata.languages: chardet + chardet.sbcharsetprober: chardet + chardet.sbcsgroupprober: chardet + chardet.sjisprober: chardet + chardet.universaldetector: chardet + chardet.utf8prober: chardet + chardet.version: chardet + dateutil: python_dateutil + dateutil.easter: python_dateutil + dateutil.parser: python_dateutil + dateutil.parser.isoparser: python_dateutil + dateutil.relativedelta: python_dateutil + dateutil.rrule: python_dateutil + dateutil.tz: python_dateutil + dateutil.tz.tz: python_dateutil + dateutil.tz.win: python_dateutil + dateutil.tzwin: python_dateutil + dateutil.utils: python_dateutil + dateutil.zoneinfo: python_dateutil + dateutil.zoneinfo.rebuild: python_dateutil + dill: dill + dill.detect: dill + dill.logger: dill + dill.objtypes: dill + dill.pointers: dill + dill.session: dill + dill.settings: dill + dill.source: dill + dill.temp: dill + idna: idna + idna.codec: idna + idna.compat: idna + idna.core: idna + idna.idnadata: idna + idna.intranges: idna + idna.package_data: idna + idna.uts46data: idna + isort: isort + isort.api: isort + isort.comments: isort + isort.core: isort + isort.deprecated: isort + isort.deprecated.finders: isort + isort.exceptions: isort + isort.files: isort + isort.format: isort + isort.hooks: isort + isort.identify: isort + isort.io: isort + isort.literal: isort + isort.logo: isort + isort.main: isort + isort.output: isort + isort.parse: isort + isort.place: isort + isort.profiles: isort + isort.pylama_isort: isort + isort.sections: isort + isort.settings: isort + isort.setuptools_commands: isort + isort.sorting: isort + isort.stdlibs: isort + isort.stdlibs.all: isort + isort.stdlibs.py2: isort + isort.stdlibs.py27: isort + isort.stdlibs.py3: isort + isort.stdlibs.py310: isort + isort.stdlibs.py311: isort + isort.stdlibs.py36: isort + isort.stdlibs.py37: isort + isort.stdlibs.py38: isort + isort.stdlibs.py39: isort + isort.utils: isort + isort.wrap: isort + isort.wrap_modes: isort + lazy_object_proxy: lazy_object_proxy + lazy_object_proxy.compat: lazy_object_proxy + lazy_object_proxy.simple: lazy_object_proxy + lazy_object_proxy.slots: lazy_object_proxy + lazy_object_proxy.utils: lazy_object_proxy + magic: python_magic + magic.compat: python_magic + magic.loader: python_magic + mccabe: mccabe + pathspec: pathspec + pathspec.gitignore: pathspec + pathspec.pathspec: pathspec + pathspec.pattern: pathspec + pathspec.patterns: pathspec + pathspec.patterns.gitwildmatch: pathspec + pathspec.util: pathspec + pkg_resources: setuptools + pkg_resources.extern: setuptools + platformdirs: platformdirs + platformdirs.android: platformdirs + platformdirs.api: platformdirs + platformdirs.macos: platformdirs + platformdirs.unix: platformdirs + platformdirs.version: platformdirs + platformdirs.windows: platformdirs + pylint: pylint + pylint.checkers: pylint + pylint.checkers.async: pylint + pylint.checkers.base: pylint + pylint.checkers.base.basic_checker: pylint + pylint.checkers.base.basic_error_checker: pylint + pylint.checkers.base.comparison_checker: pylint + pylint.checkers.base.docstring_checker: pylint + pylint.checkers.base.name_checker: pylint + pylint.checkers.base.name_checker.checker: pylint + pylint.checkers.base.name_checker.naming_style: pylint + pylint.checkers.base.pass_checker: pylint + pylint.checkers.base_checker: pylint + pylint.checkers.classes: pylint + pylint.checkers.classes.class_checker: pylint + pylint.checkers.classes.special_methods_checker: pylint + pylint.checkers.deprecated: pylint + pylint.checkers.design_analysis: pylint + pylint.checkers.dunder_methods: pylint + pylint.checkers.ellipsis_checker: pylint + pylint.checkers.exceptions: pylint + pylint.checkers.format: pylint + pylint.checkers.imports: pylint + pylint.checkers.lambda_expressions: pylint + pylint.checkers.logging: pylint + pylint.checkers.mapreduce_checker: pylint + pylint.checkers.method_args: pylint + pylint.checkers.misc: pylint + pylint.checkers.modified_iterating_checker: pylint + pylint.checkers.newstyle: pylint + pylint.checkers.non_ascii_names: pylint + pylint.checkers.raw_metrics: pylint + pylint.checkers.refactoring: pylint + pylint.checkers.refactoring.implicit_booleaness_checker: pylint + pylint.checkers.refactoring.not_checker: pylint + pylint.checkers.refactoring.recommendation_checker: pylint + pylint.checkers.refactoring.refactoring_checker: pylint + pylint.checkers.similar: pylint + pylint.checkers.spelling: pylint + pylint.checkers.stdlib: pylint + pylint.checkers.strings: pylint + pylint.checkers.threading_checker: pylint + pylint.checkers.typecheck: pylint + pylint.checkers.unicode: pylint + pylint.checkers.unsupported_version: pylint + pylint.checkers.utils: pylint + pylint.checkers.variables: pylint + pylint.config: pylint + pylint.config.argument: pylint + pylint.config.arguments_manager: pylint + pylint.config.arguments_provider: pylint + pylint.config.callback_actions: pylint + pylint.config.config_file_parser: pylint + pylint.config.config_initialization: pylint + pylint.config.configuration_mixin: pylint + pylint.config.deprecation_actions: pylint + pylint.config.environment_variable: pylint + pylint.config.exceptions: pylint + pylint.config.find_default_config_files: pylint + pylint.config.help_formatter: pylint + pylint.config.option: pylint + pylint.config.option_manager_mixin: pylint + pylint.config.option_parser: pylint + pylint.config.options_provider_mixin: pylint + pylint.config.utils: pylint + pylint.constants: pylint + pylint.epylint: pylint + pylint.exceptions: pylint + pylint.extensions: pylint + pylint.extensions.bad_builtin: pylint + pylint.extensions.broad_try_clause: pylint + pylint.extensions.check_elif: pylint + pylint.extensions.code_style: pylint + pylint.extensions.comparetozero: pylint + pylint.extensions.comparison_placement: pylint + pylint.extensions.confusing_elif: pylint + pylint.extensions.consider_ternary_expression: pylint + pylint.extensions.docparams: pylint + pylint.extensions.docstyle: pylint + pylint.extensions.empty_comment: pylint + pylint.extensions.emptystring: pylint + pylint.extensions.eq_without_hash: pylint + pylint.extensions.for_any_all: pylint + pylint.extensions.mccabe: pylint + pylint.extensions.no_self_use: pylint + pylint.extensions.overlapping_exceptions: pylint + pylint.extensions.private_import: pylint + pylint.extensions.redefined_loop_name: pylint + pylint.extensions.redefined_variable_type: pylint + pylint.extensions.set_membership: pylint + pylint.extensions.typing: pylint + pylint.extensions.while_used: pylint + pylint.graph: pylint + pylint.interfaces: pylint + pylint.lint: pylint + pylint.lint.base_options: pylint + pylint.lint.caching: pylint + pylint.lint.expand_modules: pylint + pylint.lint.message_state_handler: pylint + pylint.lint.parallel: pylint + pylint.lint.pylinter: pylint + pylint.lint.report_functions: pylint + pylint.lint.run: pylint + pylint.lint.utils: pylint + pylint.message: pylint + pylint.message.message: pylint + pylint.message.message_definition: pylint + pylint.message.message_definition_store: pylint + pylint.message.message_id_store: pylint + pylint.pyreverse: pylint + pylint.pyreverse.diadefslib: pylint + pylint.pyreverse.diagrams: pylint + pylint.pyreverse.dot_printer: pylint + pylint.pyreverse.inspector: pylint + pylint.pyreverse.main: pylint + pylint.pyreverse.mermaidjs_printer: pylint + pylint.pyreverse.plantuml_printer: pylint + pylint.pyreverse.printer: pylint + pylint.pyreverse.printer_factory: pylint + pylint.pyreverse.utils: pylint + pylint.pyreverse.vcg_printer: pylint + pylint.pyreverse.writer: pylint + pylint.reporters: pylint + pylint.reporters.base_reporter: pylint + pylint.reporters.collecting_reporter: pylint + pylint.reporters.json_reporter: pylint + pylint.reporters.multi_reporter: pylint + pylint.reporters.reports_handler_mix_in: pylint + pylint.reporters.text: pylint + pylint.reporters.ureports: pylint + pylint.reporters.ureports.base_writer: pylint + pylint.reporters.ureports.nodes: pylint + pylint.reporters.ureports.text_writer: pylint + pylint.testutils: pylint + pylint.testutils.checker_test_case: pylint + pylint.testutils.configuration_test: pylint + pylint.testutils.constants: pylint + pylint.testutils.decorator: pylint + pylint.testutils.functional: pylint + pylint.testutils.functional.find_functional_tests: pylint + pylint.testutils.functional.lint_module_output_update: pylint + pylint.testutils.functional.test_file: pylint + pylint.testutils.functional_test_file: pylint + pylint.testutils.get_test_info: pylint + pylint.testutils.global_test_linter: pylint + pylint.testutils.lint_module_test: pylint + pylint.testutils.output_line: pylint + pylint.testutils.pyreverse: pylint + pylint.testutils.reporter_for_tests: pylint + pylint.testutils.tokenize_str: pylint + pylint.testutils.unittest_linter: pylint + pylint.testutils.utils: pylint + pylint.typing: pylint + pylint.utils: pylint + pylint.utils.ast_walker: pylint + pylint.utils.docs: pylint + pylint.utils.file_state: pylint + pylint.utils.linterstats: pylint + pylint.utils.pragma_parser: pylint + pylint.utils.utils: pylint + requests: requests + requests.adapters: requests + requests.api: requests + requests.auth: requests + requests.certs: requests + requests.compat: requests + requests.cookies: requests + requests.exceptions: requests + requests.help: requests + requests.hooks: requests + requests.models: requests + requests.packages: requests + requests.sessions: requests + requests.status_codes: requests + requests.structures: requests + requests.utils: requests + setuptools: setuptools + setuptools.archive_util: setuptools + setuptools.build_meta: setuptools + setuptools.command: setuptools + setuptools.command.alias: setuptools + setuptools.command.bdist_egg: setuptools + setuptools.command.bdist_rpm: setuptools + setuptools.command.build: setuptools + setuptools.command.build_clib: setuptools + setuptools.command.build_ext: setuptools + setuptools.command.build_py: setuptools + setuptools.command.develop: setuptools + setuptools.command.dist_info: setuptools + setuptools.command.easy_install: setuptools + setuptools.command.editable_wheel: setuptools + setuptools.command.egg_info: setuptools + setuptools.command.install: setuptools + setuptools.command.install_egg_info: setuptools + setuptools.command.install_lib: setuptools + setuptools.command.install_scripts: setuptools + setuptools.command.py36compat: setuptools + setuptools.command.register: setuptools + setuptools.command.rotate: setuptools + setuptools.command.saveopts: setuptools + setuptools.command.sdist: setuptools + setuptools.command.setopt: setuptools + setuptools.command.test: setuptools + setuptools.command.upload: setuptools + setuptools.command.upload_docs: setuptools + setuptools.config: setuptools + setuptools.config.expand: setuptools + setuptools.config.pyprojecttoml: setuptools + setuptools.config.setupcfg: setuptools + setuptools.dep_util: setuptools + setuptools.depends: setuptools + setuptools.discovery: setuptools + setuptools.dist: setuptools + setuptools.errors: setuptools + setuptools.extension: setuptools + setuptools.extern: setuptools + setuptools.glob: setuptools + setuptools.installer: setuptools + setuptools.launch: setuptools + setuptools.logging: setuptools + setuptools.monkey: setuptools + setuptools.msvc: setuptools + setuptools.namespaces: setuptools + setuptools.package_index: setuptools + setuptools.py34compat: setuptools + setuptools.sandbox: setuptools + setuptools.unicode_utils: setuptools + setuptools.version: setuptools + setuptools.wheel: setuptools + setuptools.windows_support: setuptools + six: six + tabulate: tabulate + tabulate.version: tabulate + tomli: tomli + tomlkit: tomlkit + tomlkit.api: tomlkit + tomlkit.container: tomlkit + tomlkit.exceptions: tomlkit + tomlkit.items: tomlkit + tomlkit.parser: tomlkit + tomlkit.source: tomlkit + tomlkit.toml_char: tomlkit + tomlkit.toml_document: tomlkit + tomlkit.toml_file: tomlkit + typing_extensions: typing_extensions + urllib3: urllib3 + urllib3.connection: urllib3 + urllib3.connectionpool: urllib3 + urllib3.contrib: urllib3 + urllib3.contrib.appengine: urllib3 + urllib3.contrib.ntlmpool: urllib3 + urllib3.contrib.pyopenssl: urllib3 + urllib3.contrib.securetransport: urllib3 + urllib3.contrib.socks: urllib3 + urllib3.exceptions: urllib3 + urllib3.fields: urllib3 + urllib3.filepost: urllib3 + urllib3.packages: urllib3 + urllib3.packages.backports: urllib3 + urllib3.packages.backports.makefile: urllib3 + urllib3.packages.six: urllib3 + urllib3.poolmanager: urllib3 + urllib3.request: urllib3 + urllib3.response: urllib3 + urllib3.util: urllib3 + urllib3.util.connection: urllib3 + urllib3.util.proxy: urllib3 + urllib3.util.queue: urllib3 + urllib3.util.request: urllib3 + urllib3.util.response: urllib3 + urllib3.util.retry: urllib3 + urllib3.util.ssl_: urllib3 + urllib3.util.ssl_match_hostname: urllib3 + urllib3.util.ssltransport: urllib3 + urllib3.util.timeout: urllib3 + urllib3.util.url: urllib3 + urllib3.util.wait: urllib3 + wrapt: wrapt + wrapt.arguments: wrapt + wrapt.decorators: wrapt + wrapt.importer: wrapt + wrapt.wrappers: wrapt + yaml: PyYAML + yaml.composer: PyYAML + yaml.constructor: PyYAML + yaml.cyaml: PyYAML + yaml.dumper: PyYAML + yaml.emitter: PyYAML + yaml.error: PyYAML + yaml.events: PyYAML + yaml.loader: PyYAML + yaml.nodes: PyYAML + yaml.parser: PyYAML + yaml.reader: PyYAML + yaml.representer: PyYAML + yaml.resolver: PyYAML + yaml.scanner: PyYAML + yaml.serializer: PyYAML + yaml.tokens: PyYAML + yamllint: yamllint + yamllint.cli: yamllint + yamllint.config: yamllint + yamllint.linter: yamllint + yamllint.parser: yamllint + yamllint.rules: yamllint + yamllint.rules.braces: yamllint + yamllint.rules.brackets: yamllint + yamllint.rules.colons: yamllint + yamllint.rules.commas: yamllint + yamllint.rules.comments: yamllint + yamllint.rules.comments_indentation: yamllint + yamllint.rules.common: yamllint + yamllint.rules.document_end: yamllint + yamllint.rules.document_start: yamllint + yamllint.rules.empty_lines: yamllint + yamllint.rules.empty_values: yamllint + yamllint.rules.float_values: yamllint + yamllint.rules.hyphens: yamllint + yamllint.rules.indentation: yamllint + yamllint.rules.key_duplicates: yamllint + yamllint.rules.key_ordering: yamllint + yamllint.rules.line_length: yamllint + yamllint.rules.new_line_at_end_of_file: yamllint + yamllint.rules.new_lines: yamllint + yamllint.rules.octal_values: yamllint + yamllint.rules.quoted_strings: yamllint + yamllint.rules.trailing_spaces: yamllint + yamllint.rules.truthy: yamllint + pip_repository: + name: pip + use_pip_repository_aliases: true +integrity: d979738b10adbbaff0884837e4414688990491c6c40f6a25d58b9bb564411477 diff --git a/examples/bzlmod_build_file_generation/lib.py b/examples/bzlmod_build_file_generation/lib.py new file mode 100644 index 0000000000..646c6e890f --- /dev/null +++ b/examples/bzlmod_build_file_generation/lib.py @@ -0,0 +1,19 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from tabulate import tabulate + + +def main(table): + return tabulate(table) diff --git a/examples/bzlmod_build_file_generation/other_module/MODULE.bazel b/examples/bzlmod_build_file_generation/other_module/MODULE.bazel new file mode 100644 index 0000000000..992e120760 --- /dev/null +++ b/examples/bzlmod_build_file_generation/other_module/MODULE.bazel @@ -0,0 +1,5 @@ +module( + name = "other_module", +) + +bazel_dep(name = "rules_python", version = "") diff --git a/examples/bzlmod_build_file_generation/other_module/WORKSPACE b/examples/bzlmod_build_file_generation/other_module/WORKSPACE new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/bzlmod_build_file_generation/other_module/other_module/pkg/BUILD.bazel b/examples/bzlmod_build_file_generation/other_module/other_module/pkg/BUILD.bazel new file mode 100644 index 0000000000..9a130e3554 --- /dev/null +++ b/examples/bzlmod_build_file_generation/other_module/other_module/pkg/BUILD.bazel @@ -0,0 +1,11 @@ +load("@rules_python//python:defs.bzl", "py_library") + +py_library( + name = "lib", + srcs = ["lib.py"], + data = ["data/data.txt"], + visibility = ["//visibility:public"], + deps = ["@rules_python//python/runfiles"], +) + +exports_files(["data/data.txt"]) diff --git a/examples/bzlmod_build_file_generation/other_module/other_module/pkg/data/data.txt b/examples/bzlmod_build_file_generation/other_module/other_module/pkg/data/data.txt new file mode 100644 index 0000000000..e975eaf640 --- /dev/null +++ b/examples/bzlmod_build_file_generation/other_module/other_module/pkg/data/data.txt @@ -0,0 +1 @@ +Hello, other_module! diff --git a/examples/bzlmod_build_file_generation/other_module/other_module/pkg/lib.py b/examples/bzlmod_build_file_generation/other_module/other_module/pkg/lib.py new file mode 100644 index 0000000000..eaf65fb46a --- /dev/null +++ b/examples/bzlmod_build_file_generation/other_module/other_module/pkg/lib.py @@ -0,0 +1,27 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from python.runfiles import runfiles + + +def GetRunfilePathWithCurrentRepository(): + r = runfiles.Create() + own_repo = r.CurrentRepository() + # For a non-main repository, the name of the runfiles directory is equal to + # the canonical repository name. + return r.Rlocation(own_repo + "/other_module/pkg/data/data.txt") + + +def GetRunfilePathWithRepoMapping(): + return runfiles.Create().Rlocation("other_module/other_module/pkg/data/data.txt") diff --git a/examples/bzlmod_build_file_generation/requirements.in b/examples/bzlmod_build_file_generation/requirements.in new file mode 100644 index 0000000000..a709195442 --- /dev/null +++ b/examples/bzlmod_build_file_generation/requirements.in @@ -0,0 +1,6 @@ +requests~=2.25.1 +s3cmd~=2.1.0 +yamllint>=1.28.0 +tabulate~=0.9.0 +pylint~=2.15.5 +python-dateutil>=2.8.2 diff --git a/examples/bzlmod_build_file_generation/requirements_lock.txt b/examples/bzlmod_build_file_generation/requirements_lock.txt new file mode 100644 index 0000000000..2160fe1163 --- /dev/null +++ b/examples/bzlmod_build_file_generation/requirements_lock.txt @@ -0,0 +1,227 @@ +# +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: +# +# bazel run //:requirements.update +# +astroid==2.12.13 \ + --hash=sha256:10e0ad5f7b79c435179d0d0f0df69998c4eef4597534aae44910db060baeb907 \ + --hash=sha256:1493fe8bd3dfd73dc35bd53c9d5b6e49ead98497c47b2307662556a5692d29d7 + # via pylint +certifi==2022.12.7 \ + --hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \ + --hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18 + # via requests +chardet==4.0.0 \ + --hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa \ + --hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5 + # via requests +dill==0.3.6 \ + --hash=sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0 \ + --hash=sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373 + # via pylint +idna==2.10 \ + --hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 \ + --hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0 + # via requests +isort==5.11.4 \ + --hash=sha256:6db30c5ded9815d813932c04c2f85a360bcdd35fed496f4d8f35495ef0a261b6 \ + --hash=sha256:c033fd0edb91000a7f09527fe5c75321878f98322a77ddcc81adbd83724afb7b + # via pylint +lazy-object-proxy==1.8.0 \ + --hash=sha256:0c1c7c0433154bb7c54185714c6929acc0ba04ee1b167314a779b9025517eada \ + --hash=sha256:14010b49a2f56ec4943b6cf925f597b534ee2fe1f0738c84b3bce0c1a11ff10d \ + --hash=sha256:4e2d9f764f1befd8bdc97673261b8bb888764dfdbd7a4d8f55e4fbcabb8c3fb7 \ + --hash=sha256:4fd031589121ad46e293629b39604031d354043bb5cdf83da4e93c2d7f3389fe \ + --hash=sha256:5b51d6f3bfeb289dfd4e95de2ecd464cd51982fe6f00e2be1d0bf94864d58acd \ + --hash=sha256:6850e4aeca6d0df35bb06e05c8b934ff7c533734eb51d0ceb2d63696f1e6030c \ + --hash=sha256:6f593f26c470a379cf7f5bc6db6b5f1722353e7bf937b8d0d0b3fba911998858 \ + --hash=sha256:71d9ae8a82203511a6f60ca5a1b9f8ad201cac0fc75038b2dc5fa519589c9288 \ + --hash=sha256:7e1561626c49cb394268edd00501b289053a652ed762c58e1081224c8d881cec \ + --hash=sha256:8f6ce2118a90efa7f62dd38c7dbfffd42f468b180287b748626293bf12ed468f \ + --hash=sha256:ae032743794fba4d171b5b67310d69176287b5bf82a21f588282406a79498891 \ + --hash=sha256:afcaa24e48bb23b3be31e329deb3f1858f1f1df86aea3d70cb5c8578bfe5261c \ + --hash=sha256:b70d6e7a332eb0217e7872a73926ad4fdc14f846e85ad6749ad111084e76df25 \ + --hash=sha256:c219a00245af0f6fa4e95901ed28044544f50152840c5b6a3e7b2568db34d156 \ + --hash=sha256:ce58b2b3734c73e68f0e30e4e725264d4d6be95818ec0a0be4bb6bf9a7e79aa8 \ + --hash=sha256:d176f392dbbdaacccf15919c77f526edf11a34aece58b55ab58539807b85436f \ + --hash=sha256:e20bfa6db17a39c706d24f82df8352488d2943a3b7ce7d4c22579cb89ca8896e \ + --hash=sha256:eac3a9a5ef13b332c059772fd40b4b1c3d45a3a2b05e33a361dee48e54a4dad0 \ + --hash=sha256:eb329f8d8145379bf5dbe722182410fe8863d186e51bf034d2075eb8d85ee25b + # via astroid +mccabe==0.7.0 \ + --hash=sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325 \ + --hash=sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e + # via pylint +pathspec==0.10.3 \ + --hash=sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6 \ + --hash=sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6 + # via yamllint +platformdirs==2.6.0 \ + --hash=sha256:1a89a12377800c81983db6be069ec068eee989748799b946cce2a6e80dcc54ca \ + --hash=sha256:b46ffafa316e6b83b47489d240ce17173f123a9b9c83282141c3daf26ad9ac2e + # via pylint +pylint==2.15.9 \ + --hash=sha256:18783cca3cfee5b83c6c5d10b3cdb66c6594520ffae61890858fe8d932e1c6b4 \ + --hash=sha256:349c8cd36aede4d50a0754a8c0218b43323d13d5d88f4b2952ddfe3e169681eb + # via -r requirements.in +python-dateutil==2.8.2 \ + --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ + --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 + # via + # -r requirements.in + # s3cmd +python-magic==0.4.27 \ + --hash=sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b \ + --hash=sha256:c212960ad306f700aa0d01e5d7a325d20548ff97eb9920dcd29513174f0294d3 + # via s3cmd +pyyaml==6.0 \ + --hash=sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf \ + --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ + --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ + --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ + --hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b \ + --hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 \ + --hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 \ + --hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba \ + --hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 \ + --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ + --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ + --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ + --hash=sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782 \ + --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ + --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ + --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ + --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ + --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ + --hash=sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1 \ + --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ + --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ + --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ + --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ + --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ + --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ + --hash=sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d \ + --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ + --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ + --hash=sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7 \ + --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ + --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ + --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ + --hash=sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358 \ + --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ + --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ + --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ + --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ + --hash=sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f \ + --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ + --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 + # via yamllint +requests==2.25.1 \ + --hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \ + --hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e + # via -r requirements.in +s3cmd==2.1.0 \ + --hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \ + --hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03 + # via -r requirements.in +setuptools==65.6.3 \ + --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ + --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 + # via yamllint +six==1.16.0 \ + --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ + --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 + # via python-dateutil +tabulate==0.9.0 \ + --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \ + --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f + # via -r requirements.in +tomli==2.0.1 \ + --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ + --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f + # via pylint +tomlkit==0.11.6 \ + --hash=sha256:07de26b0d8cfc18f871aec595fda24d95b08fef89d147caa861939f37230bf4b \ + --hash=sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73 + # via pylint +typing-extensions==4.4.0 \ + --hash=sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa \ + --hash=sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e + # via + # astroid + # pylint +urllib3==1.26.13 \ + --hash=sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc \ + --hash=sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8 + # via requests +wrapt==1.14.1 \ + --hash=sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3 \ + --hash=sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b \ + --hash=sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4 \ + --hash=sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2 \ + --hash=sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656 \ + --hash=sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3 \ + --hash=sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff \ + --hash=sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310 \ + --hash=sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a \ + --hash=sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57 \ + --hash=sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069 \ + --hash=sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383 \ + --hash=sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe \ + --hash=sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87 \ + --hash=sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d \ + --hash=sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b \ + --hash=sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907 \ + --hash=sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f \ + --hash=sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0 \ + --hash=sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28 \ + --hash=sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1 \ + --hash=sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853 \ + --hash=sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc \ + --hash=sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3 \ + --hash=sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3 \ + --hash=sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164 \ + --hash=sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1 \ + --hash=sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c \ + --hash=sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1 \ + --hash=sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7 \ + --hash=sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1 \ + --hash=sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320 \ + --hash=sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed \ + --hash=sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1 \ + --hash=sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248 \ + --hash=sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c \ + --hash=sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456 \ + --hash=sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77 \ + --hash=sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef \ + --hash=sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1 \ + --hash=sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7 \ + --hash=sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86 \ + --hash=sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4 \ + --hash=sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d \ + --hash=sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d \ + --hash=sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8 \ + --hash=sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5 \ + --hash=sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471 \ + --hash=sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00 \ + --hash=sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68 \ + --hash=sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3 \ + --hash=sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d \ + --hash=sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735 \ + --hash=sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d \ + --hash=sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569 \ + --hash=sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7 \ + --hash=sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59 \ + --hash=sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5 \ + --hash=sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb \ + --hash=sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b \ + --hash=sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f \ + --hash=sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462 \ + --hash=sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015 \ + --hash=sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af + # via astroid +yamllint==1.28.0 \ + --hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \ + --hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b + # via -r requirements.in diff --git a/examples/bzlmod_build_file_generation/requirements_windows.txt b/examples/bzlmod_build_file_generation/requirements_windows.txt new file mode 100644 index 0000000000..06cfdc332c --- /dev/null +++ b/examples/bzlmod_build_file_generation/requirements_windows.txt @@ -0,0 +1,231 @@ +# +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: +# +# bazel run //:requirements.update +# +astroid==2.12.13 \ + --hash=sha256:10e0ad5f7b79c435179d0d0f0df69998c4eef4597534aae44910db060baeb907 \ + --hash=sha256:1493fe8bd3dfd73dc35bd53c9d5b6e49ead98497c47b2307662556a5692d29d7 + # via pylint +certifi==2022.12.7 \ + --hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \ + --hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18 + # via requests +chardet==4.0.0 \ + --hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa \ + --hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5 + # via requests +colorama==0.4.6 \ + --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ + --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 + # via pylint +dill==0.3.6 \ + --hash=sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0 \ + --hash=sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373 + # via pylint +idna==2.10 \ + --hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6 \ + --hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0 + # via requests +isort==5.11.4 \ + --hash=sha256:6db30c5ded9815d813932c04c2f85a360bcdd35fed496f4d8f35495ef0a261b6 \ + --hash=sha256:c033fd0edb91000a7f09527fe5c75321878f98322a77ddcc81adbd83724afb7b + # via pylint +lazy-object-proxy==1.8.0 \ + --hash=sha256:0c1c7c0433154bb7c54185714c6929acc0ba04ee1b167314a779b9025517eada \ + --hash=sha256:14010b49a2f56ec4943b6cf925f597b534ee2fe1f0738c84b3bce0c1a11ff10d \ + --hash=sha256:4e2d9f764f1befd8bdc97673261b8bb888764dfdbd7a4d8f55e4fbcabb8c3fb7 \ + --hash=sha256:4fd031589121ad46e293629b39604031d354043bb5cdf83da4e93c2d7f3389fe \ + --hash=sha256:5b51d6f3bfeb289dfd4e95de2ecd464cd51982fe6f00e2be1d0bf94864d58acd \ + --hash=sha256:6850e4aeca6d0df35bb06e05c8b934ff7c533734eb51d0ceb2d63696f1e6030c \ + --hash=sha256:6f593f26c470a379cf7f5bc6db6b5f1722353e7bf937b8d0d0b3fba911998858 \ + --hash=sha256:71d9ae8a82203511a6f60ca5a1b9f8ad201cac0fc75038b2dc5fa519589c9288 \ + --hash=sha256:7e1561626c49cb394268edd00501b289053a652ed762c58e1081224c8d881cec \ + --hash=sha256:8f6ce2118a90efa7f62dd38c7dbfffd42f468b180287b748626293bf12ed468f \ + --hash=sha256:ae032743794fba4d171b5b67310d69176287b5bf82a21f588282406a79498891 \ + --hash=sha256:afcaa24e48bb23b3be31e329deb3f1858f1f1df86aea3d70cb5c8578bfe5261c \ + --hash=sha256:b70d6e7a332eb0217e7872a73926ad4fdc14f846e85ad6749ad111084e76df25 \ + --hash=sha256:c219a00245af0f6fa4e95901ed28044544f50152840c5b6a3e7b2568db34d156 \ + --hash=sha256:ce58b2b3734c73e68f0e30e4e725264d4d6be95818ec0a0be4bb6bf9a7e79aa8 \ + --hash=sha256:d176f392dbbdaacccf15919c77f526edf11a34aece58b55ab58539807b85436f \ + --hash=sha256:e20bfa6db17a39c706d24f82df8352488d2943a3b7ce7d4c22579cb89ca8896e \ + --hash=sha256:eac3a9a5ef13b332c059772fd40b4b1c3d45a3a2b05e33a361dee48e54a4dad0 \ + --hash=sha256:eb329f8d8145379bf5dbe722182410fe8863d186e51bf034d2075eb8d85ee25b + # via astroid +mccabe==0.7.0 \ + --hash=sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325 \ + --hash=sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e + # via pylint +pathspec==0.10.3 \ + --hash=sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6 \ + --hash=sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6 + # via yamllint +platformdirs==2.6.0 \ + --hash=sha256:1a89a12377800c81983db6be069ec068eee989748799b946cce2a6e80dcc54ca \ + --hash=sha256:b46ffafa316e6b83b47489d240ce17173f123a9b9c83282141c3daf26ad9ac2e + # via pylint +pylint==2.15.9 \ + --hash=sha256:18783cca3cfee5b83c6c5d10b3cdb66c6594520ffae61890858fe8d932e1c6b4 \ + --hash=sha256:349c8cd36aede4d50a0754a8c0218b43323d13d5d88f4b2952ddfe3e169681eb + # via -r requirements.in +python-dateutil==2.8.2 \ + --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ + --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 + # via + # -r requirements.in + # s3cmd +python-magic==0.4.27 \ + --hash=sha256:c1ba14b08e4a5f5c31a302b7721239695b2f0f058d125bd5ce1ee36b9d9d3c3b \ + --hash=sha256:c212960ad306f700aa0d01e5d7a325d20548ff97eb9920dcd29513174f0294d3 + # via s3cmd +pyyaml==6.0 \ + --hash=sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf \ + --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ + --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ + --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ + --hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b \ + --hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 \ + --hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 \ + --hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba \ + --hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 \ + --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ + --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ + --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ + --hash=sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782 \ + --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ + --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ + --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ + --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ + --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ + --hash=sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1 \ + --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ + --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ + --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ + --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ + --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ + --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ + --hash=sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d \ + --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ + --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ + --hash=sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7 \ + --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ + --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ + --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ + --hash=sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358 \ + --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ + --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ + --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ + --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ + --hash=sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f \ + --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ + --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 + # via yamllint +requests==2.25.1 \ + --hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804 \ + --hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e + # via -r requirements.in +s3cmd==2.1.0 \ + --hash=sha256:49cd23d516b17974b22b611a95ce4d93fe326feaa07320bd1d234fed68cbccfa \ + --hash=sha256:966b0a494a916fc3b4324de38f089c86c70ee90e8e1cae6d59102103a4c0cc03 + # via -r requirements.in +setuptools==65.6.3 \ + --hash=sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54 \ + --hash=sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75 + # via yamllint +six==1.16.0 \ + --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ + --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 + # via python-dateutil +tabulate==0.9.0 \ + --hash=sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c \ + --hash=sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f + # via -r requirements.in +tomli==2.0.1 \ + --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ + --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f + # via pylint +tomlkit==0.11.6 \ + --hash=sha256:07de26b0d8cfc18f871aec595fda24d95b08fef89d147caa861939f37230bf4b \ + --hash=sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73 + # via pylint +typing-extensions==4.4.0 \ + --hash=sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa \ + --hash=sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e + # via + # astroid + # pylint +urllib3==1.26.13 \ + --hash=sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc \ + --hash=sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8 + # via requests +wrapt==1.14.1 \ + --hash=sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3 \ + --hash=sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b \ + --hash=sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4 \ + --hash=sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2 \ + --hash=sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656 \ + --hash=sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3 \ + --hash=sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff \ + --hash=sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310 \ + --hash=sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a \ + --hash=sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57 \ + --hash=sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069 \ + --hash=sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383 \ + --hash=sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe \ + --hash=sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87 \ + --hash=sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d \ + --hash=sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b \ + --hash=sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907 \ + --hash=sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f \ + --hash=sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0 \ + --hash=sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28 \ + --hash=sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1 \ + --hash=sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853 \ + --hash=sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc \ + --hash=sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3 \ + --hash=sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3 \ + --hash=sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164 \ + --hash=sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1 \ + --hash=sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c \ + --hash=sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1 \ + --hash=sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7 \ + --hash=sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1 \ + --hash=sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320 \ + --hash=sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed \ + --hash=sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1 \ + --hash=sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248 \ + --hash=sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c \ + --hash=sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456 \ + --hash=sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77 \ + --hash=sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef \ + --hash=sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1 \ + --hash=sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7 \ + --hash=sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86 \ + --hash=sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4 \ + --hash=sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d \ + --hash=sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d \ + --hash=sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8 \ + --hash=sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5 \ + --hash=sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471 \ + --hash=sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00 \ + --hash=sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68 \ + --hash=sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3 \ + --hash=sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d \ + --hash=sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735 \ + --hash=sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d \ + --hash=sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569 \ + --hash=sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7 \ + --hash=sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59 \ + --hash=sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5 \ + --hash=sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb \ + --hash=sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b \ + --hash=sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f \ + --hash=sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462 \ + --hash=sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015 \ + --hash=sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af + # via astroid +yamllint==1.28.0 \ + --hash=sha256:89bb5b5ac33b1ade059743cf227de73daa34d5e5a474b06a5e17fc16583b0cf2 \ + --hash=sha256:9e3d8ddd16d0583214c5fdffe806c9344086721f107435f68bad990e5a88826b + # via -r requirements.in diff --git a/examples/bzlmod_build_file_generation/runfiles/BUILD.bazel b/examples/bzlmod_build_file_generation/runfiles/BUILD.bazel new file mode 100644 index 0000000000..3503ac3017 --- /dev/null +++ b/examples/bzlmod_build_file_generation/runfiles/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_python//python:defs.bzl", "py_test") + +# gazelle:ignore +py_test( + name = "runfiles_test", + srcs = ["runfiles_test.py"], + data = [ + "data/data.txt", + "@our_other_module//other_module/pkg:data/data.txt", + ], + env = { + "DATA_RLOCATIONPATH": "$(rlocationpath data/data.txt)", + "OTHER_MODULE_DATA_RLOCATIONPATH": "$(rlocationpath @our_other_module//other_module/pkg:data/data.txt)", + }, + deps = [ + "@our_other_module//other_module/pkg:lib", + "@rules_python//python/runfiles", + ], +) diff --git a/examples/bzlmod_build_file_generation/runfiles/data/data.txt b/examples/bzlmod_build_file_generation/runfiles/data/data.txt new file mode 100644 index 0000000000..fb17e0df66 --- /dev/null +++ b/examples/bzlmod_build_file_generation/runfiles/data/data.txt @@ -0,0 +1 @@ +Hello, example_bzlmod! diff --git a/examples/bzlmod_build_file_generation/runfiles/runfiles_test.py b/examples/bzlmod_build_file_generation/runfiles/runfiles_test.py new file mode 100644 index 0000000000..a588040cfd --- /dev/null +++ b/examples/bzlmod_build_file_generation/runfiles/runfiles_test.py @@ -0,0 +1,64 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import unittest + +from other_module.pkg import lib + +from python.runfiles import runfiles + + +class RunfilesTest(unittest.TestCase): + # """Unit tests for `runfiles.Runfiles`.""" + def testCurrentRepository(self): + self.assertEqual(runfiles.Create().CurrentRepository(), "") + + def testRunfilesWithRepoMapping(self): + data_path = runfiles.Create().Rlocation("example_bzlmod_build_file_generation/runfiles/data/data.txt") + with open(data_path) as f: + self.assertEqual(f.read().strip(), "Hello, example_bzlmod!") + + def testRunfileWithRlocationpath(self): + data_rlocationpath = os.getenv("DATA_RLOCATIONPATH") + data_path = runfiles.Create().Rlocation(data_rlocationpath) + with open(data_path) as f: + self.assertEqual(f.read().strip(), "Hello, example_bzlmod!") + + def testRunfileInOtherModuleWithOurRepoMapping(self): + data_path = runfiles.Create().Rlocation( + "our_other_module/other_module/pkg/data/data.txt" + ) + with open(data_path) as f: + self.assertEqual(f.read().strip(), "Hello, other_module!") + + def testRunfileInOtherModuleWithItsRepoMapping(self): + data_path = lib.GetRunfilePathWithRepoMapping() + with open(data_path) as f: + self.assertEqual(f.read().strip(), "Hello, other_module!") + + def testRunfileInOtherModuleWithCurrentRepository(self): + data_path = lib.GetRunfilePathWithCurrentRepository() + with open(data_path) as f: + self.assertEqual(f.read().strip(), "Hello, other_module!") + + def testRunfileInOtherModuleWithRlocationpath(self): + data_rlocationpath = os.getenv("OTHER_MODULE_DATA_RLOCATIONPATH") + data_path = runfiles.Create().Rlocation(data_rlocationpath) + with open(data_path) as f: + self.assertEqual(f.read().strip(), "Hello, other_module!") + + +if __name__ == "__main__": + unittest.main() diff --git a/gazelle/README.md b/gazelle/README.md index 2cd38764fc..e36f3a303a 100644 --- a/gazelle/README.md +++ b/gazelle/README.md @@ -15,7 +15,10 @@ without using bzlmod as your dependency manager. ## Example -We have an example of using Gazelle with Python located [here](https://github.com/bazelbuild/rules_python/tree/main/examples/build_file_generation). +We have an example of using Gazelle with Python located [here](https://github.com/bazelbuild/rules_python/tree/main/examples/bzlmod). +A fully-working example without using bzlmod is in [`examples/build_file_generation`](../examples/build_file_generation). + +The following documentation covers using bzlmod. ## Adding Gazelle to your project @@ -40,10 +43,37 @@ bazel_dep(name = "rules_python_gazelle_plugin", version = "0.20.0") # The following stanza defines the dependency rules_python. bazel_dep(name = "gazelle", version = "0.30.0", repo_name = "bazel_gazelle") -``` -You will also need to do the other usual configuration for `rules_python` in your -`MODULE.bazel` file. +# Import the python repositories generated by the given module extension into the scope of the current module. +use_repo(python, "python3_9") +use_repo(python, "python3_9_toolchains") + +# Register an already-defined toolchain so that Bazel can use it during toolchain resolution. +register_toolchains( + "@python3_9_toolchains//:all", +) + +# Use the pip extension +pip = use_extension("@rules_python//python:extensions.bzl", "pip") + +# Use the extension to call the `pip_repository` rule that invokes `pip`, with `incremental` set. +# Accepts a locked/compiled requirements file and installs the dependencies listed within. +# Those dependencies become available in a generated `requirements.bzl` file. +# You can instead check this `requirements.bzl` file into your repo. +# Because this project has different requirements for windows vs other +# operating systems, we have requirements for each. +pip.parse( + name = "pip", + # When using gazelle you must use set the following flag + # in order for the generation of gazelle dependency resolution. + incompatible_generate_aliases = True, + requirements_lock = "//:requirements_lock.txt", + requirements_windows = "//:requirements_windows.txt", +) + +# Imports the pip toolchain generated by the given module extension into the scope of the current module. +use_repo(pip, "pip") +``` Next, we'll fetch metadata about your Python dependencies, so that gazelle can determine which package a given import statement comes from. This is provided by the `modules_mapping` rule. We'll make a target for consuming this @@ -86,6 +116,9 @@ gazelle_python_manifest( # This should point to wherever we declare our python dependencies # (the same as what we passed to the modules_mapping rule in WORKSPACE) requirements = "//:requirements_lock.txt", + # NOTE: we can use this flag in order to make our setup compatible with + # bzlmod. + use_pip_repository_aliases = True, ) ``` @@ -112,8 +145,6 @@ 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. -A fully-working example is in [`examples/build_file_generation`](../examples/build_file_generation). - ## Usage Gazelle is non-destructive. diff --git a/python/extensions.bzl b/python/extensions.bzl index 2b0c188554..3bcbb5023d 100644 --- a/python/extensions.bzl +++ b/python/extensions.bzl @@ -19,18 +19,24 @@ load("@rules_python//python/pip_install:pip_repository.bzl", "locked_requirement load("@rules_python//python/pip_install:repositories.bzl", "pip_install_dependencies") load("@rules_python//python/pip_install:requirements_parser.bzl", parse_requirements = "parse") load("@rules_python//python/private:coverage_deps.bzl", "install_coverage_deps") +load("@rules_python//python/private:toolchains_repo.bzl", "get_host_os_arch", "get_host_platform") def _python_impl(module_ctx): for mod in module_ctx.modules: - for attr in mod.tags.toolchain: + for toolchain_attr in mod.tags.toolchain: python_register_toolchains( - name = attr.name, - python_version = attr.python_version, + name = toolchain_attr.name, + python_version = toolchain_attr.python_version, bzlmod = True, # Toolchain registration in bzlmod is done in MODULE file register_toolchains = False, - register_coverage_tool = attr.configure_coverage_tool, - ignore_root_user_error = attr.ignore_root_user_error, + register_coverage_tool = toolchain_attr.configure_coverage_tool, + ignore_root_user_error = toolchain_attr.ignore_root_user_error, + ) + host_hub_name = toolchain_attr.name + "_host_interpreter" + _host_hub( + name = host_hub_name, + user_repo_prefix = toolchain_attr.name, ) python = module_extension( @@ -127,3 +133,89 @@ pip = module_extension( "parse": tag_class(attrs = _pip_parse_ext_attrs()), }, ) + +# This function allows us to build the label name of a label +# that is not passed into the current context. +# The module_label is the key element that is passed in. +# This value provides the root location of the labels +# See https://bazel.build/external/extension#repository_names_and_visibility +def _repo_mapped_label(module_label, extension_name, apparent): + """Construct a canonical repo label accounting for repo mapping. + + Args: + module_label: Label object of the module hosting the extension; see + "_module" implicit attribute. + extension_name: str, name of the extension that created the repo in `apparent`. + apparent: str, a repo-qualified target string, but without the "@". e.g. + "python38_x86_linux//:python". The repo name should use the apparent + name used by the extension named by `ext_name` (i.e. the value of the + `name` arg the extension passes to repository rules) + """ + return Label("@@{module}~{extension_name}~{apparent}".format( + module = module_label.workspace_name, + extension_name = extension_name, + apparent = apparent, + )) + +# We are doing some bazel stuff here that could use an explanation. +# The basis of this function is that we need to create a symlink to +# the python binary that exists in a different repo that we know is +# setup by rules_python. +# +# We are building a Label like +# @@rules_python~override~python~python3_x86_64-unknown-linux-gnu//:python +# and then the function creates a symlink named python to that Label. +# The tricky part is the "~override~" part can't be known in advance +# and will change depending on how and what version of rules_python +# is used. To figure that part out, an implicit attribute is used to +# resolve the module's current name (see "_module" attribute) +# +# We are building the Label name dynamically, and can do this even +# though the Label is not passed into this function. If we choose +# not do this a user would have to write another 16 lines +# of configuration code, but we are able to save them that work +# because we know how rules_python works internally. We are using +# functions from private:toolchains_repo.bzl which is where the repo +# is being built. The repo name differs between host OS and platforms +# and the functions from toolchains_repo gives us this functions that +# information. +def _host_hub_impl(repo_ctx): + # Intentionally empty; this is only intended to be used by repository + # rules, which don't process build file contents. + repo_ctx.file("BUILD.bazel", "") + + # The two get_ functions we use are also utilized when building + # the repositories for the different interpreters. + (os, arch) = get_host_os_arch(repo_ctx) + host_platform = "{}_{}//:python".format( + repo_ctx.attr.user_repo_prefix, + get_host_platform(os, arch), + ) + + # the attribute is set to attr.label(default = "//:_"), which + # provides us the resolved, canonical, prefix for the module's repos. + # The extension_name "python" is determined by the + # name bound to the module_extension() call. + # We then have the OS and platform specific name of the python + # interpreter. + label = _repo_mapped_label(repo_ctx.attr._module, "python", host_platform) + + # create the symlink in order to set the interpreter for pip. + repo_ctx.symlink(label, "python") + +# We use this rule to set the pip interpreter target when using different operating +# systems with the same project +_host_hub = repository_rule( + implementation = _host_hub_impl, + local = True, + attrs = { + "user_repo_prefix": attr.string( + mandatory = True, + doc = """\ +The prefix to create the repository name. Usually the name you used when you created the +Python toolchain. +""", + ), + "_module": attr.label(default = "//:_"), + }, +) diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl index f58c2afddb..032f23f47a 100644 --- a/python/pip_install/pip_repository.bzl +++ b/python/pip_install/pip_repository.bzl @@ -559,7 +559,7 @@ of a binary found on the host's `PATH` environment variable. If no value is set If you are using a custom python interpreter built by another repository rule, use this attribute to specify its BUILD target. This allows pip_repository to invoke pip using the same interpreter as your toolchain. If set, takes precedence over -python_interpreter. +python_interpreter. An example value: "@python3_x86_64-unknown-linux-gnu//:python". """, ), "quiet": attr.bool( From 23cf6b66baed3d884c82d9b005769e22d618c967 Mon Sep 17 00:00:00 2001 From: Ignas Anikevicius Date: Fri, 5 May 2023 07:36:08 +0900 Subject: [PATCH 232/234] fix(update_deleted_packages.sh): wheels example should not be included in .bazelrc (#1207) This correctly handles the integration tests and examples that are a part of the `rules_python` workspace and should not be included in the deleted packages list. This brings the changes made to the `.bazelrc` very close to what is in `main`, but I would like to update this later once #1155 and #1205 are merged. Fixes #919. --- .../update_deleted_packages.sh | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tools/bazel_integration_test/update_deleted_packages.sh b/tools/bazel_integration_test/update_deleted_packages.sh index e21f88706a..54db02630f 100755 --- a/tools/bazel_integration_test/update_deleted_packages.sh +++ b/tools/bazel_integration_test/update_deleted_packages.sh @@ -15,6 +15,13 @@ # For integration tests, we want to be able to glob() up the sources inside a nested package # See explanation in .bazelrc +# +# This script ensures that we only delete subtrees that have something a file +# signifying a new bazel workspace, whether it be bzlmod or classic. Generic +# algorithm: +# 1. Get all directories where a WORKSPACE or MODULE.bazel exists. +# 2. For each of the directories, get all directories that contains a BUILD.bazel file. +# 3. Sort and remove duplicates. set -euxo pipefail @@ -23,5 +30,10 @@ cd $DIR # The sed -i.bak pattern is compatible between macos and linux sed -i.bak "/^[^#].*--deleted_packages/s#=.*#=$(\ - find examples/*/* tests/*/* \( -name BUILD -or -name BUILD.bazel \) | xargs -n 1 dirname | paste -sd, -\ + find examples/*/* tests/*/* \( -name WORKSPACE -or -name MODULE.bazel \) | + xargs -n 1 dirname | + xargs -n 1 -I{} find {} \( -name BUILD -or -name BUILD.bazel \) | + xargs -n 1 dirname | + sort -u | + paste -sd, -\ )#" $DIR/.bazelrc && rm .bazelrc.bak From 799e63fbc9c6dee95e07077689d7122c5736947f Mon Sep 17 00:00:00 2001 From: Daniel Wagner-Hall Date: Mon, 8 May 2023 20:37:22 +0100 Subject: [PATCH 233/234] fix: Strip trailing newline from python output (#1212) This is used to generate a path, which shouldn't have a trailing newline. --- python/pip_install/pip_repository.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/pip_install/pip_repository.bzl b/python/pip_install/pip_repository.bzl index 032f23f47a..5462f1b14d 100644 --- a/python/pip_install/pip_repository.bzl +++ b/python/pip_install/pip_repository.bzl @@ -128,7 +128,7 @@ def _get_toolchain_unix_cflags(rctx): er = rctx.execute([ rctx.path(rctx.attr.python_interpreter_target).realpath, "-c", - "import sys; print(f'{sys.version_info[0]}.{sys.version_info[1]}')", + "import sys; print(f'{sys.version_info[0]}.{sys.version_info[1]}', end='')", ]) if er.return_code != 0: fail("could not get python version from interpreter (status {}): {}".format(er.return_code, er.stderr)) From 0efcd94d0ee6e1e56b27d25469c28502282fab5b Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Mon, 8 May 2023 13:12:56 -0700 Subject: [PATCH 234/234] fix: manually ignore bazel-* directories to make using custom Bazel builds easier (#1181) Normally, Bazel will ignore its convenience symlinks, so putting them in the .bazelignore file isn't necessary. However, when `--output_user_root` is set, which is beneficial to set when using different Bazel versions (it preserves the analysis cache between versions), the symlinks aren't ignored. Putting them in the bazelignore file fixes this. --- .bazelignore | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.bazelignore b/.bazelignore index e69de29bb2..a603a7bd8a 100644 --- a/.bazelignore +++ b/.bazelignore @@ -0,0 +1,8 @@ +# Normally these are ignored, but if you're using a custom +# build of Bazel with a custom --output_user_root value, Bazel +# tries to follow the symlinks of the other builds and finds +# the WORKSPACE, BUILD, etc files and tries to build them. +bazel-rules_python +bazel-bin +bazel-out +bazel-testlogs