Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 14 commits into from
Apr 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
5 changes: 5 additions & 0 deletions docs/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
96 changes: 96 additions & 0 deletions docs/subpackages_doc.md
Original file line number Diff line number Diff line change
@@ -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>





5 changes: 5 additions & 0 deletions lib/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ bzl_library(
srcs = ["structs.bzl"],
)

bzl_library(
name = "subpackages",
srcs = ["subpackages.bzl"],
)

bzl_library(
name = "types",
srcs = ["types.bzl"],
Expand Down
96 changes: 96 additions & 0 deletions lib/subpackages.bzl
Original file line number Diff line number Diff line change
@@ -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,
)
3 changes: 3 additions & 0 deletions tests/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -37,6 +38,8 @@ shell_test_suite()

structs_test_suite()

subpackages_test_suite()

types_test_suite()

unittest_passing_tests_suite()
Expand Down
84 changes: 84 additions & 0 deletions tests/subpackages_tests.bzl
Original file line number Diff line number Diff line change
@@ -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)