diff options
-rw-r--r-- | .bazelci/presubmit.yml | 34 | ||||
-rw-r--r-- | docs/pip_repository.md | 13 | ||||
-rw-r--r-- | examples/build_file_generation/BUILD.bazel | 5 | ||||
-rw-r--r-- | examples/build_file_generation/MODULE.bazel | 43 | ||||
-rw-r--r-- | examples/build_file_generation/WORKSPACE | 2 | ||||
-rw-r--r-- | examples/build_file_generation/gazelle_python.yaml | 3 | ||||
-rw-r--r-- | gazelle/MODULE.bazel | 20 | ||||
-rw-r--r-- | gazelle/deps.bzl | 57 | ||||
-rw-r--r-- | gazelle/go.mod | 2 | ||||
-rw-r--r-- | gazelle/manifest/defs.bzl | 11 | ||||
-rw-r--r-- | gazelle/manifest/generate/generate.go | 23 | ||||
-rw-r--r-- | gazelle/manifest/manifest.go | 3 | ||||
-rw-r--r-- | gazelle/python/BUILD.bazel | 1 | ||||
-rw-r--r-- | gazelle/pythonconfig/pythonconfig.go | 10 | ||||
-rw-r--r-- | python/extensions.bzl | 1 | ||||
-rw-r--r-- | python/pip_install/pip_repository.bzl | 72 |
16 files changed, 231 insertions, 69 deletions
diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index a1b16bb..a0d9a19 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 2ccdc64..c02058e 100644 --- a/docs/pip_repository.md +++ b/docs/pip_repository.md @@ -8,9 +8,10 @@ <pre> pip_repository(<a href="#pip_repository-name">name</a>, <a href="#pip_repository-annotations">annotations</a>, <a href="#pip_repository-download_only">download_only</a>, <a href="#pip_repository-enable_implicit_namespace_pkgs">enable_implicit_namespace_pkgs</a>, <a href="#pip_repository-environment">environment</a>, - <a href="#pip_repository-extra_pip_args">extra_pip_args</a>, <a href="#pip_repository-isolated">isolated</a>, <a href="#pip_repository-pip_data_exclude">pip_data_exclude</a>, <a href="#pip_repository-python_interpreter">python_interpreter</a>, - <a href="#pip_repository-python_interpreter_target">python_interpreter_target</a>, <a href="#pip_repository-quiet">quiet</a>, <a href="#pip_repository-repo_mapping">repo_mapping</a>, <a href="#pip_repository-repo_prefix">repo_prefix</a>, <a href="#pip_repository-requirements_darwin">requirements_darwin</a>, - <a href="#pip_repository-requirements_linux">requirements_linux</a>, <a href="#pip_repository-requirements_lock">requirements_lock</a>, <a href="#pip_repository-requirements_windows">requirements_windows</a>, <a href="#pip_repository-timeout">timeout</a>) + <a href="#pip_repository-extra_pip_args">extra_pip_args</a>, <a href="#pip_repository-incompatible_generate_aliases">incompatible_generate_aliases</a>, <a href="#pip_repository-isolated">isolated</a>, <a href="#pip_repository-pip_data_exclude">pip_data_exclude</a>, + <a href="#pip_repository-python_interpreter">python_interpreter</a>, <a href="#pip_repository-python_interpreter_target">python_interpreter_target</a>, <a href="#pip_repository-quiet">quiet</a>, <a href="#pip_repository-repo_mapping">repo_mapping</a>, <a href="#pip_repository-repo_prefix">repo_prefix</a>, + <a href="#pip_repository-requirements_darwin">requirements_darwin</a>, <a href="#pip_repository-requirements_linux">requirements_linux</a>, <a href="#pip_repository-requirements_lock">requirements_lock</a>, <a href="#pip_repository-requirements_windows">requirements_windows</a>, + <a href="#pip_repository-timeout">timeout</a>) </pre> A rule for importing `requirements.txt` dependencies into Bazel. @@ -64,6 +65,7 @@ py_binary( | <a id="pip_repository-enable_implicit_namespace_pkgs"></a>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 <code>legacy_create_init=False</code> or the global Bazel option <code>--incompatible_default_to_explicit_init_py</code> to prevent <code>__init__.py</code> being automatically generated in every directory.<br><br>This option is required to support some packages which cannot handle the conversion to pkg-util style. | Boolean | optional | <code>False</code> | | <a id="pip_repository-environment"></a>environment | Environment variables to set in the pip subprocess. Can be used to set common variables such as <code>http_proxy</code>, <code>https_proxy</code> and <code>no_proxy</code> Note that pip is run with "--isolated" on the CLI so <code>PIP_<VAR>_<NAME></code> style env vars are ignored, but env vars that control requests and urllib3 can be passed. | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | <code>{}</code> | | <a id="pip_repository-extra_pip_args"></a>extra_pip_args | Extra arguments to pass on to pip. Must not contain spaces. | List of strings | optional | <code>[]</code> | +| <a id="pip_repository-incompatible_generate_aliases"></a>incompatible_generate_aliases | Allow generating aliases '@pip//<pkg>' -> '@pip_<pkg>//:pkg'. | Boolean | optional | <code>False</code> | | <a id="pip_repository-isolated"></a>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 <code>RULES_PYTHON_PIP_ISOLATED</code> enviornment varaible can be used to control this flag. | Boolean | optional | <code>True</code> | | <a id="pip_repository-pip_data_exclude"></a>pip_data_exclude | Additional data exclusion parameters to add to the pip packages BUILD file. | List of strings | optional | <code>[]</code> | | <a id="pip_repository-python_interpreter"></a>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 <code>PATH</code> environment variable. If no value is set <code>python3</code> is defaulted for Unix systems and <code>python.exe</code> for Windows. | String | optional | <code>""</code> | @@ -83,8 +85,8 @@ py_binary( ## pip_repository_bzlmod <pre> -pip_repository_bzlmod(<a href="#pip_repository_bzlmod-name">name</a>, <a href="#pip_repository_bzlmod-repo_mapping">repo_mapping</a>, <a href="#pip_repository_bzlmod-requirements_darwin">requirements_darwin</a>, <a href="#pip_repository_bzlmod-requirements_linux">requirements_linux</a>, - <a href="#pip_repository_bzlmod-requirements_lock">requirements_lock</a>, <a href="#pip_repository_bzlmod-requirements_windows">requirements_windows</a>) +pip_repository_bzlmod(<a href="#pip_repository_bzlmod-name">name</a>, <a href="#pip_repository_bzlmod-incompatible_generate_aliases">incompatible_generate_aliases</a>, <a href="#pip_repository_bzlmod-repo_mapping">repo_mapping</a>, <a href="#pip_repository_bzlmod-requirements_darwin">requirements_darwin</a>, + <a href="#pip_repository_bzlmod-requirements_linux">requirements_linux</a>, <a href="#pip_repository_bzlmod-requirements_lock">requirements_lock</a>, <a href="#pip_repository_bzlmod-requirements_windows">requirements_windows</a>) </pre> 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 | | :------------- | :------------- | :------------- | :------------- | :------------- | | <a id="pip_repository_bzlmod-name"></a>name | A unique name for this repository. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | | +| <a id="pip_repository_bzlmod-incompatible_generate_aliases"></a>incompatible_generate_aliases | Allow generating aliases in '@pip//:<pkg>' -> '@pip_<pkg>//:pkg'. This replaces the aliases generated by the <code>bzlmod</code> tooling. | Boolean | optional | <code>False</code> | | <a id="pip_repository_bzlmod-repo_mapping"></a>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 <code>"@foo": "@bar"</code> declares that, for any time this repository depends on <code>@foo</code> (such as a dependency on <code>@foo//some:target</code>, it should actually resolve that dependency within globally-declared <code>@bar</code> (<code>@bar//some:target</code>). | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | required | | | <a id="pip_repository_bzlmod-requirements_darwin"></a>requirements_darwin | Override the requirements_lock attribute when the host platform is Mac OS | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> | | <a id="pip_repository_bzlmod-requirements_linux"></a>requirements_linux | Override the requirements_lock attribute when the host platform is Linux | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> | diff --git a/examples/build_file_generation/BUILD.bazel b/examples/build_file_generation/BUILD.bazel index 6419ef2..7c88d92 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 0000000..5f79fec --- /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 9f1dae8..65e0a6e 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 847d1ec..b57e9f0 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 0000000..bd63402 --- /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 3579443..26f8c66 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 6d6f033..94f19e8 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 78e0c27..05562a1 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 0f429f8..1f56e63 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 bb48264..c49951d 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 3b5ded2..ddcad27 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 a2fe7d5..ea2ae65 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 { + // @<repository_name>//<distribution_name> + lbl := label.New(distributionRepositoryName, sanitizedDistribution, sanitizedDistribution) + return lbl.String(), true + } + // @<repository_name>_<distribution_name>//: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 01f731f..75de415 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 982d853..733142b 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//:<pkg>' -> '@pip_<pkg>//: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//<pkg>' -> '@pip_<pkg>//:pkg'.", + ), "requirements_darwin": attr.label( allow_single_file = True, doc = "Override the requirements_lock attribute when the host platform is Mac OS", |