Add subpackages module to skylib to support new bazel native.subpackages (#348)

This commit is contained in:
Kevin Kress 2022-04-04 14:56:21 -07:00 committed by GitHub
parent 2a87d4a62a
commit cc51024fc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 290 additions and 0 deletions

View File

@ -51,6 +51,7 @@ s = shell.quote(p)
* [new_sets](docs/new_sets_doc.md)
* [shell](docs/shell_doc.md)
* [structs](docs/structs_doc.md)
* [subpackages](docs/subpackages_doc.md)
* [types](docs/types_doc.md)
* [unittest](docs/unittest_doc.md)
* [versions](docs/versions_doc.md)

View File

@ -82,6 +82,11 @@ stardoc_with_diff_test(
out_label = "//docs:structs_doc.md",
)
stardoc_with_diff_test(
bzl_library_target = "//lib:subpackages",
out_label = "//docs:subpackages_doc.md",
)
stardoc_with_diff_test(
bzl_library_target = "//lib:types",
out_label = "//docs:types_doc.md",

96
docs/subpackages_doc.md Executable file
View File

@ -0,0 +1,96 @@
<!-- Generated with Stardoc: http://skydoc.bazel.build -->
Skylib module containing common functions for working with native.subpackages()
<a id="#subpackages.all"></a>
## subpackages.all
<pre>
subpackages.all(<a href="#subpackages.all-exclude">exclude</a>, <a href="#subpackages.all-allow_empty">allow_empty</a>, <a href="#subpackages.all-fully_qualified">fully_qualified</a>)
</pre>
List all direct subpackages of the current package regardless of directory depth.
The returned list contains all subpackages, but not subpackages of subpackages.
Example:
Assuming the following BUILD files exist:
BUILD
foo/BUILD
foo/sub/BUILD
bar/BUILD
baz/deep/dir/BUILD
If the current package is '//' all() will return ['//foo', '//bar',
'//baz/deep/dir']. //foo/sub is not included because it is a direct
subpackage of '//foo' not '//'
NOTE: fail()s if native.subpackages() is not supported.
**PARAMETERS**
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
| <a id="subpackages.all-exclude"></a>exclude | see native.subpackages(exclude) | <code>[]</code> |
| <a id="subpackages.all-allow_empty"></a>allow_empty | see native.subpackages(allow_empty) | <code>False</code> |
| <a id="subpackages.all-fully_qualified"></a>fully_qualified | It true return fully qualified Labels for subpackages, otherwise returns subpackage path relative to current package. | <code>True</code> |
**RETURNS**
A mutable sorted list containing all sub-packages of the current Bazel
package.
<a id="#subpackages.exists"></a>
## subpackages.exists
<pre>
subpackages.exists(<a href="#subpackages.exists-relative_path">relative_path</a>)
</pre>
Checks to see if relative_path is a direct subpackage of the current package.
Example:
BUILD
foo/BUILD
foo/sub/BUILD
If the current package is '//' (the top-level BUILD file):
subpackages.exists("foo") == True
subpackages.exists("foo/sub") == False
subpackages.exists("bar") == False
NOTE: fail()s if native.subpackages() is not supported in the current Bazel version.
**PARAMETERS**
| Name | Description | Default Value |
| :------------- | :------------- | :------------- |
| <a id="subpackages.exists-relative_path"></a>relative_path | a path to a subpackage to test, must not be an absolute Label. | none |
**RETURNS**
True if 'relative_path' is a subpackage of the current package.
<a id="#subpackages.supported"></a>
## subpackages.supported
<pre>
subpackages.supported()
</pre>

View File

@ -61,6 +61,11 @@ bzl_library(
srcs = ["structs.bzl"],
)
bzl_library(
name = "subpackages",
srcs = ["subpackages.bzl"],
)
bzl_library(
name = "types",
srcs = ["types.bzl"],

96
lib/subpackages.bzl Normal file
View File

@ -0,0 +1,96 @@
# 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.
"""Skylib module containing common functions for working with native.subpackages()
"""
_SUBPACKAGES_SUPPORTED = hasattr(native, "subpackages")
def _supported():
return _SUBPACKAGES_SUPPORTED
def _check_supported():
if not _SUBPACKAGES_SUPPORTED:
fail("native.subpackages not supported in this version of Bazel.")
def _all(exclude = [], allow_empty = False, fully_qualified = True):
"""List all direct subpackages of the current package regardless of directory depth.
The returned list contains all subpackages, but not subpackages of subpackages.
Example:
Assuming the following BUILD files exist:
BUILD
foo/BUILD
foo/sub/BUILD
bar/BUILD
baz/deep/dir/BUILD
If the current package is '//' all() will return ['//foo', '//bar',
'//baz/deep/dir']. //foo/sub is not included because it is a direct
subpackage of '//foo' not '//'
NOTE: fail()s if native.subpackages() is not supported.
Args:
exclude: see native.subpackages(exclude)
allow_empty: see native.subpackages(allow_empty)
fully_qualified: It true return fully qualified Labels for subpackages,
otherwise returns subpackage path relative to current package.
Returns:
A mutable sorted list containing all sub-packages of the current Bazel
package.
"""
_check_supported()
subs = native.subpackages(include = ["**"], exclude = exclude, allow_empty = allow_empty)
if fully_qualified:
return [_fully_qualified(s) for s in subs]
return subs
def _fully_qualified(relative_path):
return "//%s/%s" % (native.package_name(), relative_path)
def _exists(relative_path):
"""Checks to see if relative_path is a direct subpackage of the current package.
Example:
BUILD
foo/BUILD
foo/sub/BUILD
If the current package is '//' (the top-level BUILD file):
subpackages.exists("foo") == True
subpackages.exists("foo/sub") == False
subpackages.exists("bar") == False
NOTE: fail()s if native.subpackages() is not supported in the current Bazel version.
Args:
relative_path: a path to a subpackage to test, must not be an absolute Label.
Returns:
True if 'relative_path' is a subpackage of the current package.
"""
_check_supported()
return relative_path in native.subpackages(include = [relative_path], allow_empty = True)
subpackages = struct(
all = _all,
exists = _exists,
supported = _supported,
)

View File

@ -8,6 +8,7 @@ load(":paths_tests.bzl", "paths_test_suite")
load(":selects_tests.bzl", "selects_test_suite")
load(":shell_tests.bzl", "shell_args_test_gen", "shell_test_suite")
load(":structs_tests.bzl", "structs_test_suite")
load(":subpackages_tests.bzl", "subpackages_test_suite")
load(":types_tests.bzl", "types_test_suite")
load(":unittest_tests.bzl", "unittest_passing_tests_suite")
load(":versions_tests.bzl", "versions_test_suite")
@ -37,6 +38,8 @@ shell_test_suite()
structs_test_suite()
subpackages_test_suite()
types_test_suite()
unittest_passing_tests_suite()

View File

@ -0,0 +1,84 @@
# 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.
"""Unit tests for subpackages.bzl."""
load("//lib:subpackages.bzl", "subpackages")
load("//lib:unittest.bzl", "loadingtest")
def _all_test(env):
"""Unit tests for subpackages.all."""
all_pkgs = [
"copy_file",
"diff_test",
"expand_template",
"select_file",
"write_file",
]
# Not all pkgs exist in all test environments.
if subpackages.exists("run_binary"):
all_pkgs.append("run_binary")
if subpackages.exists("native_binary"):
all_pkgs.append("native_binary")
# These exist in all cases
filtered_pkgs = [
"copy_file",
"expand_template",
"select_file",
"write_file",
]
# subpackages is always in sorted order:
all_pkgs = sorted(all_pkgs)
# test defaults
loadingtest.equals(
env,
"all",
["//tests/" + pkg for pkg in all_pkgs],
subpackages.all(),
)
# test non-fully-qualified output
loadingtest.equals(
env,
"all_not_fully_qualified",
all_pkgs,
subpackages.all(fully_qualified = False),
)
# test exclusion
loadingtest.equals(
env,
"all_w_exclude",
filtered_pkgs,
subpackages.all(exclude = ["diff_test", "run_binary", "native_binary"], fully_qualified = False),
)
def _exists_test(env):
"""Unit tests for subpackages.exists."""
loadingtest.equals(env, "exists_yes", True, subpackages.exists("copy_file"))
loadingtest.equals(env, "exists_no", False, subpackages.exists("never_existed"))
def subpackages_test_suite():
"""Creates the test targets and test suite for subpackages.bzl tests."""
if subpackages.supported():
env = loadingtest.make("subpackages")
_all_test(env)
_exists_test(env)